forked from diamondburned/arikawa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevents.go
1030 lines (868 loc) · 33.5 KB
/
events.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
package gateway
import (
"errors"
"strconv"
"strings"
"github.com/diamondburned/arikawa/v3/discord"
"github.com/diamondburned/arikawa/v3/utils/json"
"github.com/diamondburned/arikawa/v3/utils/json/option"
"github.com/diamondburned/arikawa/v3/utils/ws"
)
//go:generate go run ../utils/cmd/genevent -o event_methods.go
// ReadyEventKeepRaw, if true, will make the gateway keep a copy of the raw JSON
// body that makes up the Ready event. This is useful for non-bots.
var ReadyEventKeepRaw = false
// Event is a type alias for ws.Event. It exists for convenience and describes
// the same event as any other ws.Event.
type Event ws.Event
// Rule: VOICE_STATE_UPDATE -> VoiceStateUpdateEvent.
// Ready is too big, so it's moved to ready.go.
const (
dispatchOp ws.OpCode = 0 // recv
heartbeatOp ws.OpCode = 1 // send/recv
identifyOp ws.OpCode = 2 // send...
statusUpdateOp ws.OpCode = 3 //
voiceStateUpdateOp ws.OpCode = 4 //
voiceServerPingOp ws.OpCode = 5 //
resumeOp ws.OpCode = 6 //
reconnectOp ws.OpCode = 7 // recv
requestGuildMembersOp ws.OpCode = 8 // send
invalidSessionOp ws.OpCode = 9 // recv...
helloOp ws.OpCode = 10
heartbeatAckOp ws.OpCode = 11
callConnectOp ws.OpCode = 13
guildSubscriptionsOp ws.OpCode = 14
)
// OpUnmarshalers contains the Op unmarshalers for this gateway.
var OpUnmarshalers = ws.NewOpUnmarshalers()
// HeartbeatCommand is a command for Op 1. It is the last sequence number to be
// sent.
type HeartbeatCommand int
// HeartbeatAckEvent is an event for Op 11.
type HeartbeatAckEvent struct{}
// ReconnectEvent is an event for Op 7.
type ReconnectEvent struct{}
// HelloEvent is an event for Op 10.
//
// https://discord.com/developers/docs/topics/gateway#connecting-and-resuming
type HelloEvent struct {
HeartbeatInterval discord.Milliseconds `json:"heartbeat_interval"`
}
// ResumeCommand is a command for Op 6. It describes the Resume send command.
// This is not to be confused with ResumedEvent, which is an event that Discord
// sends us.
type ResumeCommand struct {
Token string `json:"token"`
SessionID string `json:"session_id"`
Sequence int64 `json:"seq"`
}
// InvalidSessionEvent is an event for Op 9. It indicates if the event is
// resumable.
//
// https://discord.com/developers/docs/topics/gateway#connecting-and-resuming
type InvalidSessionEvent bool
// RequestGuildMembersCommand is a command for Op 8. Either UserIDs or (Query
// and Limit) must be filled.
type RequestGuildMembersCommand struct {
// GuildIDs contains the IDs of the guilds to request data from. Multiple
// guilds can only be requested when using user accounts.
//
// The guild_id JSON key is intentional, despite the type being an array.
GuildIDs []discord.GuildID `json:"guild_id"`
// UserIDs contains the IDs of the users to request data for. If this is
// filled, then the Query field must be empty.
UserIDs []discord.UserID `json:"user_ids,omitempty"`
// Query is a string to search for matching usernames. If this is filled,
// then the UserIDs field must be empty. If Query is empty, then all members
// are filled for bots.
Query option.String `json:"query,omitempty"`
// Limit is used to specify the maximum number of members to send back when
// Query is used.
Limit uint `json:"limit,omitempty"`
Presences bool `json:"presences"`
Nonce string `json:"nonce,omitempty"`
}
// MarshalJSON marshals a RequestGuildMembersCommand.
func (c *RequestGuildMembersCommand) MarshalJSON() ([]byte, error) {
type raw RequestGuildMembersCommand
if c.UserIDs != nil && c.Query != nil {
return nil, errors.New("neither UserIDs nor Query can be filled")
}
var marshaling interface{} = (*raw)(c)
if c.Query != nil {
// Force the Limit field to be present if Query is present.
marshaling = struct {
*raw
Limit uint `json:"limit"`
}{
raw: (*raw)(c),
Limit: c.Limit,
}
}
return json.Marshal(marshaling)
}
// UpdateVoiceStateCommand is a command for Op 4.
type UpdateVoiceStateCommand struct {
GuildID discord.GuildID `json:"guild_id"`
ChannelID discord.ChannelID `json:"channel_id"` // nullable
SelfMute bool `json:"self_mute"`
SelfDeaf bool `json:"self_deaf"`
}
// UpdatePresenceCommand is a command for Op 3. It is sent by this client to
// indicate a presence or status update.
type UpdatePresenceCommand struct {
Since discord.UnixMsTimestamp `json:"since"` // 0 if not idle
// Activities can be null or an empty slice.
Activities []discord.Activity `json:"activities"`
Status discord.Status `json:"status"`
AFK bool `json:"afk"`
}
// GuildSubscribeCommand is a command for Op 14. It is undocumented.
type GuildSubscribeCommand struct {
Typing bool `json:"typing"`
Threads bool `json:"threads"`
Activities bool `json:"activities"`
GuildID discord.GuildID `json:"guild_id"`
// Channels is not documented. It's used to fetch the right members sidebar.
Channels map[discord.ChannelID][][2]int `json:"channels,omitempty"`
}
// ResumedEvent is a dispatch event. It is sent by Discord whenever we've
// successfully caught up to all events after resuming.
type ResumedEvent struct{}
// ChannelCreateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#channels
type ChannelCreateEvent struct {
discord.Channel
}
// ChannelUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#channels
type ChannelUpdateEvent struct {
discord.Channel
}
// ChannelDeleteEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#channels
type ChannelDeleteEvent struct {
discord.Channel
}
// ChannelPinsUpdateEvent is a dispatch event.
type ChannelPinsUpdateEvent struct {
GuildID discord.GuildID `json:"guild_id,omitempty"`
ChannelID discord.ChannelID `json:"channel_id,omitempty"`
LastPin discord.Timestamp `json:"timestamp,omitempty"`
}
// ChannelUnreadUpdateEvent is a dispatch event.
type ChannelUnreadUpdateEvent struct {
GuildID discord.GuildID `json:"guild_id"`
ChannelUnreadUpdates []struct {
ID discord.ChannelID `json:"id"`
LastMessageID discord.MessageID `json:"last_message_id"`
}
}
// ThreadCreateEvent is a dispatch event. It is sent when a thread is created,
// relevant to the current user, or when the current user is added to a thread.
type ThreadCreateEvent struct {
discord.Channel
}
// ThreadUpdateEvent is a dispatch event. It is sent when a thread is updated.
type ThreadUpdateEvent struct {
discord.Channel
}
// ThreadDeleteEvent is a dispatch event. It is sent when a thread relevant to
// the current user is deleted.
type ThreadDeleteEvent struct {
// ID is the id of this channel.
ID discord.ChannelID `json:"id"`
// GuildID is the id of the guild.
GuildID discord.GuildID `json:"guild_id,omitempty"`
// Type is the type of channel.
Type discord.ChannelType `json:"type,omitempty"`
// ParentID is the id of the text channel this thread was created.
ParentID discord.ChannelID `json:"parent_id,omitempty"`
}
// ThreadListSyncEvent is a dispatch event. It is sent when the current user
// gains access to a channel.
type ThreadListSyncEvent struct {
// GuildID is the id of the guild.
GuildID discord.GuildID `json:"guild_id"`
// ChannelIDs are the parent channel ids whose threads are being
// synced. If nil, then threads were synced for the entire guild.
// This slice may contain ChannelIDs that have no active threads as
// well, so you know to clear that data.
ChannelIDs []discord.ChannelID `json:"channel_ids,omitempty"`
Threads []discord.Channel `json:"threads"`
Members []discord.ThreadMember `json:"members"`
}
// ThreadMemberUpdateEvent is a dispatch event. It is sent when the thread
// member object for the current user is updated.
type ThreadMemberUpdateEvent struct {
discord.ThreadMember
}
// ThreadMembersUpdateEvent is a dispatch event. It is sent when anyone is added
// to or removed from a thread. If the current user does not have the
// GUILD_MEMBERS Gateway Intent, then this event will only be sent if the
// current user was added to or removed from the thread.
type ThreadMembersUpdateEvent struct {
// ID is the id of the thread.
ID discord.ChannelID `json:"id"`
// GuildID is the id of the guild.
GuildID discord.GuildID `json:"guild_id"`
// MemberCount is the approximate number of members in the thread,
// capped at 50.
MemberCount int `json:"member_count"`
// AddedMembers are the users who were added to the thread.
AddedMembers []discord.ThreadMember `json:"added_members,omitempty"`
// RemovedUserIDs are the ids of the users who were removed from the
// thread.
RemovedMemberIDs []discord.UserID `json:"removed_member_ids,omitempty"`
}
// GuildCreateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildCreateEvent struct {
discord.Guild
Joined discord.Timestamp `json:"joined_at,omitempty"`
Large bool `json:"large,omitempty"`
Unavailable bool `json:"unavailable,omitempty"`
MemberCount uint64 `json:"member_count,omitempty"`
VoiceStates []discord.VoiceState `json:"voice_states,omitempty"`
Members []discord.Member `json:"members,omitempty"`
Channels []discord.Channel `json:"channels,omitempty"`
Threads []discord.Channel `json:"threads,omitempty"`
Presences []discord.Presence `json:"presences,omitempty"`
}
// GuildUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildUpdateEvent struct {
discord.Guild
}
// GuildDeleteEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildDeleteEvent struct {
ID discord.GuildID `json:"id"`
// Unavailable if false == removed
Unavailable bool `json:"unavailable"`
}
// GuildAuditLogEntryCreateEvent is a dispatch event.
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildAuditLogEntryCreateEvent struct {
discord.AuditLogEntry
}
// GuildBanAddEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildBanAddEvent struct {
GuildID discord.GuildID `json:"guild_id"`
User discord.User `json:"user"`
}
// GuildBanRemoveEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildBanRemoveEvent struct {
GuildID discord.GuildID `json:"guild_id"`
User discord.User `json:"user"`
}
// GuildEmojisUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildEmojisUpdateEvent struct {
GuildID discord.GuildID `json:"guild_id"`
Emojis []discord.Emoji `json:"emojis"`
}
// GuildIntegrationsUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildIntegrationsUpdateEvent struct {
GuildID discord.GuildID `json:"guild_id"`
}
// GuildMemberAddEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildMemberAddEvent struct {
discord.Member
GuildID discord.GuildID `json:"guild_id"`
}
// GuildMemberRemoveEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildMemberRemoveEvent struct {
GuildID discord.GuildID `json:"guild_id"`
User discord.User `json:"user"`
}
// GuildMemberUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildMemberUpdateEvent struct {
GuildID discord.GuildID `json:"guild_id"`
RoleIDs []discord.RoleID `json:"roles"`
User discord.User `json:"user"`
Nick string `json:"nick"`
Avatar discord.Hash `json:"avatar"`
IsPending bool `json:"pending,omitempty"`
CommunicationDisabledUntil discord.Timestamp `json:"communication_disabled_until"`
}
// UpdateMember updates the given discord.Member.
func (u *GuildMemberUpdateEvent) UpdateMember(m *discord.Member) {
m.RoleIDs = u.RoleIDs
m.User = u.User
m.Nick = u.Nick
m.Avatar = u.Avatar
m.IsPending = u.IsPending
m.CommunicationDisabledUntil = u.CommunicationDisabledUntil
}
// GuildMembersChunkEvent is a dispatch event. It is sent when the Guild Request
// Members command is sent.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildMembersChunkEvent struct {
GuildID discord.GuildID `json:"guild_id"`
Members []discord.Member `json:"members"`
ChunkIndex int `json:"chunk_index"`
ChunkCount int `json:"chunk_count"`
// Whatever's not found goes here
NotFound []string `json:"not_found,omitempty"`
// Only filled if requested
Presences []discord.Presence `json:"presences,omitempty"`
Nonce string `json:"nonce,omitempty"`
}
// GuildMemberListUpdate is a dispatch event. It is an undocumented event. It's
// received when the client sends over GuildSubscriptions with the Channels
// field used. The State package does not handle this event.
type GuildMemberListUpdate struct {
ID string `json:"id"`
GuildID discord.GuildID `json:"guild_id"`
MemberCount uint64 `json:"member_count"`
OnlineCount uint64 `json:"online_count"`
// Groups is all the visible role sections.
Groups []GuildMemberListGroup `json:"groups"`
Ops []GuildMemberListOp `json:"ops"`
}
// GuildMemberListGroup is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildMemberListGroup struct {
ID string `json:"id"` // either discord.RoleID, "online" or "offline"
Count uint64 `json:"count"`
}
// GuildMemberListOp is an entry of every operation in GuildMemberListUpdate.
type GuildMemberListOp struct {
// Mysterious string, so far spotted to be [SYNC, INSERT, UPDATE, DELETE].
Op string `json:"op"`
// NON-SYNC ONLY
// Only available for Ops that aren't "SYNC".
Index int `json:"index,omitempty"`
Item GuildMemberListOpItem `json:"item,omitempty"`
// SYNC ONLY
// Range requested in GuildSubscribeCommand.
Range [2]int `json:"range,omitempty"`
// Items is basically a linear list of roles and members, similarly to
// how the client renders it. No, it's not nested.
Items []GuildMemberListOpItem `json:"items,omitempty"`
}
// GuildMemberListOpItem is a union of either Group or Member. Refer to
// (*GuildMemberListUpdate).Ops for more.
type GuildMemberListOpItem struct {
Group *GuildMemberListGroup `json:"group,omitempty"`
Member *struct {
discord.Member
HoistedRole string `json:"hoisted_role"`
Presence discord.Presence `json:"presence"`
} `json:"member,omitempty"`
}
// GuildRoleCreateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildRoleCreateEvent struct {
GuildID discord.GuildID `json:"guild_id"`
Role discord.Role `json:"role"`
}
// GuildRoleUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildRoleUpdateEvent struct {
GuildID discord.GuildID `json:"guild_id"`
Role discord.Role `json:"role"`
}
// GuildRoleDeleteEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guilds
type GuildRoleDeleteEvent struct {
GuildID discord.GuildID `json:"guild_id"`
RoleID discord.RoleID `json:"role_id"`
}
// InviteCreateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#invites
type InviteCreateEvent struct {
Code string `json:"code"`
CreatedAt discord.Timestamp `json:"created_at"`
ChannelID discord.ChannelID `json:"channel_id"`
GuildID discord.GuildID `json:"guild_id,omitempty"`
// Similar to discord.Invite
Inviter *discord.User `json:"inviter,omitempty"`
Target *discord.User `json:"target_user,omitempty"`
TargetType discord.InviteUserType `json:"target_user_type,omitempty"`
discord.InviteMetadata
}
// InviteDeleteEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#invites
type InviteDeleteEvent struct {
Code string `json:"code"`
ChannelID discord.ChannelID `json:"channel_id"`
GuildID discord.GuildID `json:"guild_id,omitempty"`
}
// MessageCreateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#messages
type MessageCreateEvent struct {
discord.Message
Member *discord.Member `json:"member,omitempty"`
}
// MessageUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#messages
type MessageUpdateEvent struct {
discord.Message
Member *discord.Member `json:"member,omitempty"`
}
// MessageDeleteEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#messages
type MessageDeleteEvent struct {
ID discord.MessageID `json:"id"`
ChannelID discord.ChannelID `json:"channel_id"`
GuildID discord.GuildID `json:"guild_id,omitempty"`
}
// MessageDeleteBulkEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#messages
type MessageDeleteBulkEvent struct {
IDs []discord.MessageID `json:"ids"`
ChannelID discord.ChannelID `json:"channel_id"`
GuildID discord.GuildID `json:"guild_id,omitempty"`
}
// MessageReactionAddEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#messages
type MessageReactionAddEvent struct {
UserID discord.UserID `json:"user_id"`
ChannelID discord.ChannelID `json:"channel_id"`
MessageID discord.MessageID `json:"message_id"`
Emoji discord.Emoji `json:"emoji,omitempty"`
GuildID discord.GuildID `json:"guild_id,omitempty"`
Member *discord.Member `json:"member,omitempty"`
}
// MessageReactionRemoveEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#messages
type MessageReactionRemoveEvent struct {
UserID discord.UserID `json:"user_id"`
ChannelID discord.ChannelID `json:"channel_id"`
MessageID discord.MessageID `json:"message_id"`
Emoji discord.Emoji `json:"emoji"`
GuildID discord.GuildID `json:"guild_id,omitempty"`
}
// MessageReactionRemoveAllEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#messages
type MessageReactionRemoveAllEvent struct {
ChannelID discord.ChannelID `json:"channel_id"`
MessageID discord.MessageID `json:"message_id"`
GuildID discord.GuildID `json:"guild_id,omitempty"`
}
// MessageReactionRemoveEmojiEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#messages
type MessageReactionRemoveEmojiEvent struct {
ChannelID discord.ChannelID `json:"channel_id"`
MessageID discord.MessageID `json:"message_id"`
Emoji discord.Emoji `json:"emoji"`
GuildID discord.GuildID `json:"guild_id,omitempty"`
}
// MessageAckEvent is a dispatch event.
type MessageAckEvent struct {
MessageID discord.MessageID `json:"message_id"`
ChannelID discord.ChannelID `json:"channel_id"`
}
// PresenceUpdateEvent is a dispatch event. It represents the structure of the
// Presence Update Event object.
//
// https://discord.com/developers/docs/topics/gateway#presence-update-presence-update-event-fields
type PresenceUpdateEvent struct {
discord.Presence
}
// PresencesReplaceEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#presence
type PresencesReplaceEvent []PresenceUpdateEvent
// SessionsReplaceEvent is a dispatch event. It is undocumented. It's likely
// used for current user's presence updates.
type SessionsReplaceEvent []UserSession
// TypingStartEvent is a dispatch event.
type TypingStartEvent struct {
ChannelID discord.ChannelID `json:"channel_id"`
UserID discord.UserID `json:"user_id"`
Timestamp discord.UnixTimestamp `json:"timestamp"`
GuildID discord.GuildID `json:"guild_id,omitempty"`
Member *discord.Member `json:"member,omitempty"`
}
// UserUpdateEvent is a dispatch event.
type UserUpdateEvent struct {
discord.User
}
// VoiceStateUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#voice
type VoiceStateUpdateEvent struct {
discord.VoiceState
}
// VoiceServerUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#voice
type VoiceServerUpdateEvent struct {
Token string `json:"token"`
GuildID discord.GuildID `json:"guild_id"`
Endpoint string `json:"endpoint"`
}
// WebhooksUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#webhooks
type WebhooksUpdateEvent struct {
GuildID discord.GuildID `json:"guild_id"`
ChannelID discord.ChannelID `json:"channel_id"`
}
// InteractionCreateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#webhooks
type InteractionCreateEvent struct {
discord.InteractionEvent
}
// Undocumented
// UserGuildSettingsUpdateEvent is a dispatch event. It is undocumented.
type UserGuildSettingsUpdateEvent struct {
UserGuildSetting
}
// UserSettingsUpdateEvent is a dispatch event. It is undocumented.
type UserSettingsUpdateEvent struct {
UserSettings
}
// UserNoteUpdateEvent is a dispatch event. It is undocumented.
type UserNoteUpdateEvent struct {
ID discord.UserID `json:"id"`
Note string `json:"note"`
}
// RelationshipAddEvent is a dispatch event. It is undocumented.
type RelationshipAddEvent struct {
discord.Relationship
}
// RelationshipRemoveEvent is a dispatch event. It is undocumented.
type RelationshipRemoveEvent struct {
discord.Relationship
}
// ReadyEvent is a dispatch event for READY.
//
// https://discord.com/developers/docs/topics/gateway#ready
type ReadyEvent struct {
Version int `json:"v"`
User discord.User `json:"user"`
SessionID string `json:"session_id"`
PrivateChannels []discord.Channel `json:"private_channels"`
Guilds []GuildCreateEvent `json:"guilds"`
Shard *Shard `json:"shard,omitempty"`
Application struct {
ID discord.AppID `json:"id"`
Flags discord.ApplicationFlags `json:"flags"`
} `json:"application"`
// Bot users need not concern with what's in here. This field is only
// unmarshaled, not marshaled.
ReadyEventExtras `json:"-"`
}
func (r *ReadyEvent) UnmarshalJSON(b []byte) error {
type raw ReadyEvent
if err := json.Unmarshal(b, (*raw)(r)); err != nil {
return err
}
// Optionally unmarshal ReadyEventExtras.
if !r.User.Bot {
r.ExtrasDecodeErrors = json.PartialUnmarshal(b, &r.ReadyEventExtras)
}
if ReadyEventKeepRaw {
r.ReadyEventExtras.RawEventBody = append([]byte(nil), b...)
}
return nil
}
// Ready subtypes.
type (
// ReadyEventExtras contains undocumented fields pertaining to the Ready
// event. This is the only event that receives this special treatment,
// because it's the one with the most undocumented things.
ReadyEventExtras struct {
UserSettings *UserSettings `json:"user_settings,omitempty"`
ReadStates []ReadState `json:"read_state,omitempty"`
UserGuildSettings []UserGuildSetting `json:"user_guild_settings,omitempty"`
Relationships []discord.Relationship `json:"relationships,omitempty"`
Presences []discord.Presence `json:"presences,omitempty"`
Sessions []UserSession `json:"sessions,omitempty"`
SessionID string `json:"session_id,omitempty"`
FriendSuggestionCount int `json:"friend_suggestion_count,omitempty"`
GeoOrderedRTCRegions []string `json:"geo_ordered_rtc_regions,omitempty"`
// RawEventBody is the raw JSON body for the Ready event. It is only
// available if ReadyEventKeepRaw is true.
RawEventBody json.Raw
// ExtrasDecodeErrors will be non-nil if there were errors decoding the
// ReadyEventExtras.
ExtrasDecodeErrors []error
}
// ReadState is a single ReadState entry. It is undocumented.
ReadState struct {
ChannelID discord.ChannelID `json:"id"`
LastMessageID discord.MessageID `json:"last_message_id"`
LastPinTimestamp discord.Timestamp `json:"last_pin_timestamp"`
MentionCount int `json:"mention_count"`
}
UserSession struct {
Status discord.Status `json:"status"`
SessionID string `json:"session_id"`
Activities []discord.Activity `json:"activities"`
ClientInfo struct {
Version int `json:"version"`
OS string `json:"os"`
Client string `json:"client"`
} `json:"client_info"`
Active bool `json:"active,omitempty"`
}
// UserSettings is the struct for (almost) all user settings. It is
// undocumented.
UserSettings struct {
ShowCurrentGame bool `json:"show_current_game"`
DefaultGuildsRestricted bool `json:"default_guilds_restricted"`
InlineAttachmentMedia bool `json:"inline_attachment_media"`
InlineEmbedMedia bool `json:"inline_embed_media"`
GIFAutoPlay bool `json:"gif_auto_play"`
RenderEmbeds bool `json:"render_embeds"`
RenderReactions bool `json:"render_reactions"`
AnimateEmoji bool `json:"animate_emoji"`
AnimateStickers int `json:"animate_stickers"`
EnableTTSCommand bool `json:"enable_tts_command"`
MessageDisplayCompact bool `json:"message_display_compact"`
ConvertEmoticons bool `json:"convert_emoticons"`
ExplicitContentFilter uint8 `json:"explicit_content_filter"` // ???
DisableGamesTab bool `json:"disable_games_tab"`
DeveloperMode bool `json:"developer_mode"`
DetectPlatformAccounts bool `json:"detect_platform_accounts"`
StreamNotification bool `json:"stream_notification_enabled"`
AccessibilityDetection bool `json:"allow_accessibility_detection"`
ContactSync bool `json:"contact_sync_enabled"`
NativePhoneIntegration bool `json:"native_phone_integration_enabled"`
TimezoneOffset int `json:"timezone_offset"`
Locale string `json:"locale"`
Theme string `json:"theme"`
GuildPositions []discord.GuildID `json:"guild_positions"`
GuildFolders []GuildFolder `json:"guild_folders"`
RestrictedGuilds []discord.GuildID `json:"restricted_guilds"`
FriendSourceFlags FriendSourceFlags `json:"friend_source_flags"`
Status discord.Status `json:"status"`
CustomStatus *CustomUserStatus `json:"custom_status"`
}
// CustomUserStatus is the custom user status that allows setting an emoji
// and a piece of text on each user.
CustomUserStatus struct {
Text string `json:"text"`
ExpiresAt discord.Timestamp `json:"expires_at,omitempty"`
EmojiID discord.EmojiID `json:"emoji_id,string"`
EmojiName string `json:"emoji_name"`
}
// UserGuildSetting stores the settings for a single guild. It is
// undocumented.
UserGuildSetting struct {
GuildID discord.GuildID `json:"guild_id"`
SuppressRoles bool `json:"suppress_roles"`
SuppressEveryone bool `json:"suppress_everyone"`
Muted bool `json:"muted"`
MuteConfig *UserMuteConfig `json:"mute_config"`
MobilePush bool `json:"mobile_push"`
Notifications UserNotification `json:"message_notifications"`
ChannelOverrides []UserChannelOverride `json:"channel_overrides"`
}
// A UserChannelOverride struct describes a channel settings override for a
// users guild settings.
UserChannelOverride struct {
Muted bool `json:"muted"`
MuteConfig *UserMuteConfig `json:"mute_config"`
Notifications UserNotification `json:"message_notifications"`
ChannelID discord.ChannelID `json:"channel_id"`
}
// UserMuteConfig seems to describe the mute settings. It belongs to the
// UserGuildSettingEntry and UserChannelOverride structs and is
// undocumented.
UserMuteConfig struct {
SelectedTimeWindow int `json:"selected_time_window"`
EndTime discord.Timestamp `json:"end_time"`
}
// GuildFolder holds a single folder that you see in the left guild panel.
GuildFolder struct {
Name string `json:"name"`
ID GuildFolderID `json:"id"`
GuildIDs []discord.GuildID `json:"guild_ids"`
Color discord.Color `json:"color"`
}
// FriendSourceFlags describes sources that friend requests could be sent
// from. It belongs to the UserSettings struct and is undocumented.
FriendSourceFlags struct {
All bool `json:"all,omitempty"`
MutualGuilds bool `json:"mutual_guilds,omitempty"`
MutualFriends bool `json:"mutual_friends,omitempty"`
}
)
// UserNotification is the notification setting for a channel or guild.
type UserNotification uint8
const (
AllNotifications UserNotification = iota
OnlyMentions
NoNotifications
GuildDefaults
)
// GuildFolderID is possibly a snowflake. It can also be 0 (null) or a low
// number of unknown significance.
type GuildFolderID int64
func (g *GuildFolderID) UnmarshalJSON(b []byte) error {
var body = string(b)
if body == "null" {
return nil
}
body = strings.Trim(body, `"`)
u, err := strconv.ParseInt(body, 10, 64)
if err != nil {
return err
}
*g = GuildFolderID(u)
return nil
}
func (g GuildFolderID) MarshalJSON() ([]byte, error) {
if g == 0 {
return []byte("null"), nil
}
return []byte(strconv.FormatInt(int64(g), 10)), nil
}
// ReadySupplementalEvent is a dispatch event for READY_SUPPLEMENTAL. It is an
// undocumented event. For now, this event is never used, and its usage have yet
// been discovered.
type ReadySupplementalEvent struct {
Guilds []GuildCreateEvent `json:"guilds"` // only have ID and VoiceStates
MergedMembers [][]SupplementalMember `json:"merged_members"`
MergedPresences MergedPresences `json:"merged_presences"`
}
// ReadySupplemental event structs.
type (
// SupplementalMember is the struct for a member in the MergedMembers field
// of ReadySupplementalEvent. It has slight differences to discord.Member.
SupplementalMember struct {
UserID discord.UserID `json:"user_id"`
Nick string `json:"nick,omitempty"`
RoleIDs []discord.RoleID `json:"roles"`
GuildID discord.GuildID `json:"guild_id,omitempty"`
IsPending bool `json:"pending,omitempty"`
HoistedRole discord.RoleID `json:"hoisted_role"`
Mute bool `json:"mute"`
Deaf bool `json:"deaf"`
// Joined specifies when the user joined the guild.
Joined discord.Timestamp `json:"joined_at"`
// BoostedSince specifies when the user started boosting the guild.
BoostedSince discord.Timestamp `json:"premium_since,omitempty"`
}
// MergedPresences is the struct for presences of guilds' members and
// friends. It is undocumented.
MergedPresences struct {
Guilds [][]SupplementalPresence `json:"guilds"`
Friends []SupplementalPresence `json:"friends"`
}
// SupplementalPresence is a single presence for either a guild member or
// friend. It is used in MergedPresences and is undocumented.
SupplementalPresence struct {
UserID discord.UserID `json:"user_id"`
// Status is either "idle", "dnd", "online", or "offline".
Status discord.Status `json:"status"`
// Activities are the user's current activities.
Activities []discord.Activity `json:"activities"`
// ClientStaus is the user's platform-dependent status.
ClientStatus discord.ClientStatus `json:"client_status"`
// LastModified is only present in Friends.
LastModified discord.UnixMsTimestamp `json:"last_modified,omitempty"`
}
)
// ConvertSupplementalMembers converts a SupplementalMember to a regular Member.
func ConvertSupplementalMembers(sms []SupplementalMember) []discord.Member {
members := make([]discord.Member, len(sms))
for i, sm := range sms {
members[i] = discord.Member{
User: discord.User{ID: sm.UserID},
Nick: sm.Nick,
RoleIDs: sm.RoleIDs,
Joined: sm.Joined,
BoostedSince: sm.BoostedSince,
Deaf: sm.Deaf,
Mute: sm.Mute,
IsPending: sm.IsPending,
}
}
return members
}
// ConvertSupplementalPresences converts a SupplementalPresence to a regular
// Presence with an empty GuildID.
func ConvertSupplementalPresences(sps []SupplementalPresence) []discord.Presence {
presences := make([]discord.Presence, len(sps))
for i, sp := range sps {
presences[i] = discord.Presence{
User: discord.User{ID: sp.UserID},
Status: sp.Status,
Activities: sp.Activities,
ClientStatus: sp.ClientStatus,
}
}
return presences
}
// GuildScheduledEventCreateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guild-scheduled-event-create
type GuildScheduledEventCreateEvent struct {
discord.GuildScheduledEvent
}
// GuildScheduledEventUpdateEvent is a dispatch event.
//
// https://discord.com/developers/docs/topics/gateway#guild-scheduled-event-update
type GuildScheduledEventUpdateEvent struct {
discord.GuildScheduledEvent
}