diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 472b96d..94a5c40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: [push, pull_request] jobs: windows: name: windows-${{ matrix.buildtype }} - runs-on: windows-2016 + runs-on: windows-latest strategy: matrix: buildtype: [Debug, RelWithDebInfo, MinSizeRel] diff --git a/abaddon.cpp b/abaddon.cpp index a34ec2c..99a2520 100644 --- a/abaddon.cpp +++ b/abaddon.cpp @@ -432,8 +432,7 @@ void Abaddon::ActionConnect() { } void Abaddon::ActionDisconnect() { - if (m_discord.IsStarted()) - StopDiscord(); + StopDiscord(); } void Abaddon::ActionSetToken() { diff --git a/ci/vcpkg b/ci/vcpkg index a9b27ed..50ea8c0 160000 --- a/ci/vcpkg +++ b/ci/vcpkg @@ -1 +1 @@ -Subproject commit a9b27ed5dffbf70b135eddb0c4729f3ca87f106c +Subproject commit 50ea8c0ab7aca3bb9245bba7fc877ad2f2a4464c diff --git a/discord/discord.cpp b/discord/discord.cpp index 78036ad..fab2c49 100644 --- a/discord/discord.cpp +++ b/discord/discord.cpp @@ -24,6 +24,8 @@ DiscordClient::DiscordClient(bool mem_store) } void DiscordClient::Start() { + if (m_client_started) return; + m_http.SetBase(GetAPIURL()); std::memset(&m_zstream, 0, sizeof(m_zstream)); @@ -32,27 +34,31 @@ void DiscordClient::Start() { m_last_sequence = -1; m_heartbeat_acked = true; m_client_connected = true; + m_client_started = true; m_websocket.StartConnection(GetGatewayURL()); } void DiscordClient::Stop() { - if (!m_client_connected) return; + if (m_client_started) { + inflateEnd(&m_zstream); + m_compressed_buf.clear(); - inflateEnd(&m_zstream); - m_compressed_buf.clear(); + m_heartbeat_waiter.kill(); + if (m_heartbeat_thread.joinable()) m_heartbeat_thread.join(); + m_client_connected = false; + m_reconnecting = false; - m_heartbeat_waiter.kill(); - if (m_heartbeat_thread.joinable()) m_heartbeat_thread.join(); - m_client_connected = false; + m_store.ClearAll(); + m_guild_to_users.clear(); - m_store.ClearAll(); - m_guild_to_users.clear(); + m_websocket.Stop(); + } - m_websocket.Stop(); + m_client_started = false; } bool DiscordClient::IsStarted() const { - return m_client_connected; + return m_client_started; } bool DiscordClient::IsStoreValid() const { @@ -233,19 +239,19 @@ std::optional DiscordClient::GetMemberHighestRole(Snowflake guild_id, }); } -std::unordered_set DiscordClient::GetUsersInGuild(Snowflake id) const { +std::set DiscordClient::GetUsersInGuild(Snowflake id) const { auto it = m_guild_to_users.find(id); if (it != m_guild_to_users.end()) return it->second; - return std::unordered_set(); + return {}; } -std::unordered_set DiscordClient::GetChannelsInGuild(Snowflake id) const { +std::set DiscordClient::GetChannelsInGuild(Snowflake id) const { auto it = m_guild_to_channels.find(id); if (it != m_guild_to_channels.end()) return it->second; - return std::unordered_set(); + return {}; } bool DiscordClient::HasGuildPermission(Snowflake user_id, Snowflake guild_id, Permission perm) const { @@ -953,12 +959,12 @@ PresenceStatus DiscordClient::GetUserStatus(Snowflake id) const { return PresenceStatus::Offline; } -std::unordered_map DiscordClient::GetRelationships() const { +std::map DiscordClient::GetRelationships() const { return m_user_relationships; } -std::unordered_set DiscordClient::GetRelationships(RelationshipType type) const { - std::unordered_set ret; +std::set DiscordClient::GetRelationships(RelationshipType type) const { + std::set ret; for (const auto &[id, rtype] : m_user_relationships) if (rtype == type) ret.insert(id); @@ -1682,7 +1688,8 @@ void DiscordClient::HandleGatewayInvalidSession(const GatewayMessage &msg) { m_websocket.Stop(1000); - m_websocket.StartConnection(GetGatewayURL()); + if (m_client_started) + Glib::signal_timeout().connect_once([this] { if (m_client_started) m_websocket.StartConnection(GetGatewayURL()); }, 1000); } bool IsCompleteMessageObject(const nlohmann::json &j) { @@ -1886,6 +1893,11 @@ void DiscordClient::HandleSocketClose(uint16_t code) { m_store.ClearAll(); m_guild_to_users.clear(); + if (m_client_started && !m_reconnecting && close_code == GatewayCloseCode::Abnormal) { + Glib::signal_timeout().connect_once([this] { if (m_client_started) HandleGatewayReconnect(GatewayMessage()); }, 1000); + m_reconnecting = true; + } + m_signal_disconnected.emit(m_reconnecting, close_code); }; m_generic_mutex.lock(); diff --git a/discord/discord.hpp b/discord/discord.hpp index cfce016..918b1cb 100644 --- a/discord/discord.hpp +++ b/discord/discord.hpp @@ -6,9 +6,8 @@ #include #include #include -#include +#include #include -#include #include #include #include @@ -85,8 +84,8 @@ public: std::optional GetBan(Snowflake guild_id, Snowflake user_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::unordered_set GetUsersInGuild(Snowflake id) const; - std::unordered_set GetChannelsInGuild(Snowflake id) const; + std::set GetUsersInGuild(Snowflake id) const; + std::set GetChannelsInGuild(Snowflake id) const; bool HasGuildPermission(Snowflake user_id, Snowflake guild_id, Permission perm) const; @@ -184,8 +183,8 @@ public: PresenceStatus GetUserStatus(Snowflake id) const; - std::unordered_map GetRelationships() const; - std::unordered_set GetRelationships(RelationshipType type) const; + std::map GetRelationships() const; + std::set GetRelationships(RelationshipType type) const; std::optional GetRelationship(Snowflake id) const; private: @@ -255,14 +254,14 @@ private: std::string m_token; void AddUserToGuild(Snowflake user_id, Snowflake guild_id); - std::unordered_map> m_guild_to_users; + std::map> m_guild_to_users; - std::unordered_map> m_guild_to_channels; - std::unordered_map m_guild_join_requests; + std::map> m_guild_to_channels; + std::map m_guild_join_requests; - std::unordered_map m_user_to_status; + std::map m_user_to_status; - std::unordered_map m_user_relationships; + std::map m_user_relationships; UserData m_user_data; UserSettings m_user_settings; @@ -272,8 +271,9 @@ private: Websocket m_websocket; std::atomic m_client_connected = false; std::atomic m_ready_received = false; + bool m_client_started = false; - std::unordered_map m_event_map; + std::map m_event_map; void LoadEventMap(); std::thread m_heartbeat_thread; diff --git a/windows/mainwindow.cpp b/windows/mainwindow.cpp index 77bd6d3..dc9c51d 100644 --- a/windows/mainwindow.cpp +++ b/windows/mainwindow.cpp @@ -148,13 +148,6 @@ MainWindow::MainWindow() void MainWindow::UpdateComponents() { bool discord_active = Abaddon::Get().IsDiscordActive(); - std::string token = Abaddon::Get().GetDiscordToken(); - m_menu_discord_connect.set_sensitive(token.size() > 0 && !discord_active); - m_menu_discord_disconnect.set_sensitive(discord_active); - m_menu_discord_join_guild.set_sensitive(discord_active); - m_menu_discord_set_token.set_sensitive(!discord_active); - m_menu_discord_set_status.set_sensitive(discord_active); - if (!discord_active) { m_chat.Clear(); m_members.Clear(); @@ -258,6 +251,15 @@ void MainWindow::OnDiscordSubmenuPopup(const Gdk::Rectangle *flipped_rect, const m_menu_discord_add_recipient.set_visible(false); if (channel.has_value() && channel->GetDMRecipients().size() + 1 < 10) m_menu_discord_add_recipient.set_visible(channel->Type == ChannelType::GROUP_DM); + + const bool discord_active = Abaddon::Get().GetDiscordClient().IsStarted(); + + std::string token = Abaddon::Get().GetDiscordToken(); + m_menu_discord_connect.set_sensitive(token.size() > 0 && !discord_active); + m_menu_discord_disconnect.set_sensitive(discord_active); + m_menu_discord_join_guild.set_sensitive(discord_active); + m_menu_discord_set_token.set_sensitive(!discord_active); + m_menu_discord_set_status.set_sensitive(discord_active); } void MainWindow::OnViewSubmenuPopup(const Gdk::Rectangle *flipped_rect, const Gdk::Rectangle *final_rect, bool flipped_x, bool flipped_y) {