diff options
Diffstat (limited to 'src/discord')
-rw-r--r-- | src/discord/discord.cpp | 97 | ||||
-rw-r--r-- | src/discord/discord.hpp | 47 | ||||
-rw-r--r-- | src/discord/store.cpp | 12 | ||||
-rw-r--r-- | src/discord/store.hpp | 2 | ||||
-rw-r--r-- | src/discord/user.cpp | 60 | ||||
-rw-r--r-- | src/discord/user.hpp | 3 |
6 files changed, 122 insertions, 99 deletions
diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index c54583a..8f88a91 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -351,7 +351,9 @@ void DiscordClient::GetArchivedPrivateThreads(Snowflake channel_id, const sigc:: } std::vector<Snowflake> DiscordClient::GetChildChannelIDs(Snowflake parent_id) const { - return m_store.GetChannelIDsWithParentID(parent_id); + std::vector<Snowflake> ids; + for (auto [id, type] : m_store.GetChannelIDsWithParentID(parent_id)) ids.push_back(id); + return ids; } std::optional<WebhookMessageData> DiscordClient::GetWebhookMessageData(Snowflake message_id) const { @@ -1290,21 +1292,10 @@ Snowflake DiscordClient::GetVoiceChannelID() const noexcept { return m_voice_channel_id; } -std::unordered_set<Snowflake> DiscordClient::GetUsersInVoiceChannel(Snowflake channel_id) { - return m_voice_state_channel_users[channel_id]; -} - std::optional<uint32_t> DiscordClient::GetSSRCOfUser(Snowflake id) const { return m_voice.GetSSRCOfUser(id); } -std::optional<std::pair<Snowflake, PackedVoiceState>> DiscordClient::GetVoiceState(Snowflake user_id) const { - if (const auto it = m_voice_states.find(user_id); it != m_voice_states.end()) { - return it->second; - } - return std::nullopt; -} - bool DiscordClient::IsUserSpeaker(Snowflake user_id) const { const auto state = GetVoiceState(user_id); return state.has_value() && state->second.IsSpeaker(); @@ -1325,6 +1316,17 @@ void DiscordClient::SetVoiceDeafened(bool is_deaf) { } #endif +std::optional<std::pair<Snowflake, PackedVoiceState>> DiscordClient::GetVoiceState(Snowflake user_id) const { + if (const auto it = m_voice_states.find(user_id); it != m_voice_states.end()) { + return it->second; + } + return std::nullopt; +} + +std::unordered_set<Snowflake> DiscordClient::GetUsersInVoiceChannel(Snowflake channel_id) { + return m_voice_state_channel_users[channel_id]; +} + void DiscordClient::SetReferringChannel(Snowflake id) { if (!id.IsValid()) { m_http.SetPersistentHeader("Referer", "https://discord.com/channels/@me"); @@ -1384,7 +1386,8 @@ int DiscordClient::GetUnreadStateForChannel(Snowflake id) const noexcept { int DiscordClient::GetUnreadChannelsCountForCategory(Snowflake id) const noexcept { int result = 0; - for (Snowflake channel_id : m_store.GetChannelIDsWithParentID(id)) { + for (auto [channel_id, channel_type] : m_store.GetChannelIDsWithParentID(id)) { + if (!ShouldChannelTypeCountInUnread(channel_type)) continue; if (IsChannelMuted(channel_id)) continue; const auto iter = m_unread.find(channel_id); if (iter == m_unread.end()) continue; @@ -1406,6 +1409,9 @@ bool DiscordClient::GetUnreadStateForGuild(Snowflake id, int &total_mentions) co if (const auto iter = m_channel_muted_parent.find(channel_id); iter != m_channel_muted_parent.end()) continue; + const auto channel = GetChannel(channel_id); + if (channel.has_value() && !ShouldChannelTypeCountInUnread(channel->Type)) continue; + if (!has_any_unread && channel_unread > -1 && !IsChannelMuted(channel_id)) has_any_unread = true; } @@ -1668,10 +1674,10 @@ void DiscordClient::HandleGatewayMessage(std::string str) { case GatewayEvent::STAGE_INSTANCE_DELETE: { HandleGatewayStageInstanceDelete(m); } break; -#ifdef WITH_VOICE case GatewayEvent::VOICE_STATE_UPDATE: { HandleGatewayVoiceStateUpdate(m); } break; +#ifdef WITH_VOICE case GatewayEvent::VOICE_SERVER_UPDATE: { HandleGatewayVoiceServerUpdate(m); } break; @@ -2383,12 +2389,6 @@ void DiscordClient::HandleGatewayStageInstanceDelete(const GatewayMessage &msg) * */ -void DiscordClient::HandleGatewayVoiceStateUpdate(const GatewayMessage &msg) { - spdlog::get("discord")->trace("VOICE_STATE_UPDATE"); - - CheckVoiceState(msg.Data); -} - void DiscordClient::HandleGatewayVoiceServerUpdate(const GatewayMessage &msg) { spdlog::get("discord")->trace("VOICE_SERVER_UPDATE"); @@ -2418,8 +2418,17 @@ void DiscordClient::HandleGatewayCallCreate(const GatewayMessage &msg) { } } +#endif + +void DiscordClient::HandleGatewayVoiceStateUpdate(const GatewayMessage &msg) { + spdlog::get("discord")->trace("VOICE_STATE_UPDATE"); + + CheckVoiceState(msg.Data); +} + void DiscordClient::CheckVoiceState(const VoiceState &data) { if (data.UserID == m_user_data.ID) { +#ifdef WITH_VOICE spdlog::get("discord")->debug("Voice session ID: {}", data.SessionID); m_voice.SetSessionID(data.SessionID); @@ -2430,6 +2439,7 @@ void DiscordClient::CheckVoiceState(const VoiceState &data) { m_voice_channel_id = *data.ChannelID; m_signal_voice_channel_changed.emit(m_voice_channel_id); } +#endif } else { if (data.GuildID.has_value() && data.Member.has_value()) { if (data.Member->User.has_value()) { @@ -2461,7 +2471,6 @@ void DiscordClient::CheckVoiceState(const VoiceState &data) { } } } -#endif void DiscordClient::HandleGatewayReadySupplemental(const GatewayMessage &msg) { ReadySupplementalData data = msg.Data; @@ -2811,6 +2820,14 @@ bool DiscordClient::CheckCode(const http::response_type &r, int expected) { return true; } +bool DiscordClient::ShouldChannelTypeCountInUnread(ChannelType type) { + return type != ChannelType::GUILD_VOICE && + type != ChannelType::GUILD_FORUM && + type != ChannelType::GUILD_MEDIA && + type != ChannelType::GUILD_STORE && + type != ChannelType::GUILD_DIRECTORY; +} + void DiscordClient::StoreMessageData(Message &msg) { const auto chan = m_store.GetChannel(msg.ChannelID); if (chan.has_value() && chan->GuildID.has_value()) @@ -2973,6 +2990,15 @@ void DiscordClient::SendVoiceStateUpdate() { m_websocket.Send(msg); } +void DiscordClient::OnVoiceConnected() { + m_signal_voice_connected.emit(); +} + +void DiscordClient::OnVoiceDisconnected() { + m_signal_voice_disconnected.emit(); +} +#endif + void DiscordClient::SetVoiceState(Snowflake user_id, const VoiceState &state) { if (!state.ChannelID.has_value()) { spdlog::get("discord")->error("SetVoiceState called with missing channel ID"); @@ -3003,15 +3029,6 @@ void DiscordClient::ClearVoiceState(Snowflake user_id) { } } -void DiscordClient::OnVoiceConnected() { - m_signal_voice_connected.emit(); -} - -void DiscordClient::OnVoiceDisconnected() { - m_signal_voice_disconnected.emit(); -} -#endif - void DiscordClient::LoadEventMap() { m_event_map["READY"] = GatewayEvent::READY; m_event_map["MESSAGE_CREATE"] = GatewayEvent::MESSAGE_CREATE; @@ -3302,14 +3319,6 @@ DiscordClient::type_signal_voice_speaking DiscordClient::signal_voice_speaking() return m_signal_voice_speaking; } -DiscordClient::type_signal_voice_user_disconnect DiscordClient::signal_voice_user_disconnect() { - return m_signal_voice_user_disconnect; -} - -DiscordClient::type_signal_voice_user_connect DiscordClient::signal_voice_user_connect() { - return m_signal_voice_user_connect; -} - DiscordClient::type_signal_voice_requested_connect DiscordClient::signal_voice_requested_connect() { return m_signal_voice_requested_connect; } @@ -3325,6 +3334,15 @@ DiscordClient::type_signal_voice_client_state_update DiscordClient::signal_voice DiscordClient::type_signal_voice_channel_changed DiscordClient::signal_voice_channel_changed() { return m_signal_voice_channel_changed; } +#endif + +DiscordClient::type_signal_voice_user_disconnect DiscordClient::signal_voice_user_disconnect() { + return m_signal_voice_user_disconnect; +} + +DiscordClient::type_signal_voice_user_connect DiscordClient::signal_voice_user_connect() { + return m_signal_voice_user_connect; +} DiscordClient::type_signal_voice_state_set DiscordClient::signal_voice_state_set() { return m_signal_voice_state_set; @@ -3332,5 +3350,4 @@ DiscordClient::type_signal_voice_state_set DiscordClient::signal_voice_state_set DiscordClient::type_signal_voice_speaker_state_changed DiscordClient::signal_voice_speaker_state_changed() { return m_signal_voice_speaker_state_changed; -} -#endif +}
\ No newline at end of file diff --git a/src/discord/discord.hpp b/src/discord/discord.hpp index eca25a6..ab051aa 100644 --- a/src/discord/discord.hpp +++ b/src/discord/discord.hpp @@ -201,9 +201,7 @@ public: [[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<std::pair<Snowflake, PackedVoiceState>> GetVoiceState(Snowflake user_id) const; [[nodiscard]] bool IsUserSpeaker(Snowflake user_id) const; DiscordVoiceClient &GetVoiceClient(); @@ -212,6 +210,9 @@ public: void SetVoiceDeafened(bool is_deaf); #endif + [[nodiscard]] std::optional<std::pair<Snowflake, PackedVoiceState>> GetVoiceState(Snowflake user_id) const; + [[nodiscard]] std::unordered_set<Snowflake> GetUsersInVoiceChannel(Snowflake channel_id); + void SetReferringChannel(Snowflake id); void SetBuildNumber(uint32_t build_number); @@ -304,13 +305,13 @@ private: void HandleGatewayInvalidSession(const GatewayMessage &msg); #ifdef WITH_VOICE - void - HandleGatewayVoiceStateUpdate(const GatewayMessage &msg); void HandleGatewayVoiceServerUpdate(const GatewayMessage &msg); void HandleGatewayCallCreate(const GatewayMessage &msg); +#endif + + void HandleGatewayVoiceStateUpdate(const GatewayMessage &msg); void CheckVoiceState(const VoiceState &data); -#endif void HeartbeatThread(); void SendIdentify(); @@ -327,6 +328,8 @@ private: void StoreMessageData(Message &msg); + static bool ShouldChannelTypeCountInUnread(ChannelType type); + void HandleReadyReadState(const ReadyEventData &data); void HandleReadyGuildSettings(const ReadyEventData &data); @@ -381,19 +384,20 @@ private: bool m_deaf_requested = false; Snowflake m_voice_channel_id; - // todo sql i guess - std::unordered_map<Snowflake, std::pair<Snowflake, PackedVoiceState>> m_voice_states; - std::unordered_map<Snowflake, std::unordered_set<Snowflake>> m_voice_state_channel_users; void SendVoiceStateUpdate(); - void SetVoiceState(Snowflake user_id, const VoiceState &state); - void ClearVoiceState(Snowflake user_id); - void OnVoiceConnected(); void OnVoiceDisconnected(); #endif + void SetVoiceState(Snowflake user_id, const VoiceState &state); + void ClearVoiceState(Snowflake user_id); + + // todo sql i guess + std::unordered_map<Snowflake, std::pair<Snowflake, PackedVoiceState>> m_voice_states; + std::unordered_map<Snowflake, std::unordered_set<Snowflake>> m_voice_state_channel_users; + mutable std::mutex m_msg_mutex; Glib::Dispatcher m_msg_dispatch; std::queue<std::string> m_msg_queue; @@ -474,15 +478,16 @@ public: 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 + + 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_state_set = sigc::signal<void(Snowflake, Snowflake, VoiceStateFlags)>; using type_signal_voice_speaker_state_changed = sigc::signal<void(Snowflake /* channel_id */, Snowflake /* user_id */, bool /* is_speaker */)>; -#endif type_signal_gateway_ready signal_gateway_ready(); type_signal_gateway_ready_supplemental signal_gateway_ready_supplemental(); @@ -546,15 +551,16 @@ public: 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 + + type_signal_voice_user_disconnect signal_voice_user_disconnect(); + type_signal_voice_user_connect signal_voice_user_connect(); type_signal_voice_state_set signal_voice_state_set(); type_signal_voice_speaker_state_changed signal_voice_speaker_state_changed(); -#endif protected: type_signal_gateway_ready m_signal_gateway_ready; @@ -619,13 +625,14 @@ protected: 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 + + type_signal_voice_user_disconnect m_signal_voice_user_disconnect; + type_signal_voice_user_connect m_signal_voice_user_connect; type_signal_voice_state_set m_signal_voice_state_set; type_signal_voice_speaker_state_changed m_signal_voice_speaker_state_changed; -#endif }; diff --git a/src/discord/store.cpp b/src/discord/store.cpp index bf630aa..4de5d63 100644 --- a/src/discord/store.cpp +++ b/src/discord/store.cpp @@ -638,16 +638,16 @@ std::vector<ChannelData> Store::GetActiveThreads(Snowflake channel_id) const { return ret; } -std::vector<Snowflake> Store::GetChannelIDsWithParentID(Snowflake channel_id) const { +std::vector<std::pair<Snowflake, ChannelType>> Store::GetChannelIDsWithParentID(Snowflake channel_id) const { auto &s = m_stmt_get_chan_ids_parent; s->Bind(1, channel_id); - std::vector<Snowflake> ret; + std::vector<std::pair<Snowflake, ChannelType>> ret; while (s->FetchOne()) { - Snowflake x; - s->Get(0, x); - ret.push_back(x); + auto &p = ret.emplace_back(); + s->Get(0, p.first); + s->Get(1, p.second); } s->Reset(); @@ -2315,7 +2315,7 @@ bool Store::CreateStatements() { } m_stmt_get_chan_ids_parent = std::make_unique<Statement>(m_db, R"( - SELECT id FROM channels WHERE parent_id = ? + SELECT id, type FROM channels WHERE parent_id = ? )"); if (!m_stmt_get_chan_ids_parent->OK()) { fprintf(stderr, "failed to prepare get channel ids for parent statement: %s\n", m_db.ErrStr()); diff --git a/src/discord/store.hpp b/src/discord/store.hpp index 6157f09..e53d5c7 100644 --- a/src/discord/store.hpp +++ b/src/discord/store.hpp @@ -50,7 +50,7 @@ public: std::vector<Message> GetMessagesBefore(Snowflake channel_id, Snowflake message_id, size_t limit) const; std::vector<Message> GetPinnedMessages(Snowflake channel_id) const; std::vector<ChannelData> GetActiveThreads(Snowflake channel_id) const; // public - std::vector<Snowflake> GetChannelIDsWithParentID(Snowflake channel_id) const; + std::vector<std::pair<Snowflake, ChannelType>> GetChannelIDsWithParentID(Snowflake channel_id) const; std::unordered_set<Snowflake> GetMembersInGuild(Snowflake guild_id) const; // ^ not the same as GetUsersInGuild since users in a guild may include users who do not have retrieved member data diff --git a/src/discord/user.cpp b/src/discord/user.cpp index 8129273..a5bb0ae 100644 --- a/src/discord/user.cpp +++ b/src/discord/user.cpp @@ -220,34 +220,34 @@ void UserData::update_from_json(const nlohmann::json &j) { } const char *UserData::GetFlagName(uint64_t flag) { - switch (flag) { - case DiscordEmployee: + switch (static_cast<UserData::EFlags>(flag)) { + case UserData::EFlags::DiscordEmployee: return "discordstaff"; - case PartneredServerOwner: + case UserData::EFlags::PartneredServerOwner: return "partneredowner"; - case HypeSquadEvents: + case UserData::EFlags::HypeSquadEvents: return "hypesquadevents"; - case BugHunterLevel1: + case UserData::EFlags::BugHunterLevel1: return "discordbughunter"; - case HouseBravery: + case UserData::EFlags::HouseBravery: return "hypesquadbravery"; - case HouseBrilliance: + case UserData::EFlags::HouseBrilliance: return "hypesquadbrilliance"; - case HouseBalance: + case UserData::EFlags::HouseBalance: return "hypesquadbalance"; - case EarlySupporter: + case UserData::EFlags::EarlySupporter: return "earlysupporter"; - case TeamUser: + case UserData::EFlags::TeamUser: return "teamuser"; - case System: + case UserData::EFlags::System: return "system"; - case BugHunterLevel2: + case UserData::EFlags::BugHunterLevel2: return "discordbughunter2"; - case VerifiedBot: + case UserData::EFlags::VerifiedBot: return "verifiedbot"; - case EarlyVerifiedBotDeveloper: + case UserData::EFlags::EarlyVerifiedBotDeveloper: return "earlyverifiedbotdeveloper"; - case CertifiedModerator: + case UserData::EFlags::CertifiedModerator: return "certifiedmoderator"; default: return "unknown"; @@ -255,34 +255,34 @@ const char *UserData::GetFlagName(uint64_t flag) { } const char *UserData::GetFlagReadableName(uint64_t flag) { - switch (flag) { - case DiscordEmployee: + switch (static_cast<UserData::EFlags>(flag)) { + case UserData::EFlags::DiscordEmployee: return "Discord Staff"; - case PartneredServerOwner: + case UserData::EFlags::PartneredServerOwner: return "Partnered Server Owner"; - case HypeSquadEvents: + case UserData::EFlags::HypeSquadEvents: return "HypeSquad Events"; - case BugHunterLevel1: + case UserData::EFlags::BugHunterLevel1: return "Discord Bug Hunter"; - case HouseBravery: + case UserData::EFlags::HouseBravery: return "HypeSquad Bravery"; - case HouseBrilliance: + case UserData::EFlags::HouseBrilliance: return "HypeSquad Brilliance"; - case HouseBalance: + case UserData::EFlags::HouseBalance: return "HypeSquad Balance"; - case EarlySupporter: + case UserData::EFlags::EarlySupporter: return "Early Supporter"; - case TeamUser: + case UserData::EFlags::TeamUser: return "Team User"; // ??? - case System: + case UserData::EFlags::System: return "System"; - case BugHunterLevel2: + case UserData::EFlags::BugHunterLevel2: return "Discord Bug Hunter Level 2"; - case VerifiedBot: + case UserData::EFlags::VerifiedBot: return "Verified Bot"; - case EarlyVerifiedBotDeveloper: + case UserData::EFlags::EarlyVerifiedBotDeveloper: return "Early Verified Bot Developer"; - case CertifiedModerator: + case UserData::EFlags::CertifiedModerator: return "Discord Certified Moderator"; default: return ""; diff --git a/src/discord/user.hpp b/src/discord/user.hpp index 3e356a4..6aee6be 100644 --- a/src/discord/user.hpp +++ b/src/discord/user.hpp @@ -11,8 +11,7 @@ enum class EPremiumType { }; struct UserData { - // todo: enum class? (for consistencys sake) - enum { + enum class EFlags : uint64_t { DiscordEmployee = 1 << 0, PartneredServerOwner = 1 << 1, HypeSquadEvents = 1 << 2, |