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
|
#pragma once
#include "chatsubmitparams.hpp"
#include "waiter.hpp"
#include "httpclient.hpp"
#include "objects.hpp"
#include "store.hpp"
#include "voiceclient.hpp"
#include "websocket.hpp"
#include <sigc++/sigc++.h>
#include <nlohmann/json.hpp>
#include <thread>
#include <map>
#include <set>
#include <mutex>
#include <zlib.h>
#include <glibmm.h>
#include <queue>
#ifdef GetMessage
#undef GetMessage
#endif
class Abaddon;
class DiscordClient {
friend class Abaddon;
public:
DiscordClient(bool mem_store = false);
void Start();
bool Stop();
bool IsStarted() const;
bool IsStoreValid() const;
std::unordered_set<Snowflake> GetGuilds() const;
const UserData &GetUserData() const;
const UserGuildSettingsData &GetUserGuildSettings() const;
std::optional<UserGuildSettingsEntry> GetSettingsForGuild(Snowflake id) const;
std::vector<Snowflake> GetUserSortedGuilds() const;
std::vector<Message> GetMessagesForChannel(Snowflake id, size_t limit = 50) const;
std::vector<Message> GetMessagesBefore(Snowflake channel_id, Snowflake message_id, size_t limit = 50) const;
std::set<Snowflake> GetPrivateChannels() const;
const UserSettings &GetUserSettings() const;
EPremiumType GetSelfPremiumType() const;
void FetchMessagesInChannel(Snowflake id, const sigc::slot<void(const std::vector<Message> &)> &cb);
void FetchMessagesInChannelBefore(Snowflake channel_id, Snowflake before_id, const sigc::slot<void(const std::vector<Message> &)> &cb);
std::optional<Message> GetMessage(Snowflake id) const;
std::optional<ChannelData> GetChannel(Snowflake id) const;
std::optional<EmojiData> GetEmoji(Snowflake id) const;
std::optional<PermissionOverwrite> GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const;
std::optional<UserData> GetUser(Snowflake id) const;
std::optional<RoleData> GetRole(Snowflake id) const;
std::optional<GuildData> GetGuild(Snowflake id) const;
std::optional<GuildMember> GetMember(Snowflake user_id, Snowflake guild_id) const;
Snowflake GetMemberHoistedRole(Snowflake guild_id, Snowflake user_id, bool with_color = false) const;
std::optional<RoleData> GetMemberHighestRole(Snowflake guild_id, Snowflake user_id) const;
std::set<Snowflake> GetUsersInGuild(Snowflake id) const;
std::set<Snowflake> GetChannelsInGuild(Snowflake id) const;
std::vector<Snowflake> GetUsersInThread(Snowflake id) const;
std::vector<ChannelData> GetActiveThreads(Snowflake channel_id) const;
void GetArchivedPublicThreads(Snowflake channel_id, const sigc::slot<void(DiscordError, const ArchivedThreadsResponseData &)> &callback);
void GetArchivedPrivateThreads(Snowflake channel_id, const sigc::slot<void(DiscordError, const ArchivedThreadsResponseData &)> &callback);
std::vector<Snowflake> GetChildChannelIDs(Snowflake parent_id) const;
// get ids of given list of members for who we do not have the member data
template<typename Iter>
std::unordered_set<Snowflake> FilterUnknownMembersFrom(Snowflake guild_id, Iter begin, Iter end) {
std::unordered_set<Snowflake> ret;
const auto known = m_store.GetMembersInGuild(guild_id);
for (auto iter = begin; iter != end; iter++)
if (known.find(*iter) == known.end())
ret.insert(*iter);
return ret;
}
bool IsThreadJoined(Snowflake thread_id) const;
bool HasGuildPermission(Snowflake user_id, Snowflake guild_id, Permission perm) const;
bool HasSelfChannelPermission(Snowflake channel_id, Permission perm) const;
bool HasAnyChannelPermission(Snowflake user_id, Snowflake channel_id, Permission perm) const;
bool HasChannelPermission(Snowflake user_id, Snowflake channel_id, Permission perm) const;
Permission ComputePermissions(Snowflake member_id, Snowflake guild_id) const;
Permission ComputeOverwrites(Permission base, Snowflake member_id, Snowflake channel_id) const;
bool CanManageMember(Snowflake guild_id, Snowflake actor, Snowflake target) const; // kick, ban, edit nickname (cant think of a better name)
void ChatMessageCallback(const std::string &nonce, const http::response_type &response, const sigc::slot<void(DiscordError code)> &callback);
void SendChatMessageNoAttachments(const ChatSubmitParams ¶ms, const sigc::slot<void(DiscordError code)> &callback);
void SendChatMessageAttachments(const ChatSubmitParams ¶ms, const sigc::slot<void(DiscordError code)> &callback);
void SendChatMessage(const ChatSubmitParams ¶ms, const sigc::slot<void(DiscordError code)> &callback);
void DeleteMessage(Snowflake channel_id, Snowflake id);
void EditMessage(Snowflake channel_id, Snowflake id, std::string content);
void SendLazyLoad(Snowflake id);
void SendThreadLazyLoad(Snowflake id);
void LeaveGuild(Snowflake id);
void KickUser(Snowflake user_id, Snowflake guild_id);
void BanUser(Snowflake user_id, Snowflake guild_id); // todo: reason, delete messages
void UpdateStatus(PresenceStatus status, bool is_afk);
void UpdateStatus(PresenceStatus status, bool is_afk, const ActivityData &obj);
void CloseDM(Snowflake channel_id);
std::optional<Snowflake> FindDM(Snowflake user_id); // wont find group dms
void AddReaction(Snowflake id, Glib::ustring param);
void RemoveReaction(Snowflake id, Glib::ustring param);
void SetGuildName(Snowflake id, const Glib::ustring &name, const sigc::slot<void(DiscordError code)> &callback);
void SetGuildIcon(Snowflake id, const std::string &data, const sigc::slot<void(DiscordError code)> &callback);
void UnbanUser(Snowflake guild_id, Snowflake user_id, const sigc::slot<void(DiscordError code)> &callback);
void DeleteInvite(const std::string &code, const sigc::slot<void(DiscordError code)> &callback);
void AddGroupDMRecipient(Snowflake channel_id, Snowflake user_id);
void RemoveGroupDMRecipient(Snowflake channel_id, Snowflake user_id);
void ModifyRolePermissions(Snowflake guild_id, Snowflake role_id, Permission permissions, const sigc::slot<void(DiscordError code)> &callback);
void ModifyRoleName(Snowflake guild_id, Snowflake role_id, const Glib::ustring &name, const sigc::slot<void(DiscordError code)> &callback);
void ModifyRoleColor(Snowflake guild_id, Snowflake role_id, uint32_t color, const sigc::slot<void(DiscordError code)> &callback);
void ModifyRoleColor(Snowflake guild_id, Snowflake role_id, const Gdk::RGBA &color, const sigc::slot<void(DiscordError code)> &callback);
void ModifyRolePosition(Snowflake guild_id, Snowflake role_id, int position, const sigc::slot<void(DiscordError code)> &callback);
void ModifyEmojiName(Snowflake guild_id, Snowflake emoji_id, const Glib::ustring &name, const sigc::slot<void(DiscordError code)> &callback);
void DeleteEmoji(Snowflake guild_id, Snowflake emoji_id, const sigc::slot<void(DiscordError code)> &callback);
void RemoveRelationship(Snowflake id, const sigc::slot<void(DiscordError code)> &callback);
void SendFriendRequest(const Glib::ustring &username, int discriminator, const sigc::slot<void(DiscordError code)> &callback);
void PutRelationship(Snowflake id, const sigc::slot<void(DiscordError code)> &callback); // send fr by id, accept incoming
void Pin(Snowflake channel_id, Snowflake message_id, const sigc::slot<void(DiscordError code)> &callback);
void Unpin(Snowflake channel_id, Snowflake message_id, const sigc::slot<void(DiscordError code)> &callback);
void LeaveThread(Snowflake channel_id, const std::string &location, const sigc::slot<void(DiscordError code)> &callback);
void ArchiveThread(Snowflake channel_id, const sigc::slot<void(DiscordError code)> &callback);
void UnArchiveThread(Snowflake channel_id, const sigc::slot<void(DiscordError code)> &callback);
void MarkChannelAsRead(Snowflake channel_id, const sigc::slot<void(DiscordError code)> &callback);
void MarkGuildAsRead(Snowflake guild_id, const sigc::slot<void(DiscordError code)> &callback);
void MuteChannel(Snowflake channel_id, const sigc::slot<void(DiscordError code)> &callback);
void UnmuteChannel(Snowflake channel_id, const sigc::slot<void(DiscordError code)> &callback);
void MuteGuild(Snowflake id, const sigc::slot<void(DiscordError code)> &callback);
void UnmuteGuild(Snowflake id, const sigc::slot<void(DiscordError code)> &callback);
void MuteThread(Snowflake id, const sigc::slot<void(DiscordError code)> &callback);
void UnmuteThread(Snowflake id, const sigc::slot<void(DiscordError code)> &callback);
bool CanModifyRole(Snowflake guild_id, Snowflake role_id) const;
bool CanModifyRole(Snowflake guild_id, Snowflake role_id, Snowflake user_id) const;
// send op 8 to get member data for unknown members
template<typename Iter>
void RequestMembers(Snowflake guild_id, Iter begin, Iter end) {
if (std::distance(begin, end) == 0) return;
RequestGuildMembersMessage obj;
obj.GuildID = guild_id;
obj.Presences = false;
obj.UserIDs = { begin, end };
m_websocket.Send(obj);
}
// real client doesn't seem to use the single role endpoints so neither do we
template<typename Iter>
auto SetMemberRoles(Snowflake guild_id, Snowflake user_id, Iter begin, Iter end, const sigc::slot<void(DiscordError code)> &callback) {
ModifyGuildMemberObject obj;
obj.Roles = { begin, end };
m_http.MakePATCH("/guilds/" + std::to_string(guild_id) + "/members/" + std::to_string(user_id), nlohmann::json(obj).dump(), [this, callback](const http::response_type &response) {
if (CheckCode(response))
callback(DiscordError::NONE);
else
callback(GetCodeFromResponse(response));
});
}
// FetchGuildBans fetches all bans+reasons via api, this func fetches stored bans (so usually just GUILD_BAN_ADD data)
std::vector<BanData> GetBansInGuild(Snowflake guild_id);
void FetchGuildBan(Snowflake guild_id, Snowflake user_id, const sigc::slot<void(BanData)> &callback);
void FetchGuildBans(Snowflake guild_id, const sigc::slot<void(std::vector<BanData>)> &callback);
void FetchInvite(const std::string &code, const sigc::slot<void(std::optional<InviteData>)> &callback);
void FetchGuildInvites(Snowflake guild_id, const sigc::slot<void(std::vector<InviteData>)> &callback);
void FetchAuditLog(Snowflake guild_id, const sigc::slot<void(AuditLogData)> &callback);
void FetchGuildEmojis(Snowflake guild_id, const sigc::slot<void(std::vector<EmojiData>)> &callback);
void FetchUserProfile(Snowflake user_id, const sigc::slot<void(UserProfileData)> &callback);
void FetchUserNote(Snowflake user_id, const sigc::slot<void(std::string note)> &callback);
void SetUserNote(Snowflake user_id, std::string note, const sigc::slot<void(DiscordError code)> &callback);
void FetchUserRelationships(Snowflake user_id, const sigc::slot<void(std::vector<UserData>)> &callback);
void FetchPinned(Snowflake id, const sigc::slot<void(std::vector<Message>, DiscordError code)> &callback);
bool IsVerificationRequired(Snowflake guild_id) const;
void GetVerificationGateInfo(Snowflake guild_id, const sigc::slot<void(std::optional<VerificationGateInfoObject>)> &callback);
void AcceptVerificationGate(Snowflake guild_id, VerificationGateInfoObject info, const sigc::slot<void(DiscordError code)> &callback);
#ifdef WITH_VOICE
void ConnectToVoice(Snowflake channel_id);
void DisconnectFromVoice();
// Is fully connected
[[nodiscard]] bool IsVoiceConnected() const noexcept;
[[nodiscard]] bool IsVoiceConnecting() const noexcept;
[[nodiscard]] Snowflake GetVoiceChannelID() const noexcept;
[[nodiscard]] std::unordered_set<Snowflake> GetUsersInVoiceChannel(Snowflake channel_id);
[[nodiscard]] std::optional<uint32_t> GetSSRCOfUser(Snowflake id) const;
[[nodiscard]] std::optional<Snowflake> GetVoiceState(Snowflake user_id) const;
DiscordVoiceClient &GetVoiceClient();
void SetVoiceMuted(bool is_mute);
void SetVoiceDeafened(bool is_deaf);
#endif
void SetReferringChannel(Snowflake id);
void SetBuildNumber(uint32_t build_number);
void SetCookie(std::string_view cookie);
void UpdateToken(const std::string &token);
void SetUserAgent(const std::string &agent);
void SetDumpReady(bool dump);
bool IsChannelMuted(Snowflake id) const noexcept;
bool IsGuildMuted(Snowflake id) const noexcept;
int GetUnreadStateForChannel(Snowflake id) const noexcept;
bool GetUnreadStateForGuild(Snowflake id, int &total_mentions) const noexcept;
int GetUnreadDMsCount() const;
PresenceStatus GetUserStatus(Snowflake id) const;
std::map<Snowflake, RelationshipType> GetRelationships() const;
std::set<Snowflake> GetRelationships(RelationshipType type) const;
std::optional<RelationshipType> GetRelationship(Snowflake id) const;
private:
static const constexpr int InflateChunkSize = 0x10000;
std::vector<uint8_t> m_compressed_buf;
std::vector<uint8_t> m_decompress_buf;
z_stream m_zstream;
bool m_dump_ready = false;
static std::string GetAPIURL();
static std::string GetGatewayURL();
static DiscordError GetCodeFromResponse(const http::response_type &response);
void ProcessNewGuild(GuildData &guild);
void HandleGatewayMessageRaw(std::string str);
void HandleGatewayMessage(std::string str);
void HandleGatewayHello(const GatewayMessage &msg);
void HandleGatewayReady(const GatewayMessage &msg);
void HandleGatewayMessageCreate(const GatewayMessage &msg);
void HandleGatewayMessageDelete(const GatewayMessage &msg);
void HandleGatewayMessageUpdate(const GatewayMessage &msg);
void HandleGatewayGuildMemberListUpdate(const GatewayMessage &msg);
void HandleGatewayGuildCreate(const GatewayMessage &msg);
void HandleGatewayGuildDelete(const GatewayMessage &msg);
void HandleGatewayMessageDeleteBulk(const GatewayMessage &msg);
void HandleGatewayGuildMemberUpdate(const GatewayMessage &msg);
void HandleGatewayPresenceUpdate(const GatewayMessage &msg);
void HandleGatewayChannelDelete(const GatewayMessage &msg);
void HandleGatewayChannelUpdate(const GatewayMessage &msg);
void HandleGatewayChannelCreate(const GatewayMessage &msg);
void HandleGatewayGuildUpdate(const GatewayMessage &msg);
void HandleGatewayGuildRoleUpdate(const GatewayMessage &msg);
void HandleGatewayGuildRoleCreate(const GatewayMessage &msg);
void HandleGatewayGuildRoleDelete(const GatewayMessage &msg);
void HandleGatewayMessageReactionAdd(const GatewayMessage &msg);
void HandleGatewayMessageReactionRemove(const GatewayMessage &msg);
void HandleGatewayChannelRecipientAdd(const GatewayMessage &msg);
void HandleGatewayChannelRecipientRemove(const GatewayMessage &msg);
void HandleGatewayTypingStart(const GatewayMessage &msg);
void HandleGatewayGuildBanRemove(const GatewayMessage &msg);
void HandleGatewayGuildBanAdd(const GatewayMessage &msg);
void HandleGatewayInviteCreate(const GatewayMessage &msg);
void HandleGatewayInviteDelete(const GatewayMessage &msg);
void HandleGatewayUserNoteUpdate(const GatewayMessage &msg);
void HandleGatewayGuildEmojisUpdate(const GatewayMessage &msg);
void HandleGatewayGuildJoinRequestCreate(const GatewayMessage &msg);
void HandleGatewayGuildJoinRequestUpdate(const GatewayMessage &msg);
void HandleGatewayGuildJoinRequestDelete(const GatewayMessage &msg);
void HandleGatewayRelationshipRemove(const GatewayMessage &msg);
void HandleGatewayRelationshipAdd(const GatewayMessage &msg);
void HandleGatewayThreadCreate(const GatewayMessage &msg);
void HandleGatewayThreadDelete(const GatewayMessage &msg);
void HandleGatewayThreadListSync(const GatewayMessage &msg);
void HandleGatewayThreadMembersUpdate(const GatewayMessage &msg);
void HandleGatewayThreadMemberUpdate(const GatewayMessage &msg);
void HandleGatewayThreadUpdate(const GatewayMessage &msg);
void HandleGatewayThreadMemberListUpdate(const GatewayMessage &msg);
void HandleGatewayMessageAck(const GatewayMessage &msg);
void HandleGatewayUserGuildSettingsUpdate(const GatewayMessage &msg);
void HandleGatewayGuildMembersChunk(const GatewayMessage &msg);
void HandleGatewayReadySupplemental(const GatewayMessage &msg);
void HandleGatewayReconnect(const GatewayMessage &msg);
void HandleGatewayInvalidSession(const GatewayMessage &msg);
#ifdef WITH_VOICE
void HandleGatewayVoiceStateUpdate(const GatewayMessage &msg);
void HandleGatewayVoiceServerUpdate(const GatewayMessage &msg);
#endif
void HeartbeatThread();
void SendIdentify();
void SendResume();
void SetHeaders();
void SetSuperPropertiesFromIdentity(const IdentifyMessage &identity);
void HandleSocketOpen();
void HandleSocketClose(const ix::WebSocketCloseInfo &info);
static bool CheckCode(const http::response_type &r);
static bool CheckCode(const http::response_type &r, int expected);
void StoreMessageData(Message &msg);
void HandleReadyReadState(const ReadyEventData &data);
void HandleReadyGuildSettings(const ReadyEventData &data);
std::string m_token;
uint32_t m_build_number = 142000;
void AddUserToGuild(Snowflake user_id, Snowflake guild_id);
std::map<Snowflake, std::set<Snowflake>> m_guild_to_users;
std::map<Snowflake, std::set<Snowflake>> m_guild_to_channels;
std::map<Snowflake, GuildApplicationData> m_guild_join_requests;
std::map<Snowflake, PresenceStatus> m_user_to_status;
std::map<Snowflake, RelationshipType> m_user_relationships;
std::set<Snowflake> m_joined_threads;
std::map<Snowflake, std::vector<Snowflake>> m_thread_members;
std::map<Snowflake, Snowflake> m_last_message_id;
std::unordered_set<Snowflake> m_muted_guilds;
std::unordered_set<Snowflake> m_muted_channels;
std::unordered_map<Snowflake, int> m_unread;
std::unordered_set<Snowflake> m_channel_muted_parent;
UserData m_user_data;
UserSettings m_user_settings;
UserGuildSettingsData m_user_guild_settings;
Store m_store;
HTTPClient m_http;
Websocket m_websocket;
std::atomic<bool> m_client_connected = false;
std::atomic<bool> m_ready_received = false;
bool m_client_started = false;
std::map<std::string, GatewayEvent> m_event_map;
void LoadEventMap();
std::thread m_heartbeat_thread;
std::atomic<int> m_last_sequence = -1;
std::atomic<int> m_heartbeat_msec = 0;
Waiter m_heartbeat_waiter;
std::atomic<bool> m_heartbeat_acked = true;
bool m_reconnecting = false; // reconnecting either to resume or reidentify
bool m_wants_resume = false; // reconnecting specifically to resume
std::string m_session_id;
#ifdef WITH_VOICE
DiscordVoiceClient m_voice;
bool m_mute_requested = false;
bool m_deaf_requested = false;
Snowflake m_voice_channel_id;
// todo sql i guess
std::unordered_map<Snowflake, Snowflake> m_voice_state_user_channel;
std::unordered_map<Snowflake, std::unordered_set<Snowflake>> m_voice_state_channel_users;
void SendVoiceStateUpdate();
void SetVoiceState(Snowflake user_id, Snowflake channel_id);
void ClearVoiceState(Snowflake user_id);
void OnVoiceConnected();
void OnVoiceDisconnected();
#endif
mutable std::mutex m_msg_mutex;
Glib::Dispatcher m_msg_dispatch;
std::queue<std::string> m_msg_queue;
void MessageDispatch();
mutable std::mutex m_generic_mutex;
Glib::Dispatcher m_generic_dispatch;
std::queue<std::function<void()>> m_generic_queue;
Glib::Timer m_progress_cb_timer;
std::set<Snowflake> m_channels_pinned_requested;
std::set<Snowflake> m_channels_lazy_loaded;
// signals
public:
typedef sigc::signal<void> type_signal_gateway_ready;
typedef sigc::signal<void> type_signal_gateway_ready_supplemental;
typedef sigc::signal<void, Message> type_signal_message_create;
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_message_delete;
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_message_update;
typedef sigc::signal<void, Snowflake> type_signal_guild_member_list_update;
typedef sigc::signal<void, GuildData> type_signal_guild_create;
typedef sigc::signal<void, Snowflake> type_signal_guild_delete;
typedef sigc::signal<void, Snowflake> type_signal_channel_delete;
typedef sigc::signal<void, Snowflake> type_signal_channel_update;
typedef sigc::signal<void, ChannelData> type_signal_channel_create;
typedef sigc::signal<void, Snowflake> type_signal_guild_update;
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_role_update; // guild id, role id
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_role_create; // guild id, role id
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_role_delete; // guild id, role id
typedef sigc::signal<void, Snowflake, Glib::ustring> type_signal_reaction_add;
typedef sigc::signal<void, Snowflake, Glib::ustring> type_signal_reaction_remove;
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_typing_start; // user id, channel id
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_guild_member_update; // guild id, user id
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_guild_ban_remove; // guild id, user id
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_guild_ban_add; // guild id, user id
typedef sigc::signal<void, InviteData> type_signal_invite_create;
typedef sigc::signal<void, InviteDeleteObject> type_signal_invite_delete;
typedef sigc::signal<void, UserData, PresenceStatus> type_signal_presence_update;
typedef sigc::signal<void, Snowflake, std::string> type_signal_note_update;
typedef sigc::signal<void, Snowflake, std::vector<EmojiData>> type_signal_guild_emojis_update; // guild id
typedef sigc::signal<void, GuildJoinRequestCreateData> type_signal_guild_join_request_create;
typedef sigc::signal<void, GuildJoinRequestUpdateData> type_signal_guild_join_request_update;
typedef sigc::signal<void, GuildJoinRequestDeleteData> type_signal_guild_join_request_delete;
typedef sigc::signal<void, Snowflake, RelationshipType> type_signal_relationship_remove;
typedef sigc::signal<void, RelationshipAddData> type_signal_relationship_add;
typedef sigc::signal<void, ChannelData> type_signal_thread_create;
typedef sigc::signal<void, ThreadDeleteData> type_signal_thread_delete;
typedef sigc::signal<void, ThreadListSyncData> type_signal_thread_list_sync;
typedef sigc::signal<void, ThreadMembersUpdateData> type_signal_thread_members_update;
typedef sigc::signal<void, ThreadUpdateData> type_signal_thread_update;
typedef sigc::signal<void, ThreadMemberListUpdateData> type_signal_thread_member_list_update;
typedef sigc::signal<void, MessageAckData> type_signal_message_ack;
typedef sigc::signal<void, GuildMembersChunkData> type_signal_guild_members_chunk;
// not discord dispatch events
typedef sigc::signal<void, Snowflake> type_signal_added_to_thread;
typedef sigc::signal<void, Snowflake> type_signal_removed_from_thread;
typedef sigc::signal<void, Message> type_signal_message_unpinned;
typedef sigc::signal<void, Message> type_signal_message_pinned;
typedef sigc::signal<void, Message> type_signal_message_sent;
typedef sigc::signal<void, Snowflake> type_signal_channel_muted;
typedef sigc::signal<void, Snowflake> type_signal_channel_unmuted;
typedef sigc::signal<void, Snowflake> type_signal_guild_muted;
typedef sigc::signal<void, Snowflake> type_signal_guild_unmuted;
typedef sigc::signal<void, Snowflake, bool> type_signal_channel_accessibility_changed;
typedef sigc::signal<void, std::string /* nonce */, float /* retry_after */> type_signal_message_send_fail; // retry after param will be 0 if it failed for a reason that isnt slowmode
typedef sigc::signal<void, bool, GatewayCloseCode> type_signal_disconnected; // bool true if reconnecting
typedef sigc::signal<void> type_signal_connected;
typedef sigc::signal<void, std::string, float> type_signal_message_progress;
#ifdef WITH_VOICE
using type_signal_voice_connected = sigc::signal<void()>;
using type_signal_voice_disconnected = sigc::signal<void()>;
using type_signal_voice_speaking = sigc::signal<void(VoiceSpeakingData)>;
using type_signal_voice_user_disconnect = sigc::signal<void(Snowflake, Snowflake)>;
using type_signal_voice_user_connect = sigc::signal<void(Snowflake, Snowflake)>;
using type_signal_voice_requested_connect = sigc::signal<void(Snowflake)>;
using type_signal_voice_requested_disconnect = sigc::signal<void()>;
using type_signal_voice_client_state_update = sigc::signal<void(DiscordVoiceClient::State)>;
using type_signal_voice_channel_changed = sigc::signal<void(Snowflake)>;
#endif
type_signal_gateway_ready signal_gateway_ready();
type_signal_gateway_ready_supplemental signal_gateway_ready_supplemental();
type_signal_message_create signal_message_create();
type_signal_message_delete signal_message_delete();
type_signal_message_update signal_message_update();
type_signal_guild_member_list_update signal_guild_member_list_update();
type_signal_guild_create signal_guild_create(); // structs are complete in this signal
type_signal_guild_delete signal_guild_delete();
type_signal_channel_delete signal_channel_delete();
type_signal_channel_update signal_channel_update();
type_signal_channel_create signal_channel_create();
type_signal_guild_update signal_guild_update();
type_signal_role_update signal_role_update();
type_signal_role_create signal_role_create();
type_signal_role_delete signal_role_delete();
type_signal_reaction_add signal_reaction_add();
type_signal_reaction_remove signal_reaction_remove();
type_signal_typing_start signal_typing_start();
type_signal_guild_member_update signal_guild_member_update();
type_signal_guild_ban_remove signal_guild_ban_remove();
type_signal_guild_ban_add signal_guild_ban_add();
type_signal_invite_create signal_invite_create();
type_signal_invite_delete signal_invite_delete(); // safe to assume guild id is set
type_signal_presence_update signal_presence_update();
type_signal_note_update signal_note_update();
type_signal_guild_emojis_update signal_guild_emojis_update();
type_signal_guild_join_request_create signal_guild_join_request_create();
type_signal_guild_join_request_update signal_guild_join_request_update();
type_signal_guild_join_request_delete signal_guild_join_request_delete();
type_signal_relationship_remove signal_relationship_remove();
type_signal_relationship_add signal_relationship_add();
type_signal_message_unpinned signal_message_unpinned();
type_signal_message_pinned signal_message_pinned();
type_signal_thread_create signal_thread_create();
type_signal_thread_delete signal_thread_delete();
type_signal_thread_list_sync signal_thread_list_sync();
type_signal_thread_members_update signal_thread_members_update();
type_signal_thread_update signal_thread_update();
type_signal_thread_member_list_update signal_thread_member_list_update();
type_signal_message_ack signal_message_ack();
type_signal_guild_members_chunk signal_guild_members_chunk();
type_signal_added_to_thread signal_added_to_thread();
type_signal_removed_from_thread signal_removed_from_thread();
type_signal_message_sent signal_message_sent();
type_signal_channel_muted signal_channel_muted();
type_signal_channel_unmuted signal_channel_unmuted();
type_signal_guild_muted signal_guild_muted();
type_signal_guild_unmuted signal_guild_unmuted();
type_signal_channel_accessibility_changed signal_channel_accessibility_changed();
type_signal_message_send_fail signal_message_send_fail();
type_signal_disconnected signal_disconnected();
type_signal_connected signal_connected();
type_signal_message_progress signal_message_progress();
#ifdef WITH_VOICE
type_signal_voice_connected signal_voice_connected();
type_signal_voice_disconnected signal_voice_disconnected();
type_signal_voice_speaking signal_voice_speaking();
type_signal_voice_user_disconnect signal_voice_user_disconnect();
type_signal_voice_user_connect signal_voice_user_connect();
type_signal_voice_requested_connect signal_voice_requested_connect();
type_signal_voice_requested_disconnect signal_voice_requested_disconnect();
type_signal_voice_client_state_update signal_voice_client_state_update();
type_signal_voice_channel_changed signal_voice_channel_changed();
#endif
protected:
type_signal_gateway_ready m_signal_gateway_ready;
type_signal_gateway_ready_supplemental m_signal_gateway_ready_supplemental;
type_signal_message_create m_signal_message_create;
type_signal_message_delete m_signal_message_delete;
type_signal_message_update m_signal_message_update;
type_signal_guild_member_list_update m_signal_guild_member_list_update;
type_signal_guild_create m_signal_guild_create;
type_signal_guild_delete m_signal_guild_delete;
type_signal_channel_delete m_signal_channel_delete;
type_signal_channel_update m_signal_channel_update;
type_signal_channel_create m_signal_channel_create;
type_signal_guild_update m_signal_guild_update;
type_signal_role_update m_signal_role_update;
type_signal_role_create m_signal_role_create;
type_signal_role_delete m_signal_role_delete;
type_signal_reaction_add m_signal_reaction_add;
type_signal_reaction_remove m_signal_reaction_remove;
type_signal_typing_start m_signal_typing_start;
type_signal_guild_member_update m_signal_guild_member_update;
type_signal_guild_ban_remove m_signal_guild_ban_remove;
type_signal_guild_ban_add m_signal_guild_ban_add;
type_signal_invite_create m_signal_invite_create;
type_signal_invite_delete m_signal_invite_delete;
type_signal_presence_update m_signal_presence_update;
type_signal_note_update m_signal_note_update;
type_signal_guild_emojis_update m_signal_guild_emojis_update;
type_signal_guild_join_request_create m_signal_guild_join_request_create;
type_signal_guild_join_request_update m_signal_guild_join_request_update;
type_signal_guild_join_request_delete m_signal_guild_join_request_delete;
type_signal_relationship_remove m_signal_relationship_remove;
type_signal_relationship_add m_signal_relationship_add;
type_signal_message_unpinned m_signal_message_unpinned;
type_signal_message_pinned m_signal_message_pinned;
type_signal_thread_create m_signal_thread_create;
type_signal_thread_delete m_signal_thread_delete;
type_signal_thread_list_sync m_signal_thread_list_sync;
type_signal_thread_members_update m_signal_thread_members_update;
type_signal_thread_update m_signal_thread_update;
type_signal_thread_member_list_update m_signal_thread_member_list_update;
type_signal_message_ack m_signal_message_ack;
type_signal_guild_members_chunk m_signal_guild_members_chunk;
type_signal_removed_from_thread m_signal_removed_from_thread;
type_signal_added_to_thread m_signal_added_to_thread;
type_signal_message_sent m_signal_message_sent;
type_signal_channel_muted m_signal_channel_muted;
type_signal_channel_unmuted m_signal_channel_unmuted;
type_signal_guild_muted m_signal_guild_muted;
type_signal_guild_unmuted m_signal_guild_unmuted;
type_signal_channel_accessibility_changed m_signal_channel_accessibility_changed;
type_signal_message_send_fail m_signal_message_send_fail;
type_signal_disconnected m_signal_disconnected;
type_signal_connected m_signal_connected;
type_signal_message_progress m_signal_message_progress;
#ifdef WITH_VOICE
type_signal_voice_connected m_signal_voice_connected;
type_signal_voice_disconnected m_signal_voice_disconnected;
type_signal_voice_speaking m_signal_voice_speaking;
type_signal_voice_user_disconnect m_signal_voice_user_disconnect;
type_signal_voice_user_connect m_signal_voice_user_connect;
type_signal_voice_requested_connect m_signal_voice_requested_connect;
type_signal_voice_requested_disconnect m_signal_voice_requested_disconnect;
type_signal_voice_client_state_update m_signal_voice_client_state_update;
type_signal_voice_channel_changed m_signal_voice_channel_changed;
#endif
};
|