#pragma once #include "chatsubmitparams.hpp" #include "waiter.hpp" #include "httpclient.hpp" #include "objects.hpp" #include "store.hpp" #include "voiceclient.hpp" #include "websocket.hpp" #include #include #include #include #include #include #include #include #include #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 GetGuilds() const; const UserData &GetUserData() const; std::vector GetUserSortedGuilds() const; std::vector GetMessagesForChannel(Snowflake id, size_t limit = 50) const; std::vector GetMessagesBefore(Snowflake channel_id, Snowflake message_id, size_t limit = 50) const; std::set GetPrivateChannels() const; const UserSettings &GetUserSettings() const; EPremiumType GetSelfPremiumType() const; void FetchMessagesInChannel(Snowflake id, const sigc::slot &)> &cb); void FetchMessagesInChannelBefore(Snowflake channel_id, Snowflake before_id, const sigc::slot &)> &cb); std::optional GetMessage(Snowflake id) const; std::optional GetChannel(Snowflake id) const; std::optional GetEmoji(Snowflake id) const; std::optional GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const; std::optional GetUser(Snowflake id) const; std::optional GetRole(Snowflake id) const; std::optional GetGuild(Snowflake id) const; std::optional GetMember(Snowflake user_id, Snowflake guild_id) const; Snowflake GetMemberHoistedRole(Snowflake guild_id, Snowflake user_id, bool with_color = false) const; std::optional GetMemberHighestRole(Snowflake guild_id, Snowflake user_id) const; std::set GetUsersInGuild(Snowflake id) const; std::set GetChannelsInGuild(Snowflake id) const; std::vector GetUsersInThread(Snowflake id) const; std::vector GetActiveThreads(Snowflake channel_id) const; void GetArchivedPublicThreads(Snowflake channel_id, const sigc::slot &callback); void GetArchivedPrivateThreads(Snowflake channel_id, const sigc::slot &callback); std::vector GetChildChannelIDs(Snowflake parent_id) const; // get ids of given list of members for who we do not have the member data template std::unordered_set FilterUnknownMembersFrom(Snowflake guild_id, Iter begin, Iter end) { std::unordered_set 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 &callback); void SendChatMessageNoAttachments(const ChatSubmitParams ¶ms, const sigc::slot &callback); void SendChatMessageAttachments(const ChatSubmitParams ¶ms, const sigc::slot &callback); void SendChatMessage(const ChatSubmitParams ¶ms, const sigc::slot &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 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 &callback); void SetGuildIcon(Snowflake id, const std::string &data, const sigc::slot &callback); void UnbanUser(Snowflake guild_id, Snowflake user_id, const sigc::slot &callback); void DeleteInvite(const std::string &code, const sigc::slot &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 &callback); void ModifyRoleName(Snowflake guild_id, Snowflake role_id, const Glib::ustring &name, const sigc::slot &callback); void ModifyRoleColor(Snowflake guild_id, Snowflake role_id, uint32_t color, const sigc::slot &callback); void ModifyRoleColor(Snowflake guild_id, Snowflake role_id, const Gdk::RGBA &color, const sigc::slot &callback); void ModifyRolePosition(Snowflake guild_id, Snowflake role_id, int position, const sigc::slot &callback); void ModifyEmojiName(Snowflake guild_id, Snowflake emoji_id, const Glib::ustring &name, const sigc::slot &callback); void DeleteEmoji(Snowflake guild_id, Snowflake emoji_id, const sigc::slot &callback); void RemoveRelationship(Snowflake id, const sigc::slot &callback); void SendFriendRequest(const Glib::ustring &username, int discriminator, const sigc::slot &callback); void PutRelationship(Snowflake id, const sigc::slot &callback); // send fr by id, accept incoming void Pin(Snowflake channel_id, Snowflake message_id, const sigc::slot &callback); void Unpin(Snowflake channel_id, Snowflake message_id, const sigc::slot &callback); void LeaveThread(Snowflake channel_id, const std::string &location, const sigc::slot &callback); void ArchiveThread(Snowflake channel_id, const sigc::slot &callback); void UnArchiveThread(Snowflake channel_id, const sigc::slot &callback); void MarkChannelAsRead(Snowflake channel_id, const sigc::slot &callback); void MarkGuildAsRead(Snowflake guild_id, const sigc::slot &callback); void MuteChannel(Snowflake channel_id, const sigc::slot &callback); void UnmuteChannel(Snowflake channel_id, const sigc::slot &callback); void MuteGuild(Snowflake id, const sigc::slot &callback); void UnmuteGuild(Snowflake id, const sigc::slot &callback); void MuteThread(Snowflake id, const sigc::slot &callback); void UnmuteThread(Snowflake id, const sigc::slot &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 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 auto SetMemberRoles(Snowflake guild_id, Snowflake user_id, Iter begin, Iter end, const sigc::slot &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 GetBansInGuild(Snowflake guild_id); void FetchGuildBan(Snowflake guild_id, Snowflake user_id, const sigc::slot &callback); void FetchGuildBans(Snowflake guild_id, const sigc::slot)> &callback); void FetchInvite(const std::string &code, const sigc::slot)> &callback); void FetchGuildInvites(Snowflake guild_id, const sigc::slot)> &callback); void FetchAuditLog(Snowflake guild_id, const sigc::slot &callback); void FetchGuildEmojis(Snowflake guild_id, const sigc::slot)> &callback); void FetchUserProfile(Snowflake user_id, const sigc::slot &callback); void FetchUserNote(Snowflake user_id, const sigc::slot &callback); void SetUserNote(Snowflake user_id, std::string note, const sigc::slot &callback); void FetchUserRelationships(Snowflake user_id, const sigc::slot)> &callback); void FetchPinned(Snowflake id, const sigc::slot, DiscordError code)> &callback); bool IsVerificationRequired(Snowflake guild_id) const; void GetVerificationGateInfo(Snowflake guild_id, const sigc::slot)> &callback); void AcceptVerificationGate(Snowflake guild_id, VerificationGateInfoObject info, const sigc::slot &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 GetUsersInVoiceChannel(Snowflake channel_id); [[nodiscard]] std::optional GetSSRCOfUser(Snowflake id) const; [[nodiscard]] std::optional 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 GetRelationships() const; std::set GetRelationships(RelationshipType type) const; std::optional GetRelationship(Snowflake id) const; private: static const constexpr int InflateChunkSize = 0x10000; std::vector m_compressed_buf; std::vector 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> m_guild_to_users; std::map> m_guild_to_channels; std::map m_guild_join_requests; std::map m_user_to_status; std::map m_user_relationships; std::set m_joined_threads; std::map> m_thread_members; std::map m_last_message_id; std::unordered_set m_muted_guilds; std::unordered_set m_muted_channels; std::unordered_map m_unread; std::unordered_set m_channel_muted_parent; UserData m_user_data; UserSettings m_user_settings; Store m_store; HTTPClient m_http; Websocket m_websocket; std::atomic m_client_connected = false; std::atomic m_ready_received = false; bool m_client_started = false; std::map m_event_map; void LoadEventMap(); std::thread m_heartbeat_thread; std::atomic m_last_sequence = -1; std::atomic m_heartbeat_msec = 0; Waiter m_heartbeat_waiter; std::atomic 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 m_voice_state_user_channel; std::unordered_map> 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 m_msg_queue; void MessageDispatch(); mutable std::mutex m_generic_mutex; Glib::Dispatcher m_generic_dispatch; std::queue> m_generic_queue; Glib::Timer m_progress_cb_timer; std::set m_channels_pinned_requested; std::set m_channels_lazy_loaded; // signals public: typedef sigc::signal type_signal_gateway_ready; typedef sigc::signal type_signal_gateway_ready_supplemental; typedef sigc::signal type_signal_message_create; typedef sigc::signal type_signal_message_delete; typedef sigc::signal type_signal_message_update; typedef sigc::signal type_signal_guild_member_list_update; typedef sigc::signal type_signal_guild_create; typedef sigc::signal type_signal_guild_delete; typedef sigc::signal type_signal_channel_delete; typedef sigc::signal type_signal_channel_update; typedef sigc::signal type_signal_channel_create; typedef sigc::signal type_signal_guild_update; typedef sigc::signal type_signal_role_update; // guild id, role id typedef sigc::signal type_signal_role_create; // guild id, role id typedef sigc::signal type_signal_role_delete; // guild id, role id typedef sigc::signal type_signal_reaction_add; typedef sigc::signal type_signal_reaction_remove; typedef sigc::signal type_signal_typing_start; // user id, channel id typedef sigc::signal type_signal_guild_member_update; // guild id, user id typedef sigc::signal type_signal_guild_ban_remove; // guild id, user id typedef sigc::signal type_signal_guild_ban_add; // guild id, user id typedef sigc::signal type_signal_invite_create; typedef sigc::signal type_signal_invite_delete; typedef sigc::signal type_signal_presence_update; typedef sigc::signal type_signal_note_update; typedef sigc::signal> type_signal_guild_emojis_update; // guild id typedef sigc::signal type_signal_guild_join_request_create; typedef sigc::signal type_signal_guild_join_request_update; typedef sigc::signal type_signal_guild_join_request_delete; typedef sigc::signal type_signal_relationship_remove; typedef sigc::signal type_signal_relationship_add; typedef sigc::signal type_signal_thread_create; typedef sigc::signal type_signal_thread_delete; typedef sigc::signal type_signal_thread_list_sync; typedef sigc::signal type_signal_thread_members_update; typedef sigc::signal type_signal_thread_update; typedef sigc::signal type_signal_thread_member_list_update; typedef sigc::signal type_signal_message_ack; typedef sigc::signal type_signal_guild_members_chunk; // not discord dispatch events typedef sigc::signal type_signal_added_to_thread; typedef sigc::signal type_signal_removed_from_thread; typedef sigc::signal type_signal_message_unpinned; typedef sigc::signal type_signal_message_pinned; typedef sigc::signal type_signal_message_sent; typedef sigc::signal type_signal_channel_muted; typedef sigc::signal type_signal_channel_unmuted; typedef sigc::signal type_signal_guild_muted; typedef sigc::signal type_signal_guild_unmuted; typedef sigc::signal type_signal_channel_accessibility_changed; typedef sigc::signal type_signal_message_send_fail; // retry after param will be 0 if it failed for a reason that isnt slowmode typedef sigc::signal type_signal_disconnected; // bool true if reconnecting typedef sigc::signal type_signal_connected; typedef sigc::signal type_signal_message_progress; #ifdef WITH_VOICE using type_signal_voice_connected = sigc::signal; using type_signal_voice_disconnected = sigc::signal; using type_signal_voice_speaking = sigc::signal; using type_signal_voice_user_disconnect = sigc::signal; using type_signal_voice_user_connect = sigc::signal; using type_signal_voice_requested_connect = sigc::signal; using type_signal_voice_requested_disconnect = sigc::signal; using type_signal_voice_client_state_update = sigc::signal; #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(); #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; #endif };