diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2024-07-05 03:51:58 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-05 03:51:58 -0400 |
commit | 68db143c8939e12dd569d6ac737213ad856c139b (patch) | |
tree | d5e814329fb19912b69b9804fc68b852674d8277 /src/discord/discord.cpp | |
parent | e6191d95341d164eacaf91739c8aa7020dd5c9b6 (diff) | |
parent | b19782c16dffd38ac5651641131a48f8ff961b32 (diff) | |
download | abaddon-portaudio-68db143c8939e12dd569d6ac737213ad856c139b.tar.gz abaddon-portaudio-68db143c8939e12dd569d6ac737213ad856c139b.zip |
Merge pull request #279 from uowuo/stages
Support for stages
Diffstat (limited to 'src/discord/discord.cpp')
-rw-r--r-- | src/discord/discord.cpp | 159 |
1 files changed, 154 insertions, 5 deletions
diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index 062a871..a7712d6 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -360,6 +360,14 @@ std::optional<WebhookMessageData> DiscordClient::GetWebhookMessageData(Snowflake return m_store.GetWebhookMessage(message_id); } +std::optional<StageInstance> DiscordClient::GetStageInstanceFromChannel(Snowflake channel_id) const { + const auto iter1 = m_channel_to_stage_instance.find(channel_id); + if (iter1 == m_channel_to_stage_instance.end()) return {}; + const auto iter2 = m_stage_instances.find(iter1->second); + if (iter2 == m_stage_instances.end()) return {}; + return iter2->second; +} + bool DiscordClient::IsThreadJoined(Snowflake thread_id) const { return std::find(m_joined_threads.begin(), m_joined_threads.end(), thread_id) != m_joined_threads.end(); } @@ -462,6 +470,10 @@ bool DiscordClient::CanManageMember(Snowflake guild_id, Snowflake actor, Snowfla return actor_highest->Position > target_highest->Position; } +bool DiscordClient::IsStageModerator(Snowflake user_id, Snowflake channel_id) const { + return HasChannelPermission(user_id, channel_id, Permission::MANAGE_CHANNELS | Permission::MOVE_MEMBERS | Permission::MUTE_MEMBERS); +} + void DiscordClient::ChatMessageCallback(const std::string &nonce, const http::response_type &response, const sigc::slot<void(DiscordError)> &callback) { if (!CheckCode(response)) { if (response.status_code == http::TooManyRequests) { @@ -1288,6 +1300,78 @@ std::optional<uint32_t> DiscordClient::GetSSRCOfUser(Snowflake id) const { return m_voice.GetSSRCOfUser(id); } +bool DiscordClient::IsUserSpeaker(Snowflake user_id) const { + const auto state = GetVoiceState(user_id); + return state.has_value() && state->second.IsSpeaker(); +} + +bool DiscordClient::HasUserRequestedToSpeak(Snowflake user_id) const { + const auto state = GetVoiceState(user_id); + return state.has_value() && state->second.RequestToSpeakTimestamp.has_value() && util::FlagSet(state->second.Flags, VoiceStateFlags::Suppressed); +} + +bool DiscordClient::IsUserInvitedToSpeak(Snowflake user_id) const { + const auto state = GetVoiceState(user_id); + return state.has_value() && state->second.RequestToSpeakTimestamp.has_value() && !util::FlagSet(state->second.Flags, VoiceStateFlags::Suppressed); +} + +void DiscordClient::RequestToSpeak(Snowflake channel_id, bool want, const sigc::slot<void(DiscordError code)> &callback) { + if (want && !HasSelfChannelPermission(channel_id, Permission::REQUEST_TO_SPEAK)) return; + const auto channel = GetChannel(channel_id); + if (!channel.has_value() || !channel->GuildID.has_value()) return; + + ModifyCurrentUserVoiceStateObject d; + d.ChannelID = channel_id; + if (want) { + d.RequestToSpeakTimestamp = Glib::DateTime::create_now_utc().format_iso8601(); + } else { + d.RequestToSpeakTimestamp = ""; + } + m_http.MakePATCH("/guilds/" + std::to_string(*channel->GuildID) + "/voice-states/@me", nlohmann::json(d).dump(), [callback](const http::response_type &response) { + if (CheckCode(response, 204)) { + callback(DiscordError::NONE); + } else { + callback(GetCodeFromResponse(response)); + } + }); +} + +void DiscordClient::SetStageSpeaking(Snowflake channel_id, bool want, const sigc::slot<void(DiscordError code)> &callback) { + const auto channel = GetChannel(channel_id); + if (!channel.has_value() || !channel->GuildID.has_value()) return; + + ModifyCurrentUserVoiceStateObject d; + d.ChannelID = channel_id; + d.Suppress = !want; + if (want) { + d.RequestToSpeakTimestamp = ""; + } + m_http.MakePATCH("/guilds/" + std::to_string(*channel->GuildID) + "/voice-states/@me", nlohmann::json(d).dump(), [callback](const http::response_type &response) { + if (CheckCode(response, 204)) { + callback(DiscordError::NONE); + } else { + callback(GetCodeFromResponse(response)); + } + }); +} + +void DiscordClient::DeclineInviteToSpeak(Snowflake channel_id, const sigc::slot<void(DiscordError code)> &callback) { + const auto channel = GetChannel(channel_id); + if (!channel.has_value() || !channel->GuildID.has_value()) return; + + ModifyCurrentUserVoiceStateObject d; + d.ChannelID = channel_id; + d.Suppress = true; + d.RequestToSpeakTimestamp = ""; + m_http.MakePATCH("/guilds/" + std::to_string(*channel->GuildID) + "/voice-states/@me", nlohmann::json(d).dump(), [callback](const http::response_type &response) { + if (CheckCode(response, 204)) { + callback(DiscordError::NONE); + } else { + callback(GetCodeFromResponse(response)); + } + }); +} + DiscordVoiceClient &DiscordClient::GetVoiceClient() { return m_voice; } @@ -1303,7 +1387,7 @@ void DiscordClient::SetVoiceDeafened(bool is_deaf) { } #endif -std::optional<std::pair<Snowflake, VoiceStateFlags>> DiscordClient::GetVoiceState(Snowflake user_id) const { +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; } @@ -1652,6 +1736,15 @@ void DiscordClient::HandleGatewayMessage(std::string str) { case GatewayEvent::GUILD_MEMBERS_CHUNK: { HandleGatewayGuildMembersChunk(m); } break; + case GatewayEvent::STAGE_INSTANCE_CREATE: { + HandleGatewayStageInstanceCreate(m); + } break; + case GatewayEvent::STAGE_INSTANCE_UPDATE: { + HandleGatewayStageInstanceUpdate(m); + } break; + case GatewayEvent::STAGE_INSTANCE_DELETE: { + HandleGatewayStageInstanceDelete(m); + } break; case GatewayEvent::VOICE_STATE_UPDATE: { HandleGatewayVoiceStateUpdate(m); } break; @@ -1712,6 +1805,14 @@ void DiscordClient::ProcessNewGuild(GuildData &guild) { return; } + if (guild.StageInstances.has_value()) { + for (const auto &stage : *guild.StageInstances) { + spdlog::get("discord")->debug("storing stage {} in channel {}", stage.ID, stage.ChannelID); + m_stage_instances[stage.ID] = stage; + m_channel_to_stage_instance[stage.ChannelID] = stage.ID; + } + } + m_store.BeginTransaction(); m_store.SetGuild(guild.ID, guild); @@ -2302,6 +2403,29 @@ void DiscordClient::HandleGatewayGuildMembersChunk(const GatewayMessage &msg) { m_store.EndTransaction(); } +void DiscordClient::HandleGatewayStageInstanceCreate(const GatewayMessage &msg) { + StageInstance data = msg.Data; + spdlog::get("discord")->debug("STAGE_INSTANCE_CREATE: {} in {}", data.ID, data.ChannelID); + m_stage_instances[data.ID] = data; + m_channel_to_stage_instance[data.ChannelID] = data.ID; + m_signal_stage_instance_create.emit(data); +} + +void DiscordClient::HandleGatewayStageInstanceUpdate(const GatewayMessage &msg) { + StageInstance data = msg.Data; + spdlog::get("discord")->debug("STAGE_INSTANCE_UPDATE: {} in {}", data.ID, data.ChannelID); + m_stage_instances[data.ID] = data; + m_signal_stage_instance_update.emit(data); +} + +void DiscordClient::HandleGatewayStageInstanceDelete(const GatewayMessage &msg) { + StageInstance data = msg.Data; + spdlog::get("discord")->debug("STAGE_INSTANCE_DELETE: {} in {}", data.ID, data.ChannelID); + m_stage_instances.erase(data.ID); + m_channel_to_stage_instance.erase(data.ChannelID); + m_signal_stage_instance_delete.emit(data); +} + #ifdef WITH_VOICE /* @@ -2399,9 +2523,14 @@ void DiscordClient::CheckVoiceState(const VoiceState &data) { if (data.ChannelID.has_value()) { const auto old_state = GetVoiceState(data.UserID); SetVoiceState(data.UserID, data); - if (old_state.has_value() && old_state->first != *data.ChannelID) { - m_signal_voice_user_disconnect.emit(data.UserID, old_state->first); - m_signal_voice_user_connect.emit(data.UserID, *data.ChannelID); + const auto new_state = GetVoiceState(data.UserID); + if (old_state.has_value()) { + if (old_state->first != *data.ChannelID) { + m_signal_voice_user_disconnect.emit(data.UserID, old_state->first); + m_signal_voice_user_connect.emit(data.UserID, *data.ChannelID); + } else if (old_state->second.IsSpeaker() != new_state.value().second.IsSpeaker()) { + m_signal_voice_speaker_state_changed.emit(*data.ChannelID, data.UserID, new_state->second.IsSpeaker()); + } } else if (!old_state.has_value()) { m_signal_voice_user_connect.emit(data.UserID, *data.ChannelID); } @@ -2954,8 +3083,9 @@ void DiscordClient::SetVoiceState(Snowflake user_id, const VoiceState &state) { if (state.IsDeafened) flags |= VoiceStateFlags::Deaf; if (state.IsSelfStream) flags |= VoiceStateFlags::SelfStream; if (state.IsSelfVideo) flags |= VoiceStateFlags::SelfVideo; + if (state.IsSuppressed) flags |= VoiceStateFlags::Suppressed; - m_voice_states[user_id] = std::make_pair(*state.ChannelID, flags); + m_voice_states[user_id] = std::make_pair(*state.ChannelID, PackedVoiceState { flags, state.RequestToSpeakTimestamp }); m_voice_state_channel_users[*state.ChannelID].insert(user_id); m_signal_voice_state_set.emit(user_id, *state.ChannelID, flags); @@ -3018,6 +3148,9 @@ void DiscordClient::LoadEventMap() { m_event_map["VOICE_STATE_UPDATE"] = GatewayEvent::VOICE_STATE_UPDATE; m_event_map["VOICE_SERVER_UPDATE"] = GatewayEvent::VOICE_SERVER_UPDATE; m_event_map["CALL_CREATE"] = GatewayEvent::CALL_CREATE; + m_event_map["STAGE_INSTANCE_CREATE"] = GatewayEvent::STAGE_INSTANCE_CREATE; + m_event_map["STAGE_INSTANCE_UPDATE"] = GatewayEvent::STAGE_INSTANCE_UPDATE; + m_event_map["STAGE_INSTANCE_DELETE"] = GatewayEvent::STAGE_INSTANCE_DELETE; } DiscordClient::type_signal_gateway_ready DiscordClient::signal_gateway_ready() { @@ -3196,6 +3329,18 @@ DiscordClient::type_signal_guild_members_chunk DiscordClient::signal_guild_membe return m_signal_guild_members_chunk; } +DiscordClient::type_signal_stage_instance_create DiscordClient::signal_stage_instance_create() { + return m_signal_stage_instance_create; +} + +DiscordClient::type_signal_stage_instance_update DiscordClient::signal_stage_instance_update() { + return m_signal_stage_instance_update; +} + +DiscordClient::type_signal_stage_instance_delete DiscordClient::signal_stage_instance_delete() { + return m_signal_stage_instance_delete; +} + DiscordClient::type_signal_added_to_thread DiscordClient::signal_added_to_thread() { return m_signal_added_to_thread; } @@ -3273,3 +3418,7 @@ DiscordClient::type_signal_voice_user_connect DiscordClient::signal_voice_user_c DiscordClient::type_signal_voice_state_set DiscordClient::signal_voice_state_set() { return m_signal_voice_state_set; } + +DiscordClient::type_signal_voice_speaker_state_changed DiscordClient::signal_voice_speaker_state_changed() { + return m_signal_voice_speaker_state_changed; +}
\ No newline at end of file |