diff options
Diffstat (limited to 'discord')
-rw-r--r-- | discord/discord.cpp | 63 | ||||
-rw-r--r-- | discord/discord.hpp | 24 | ||||
-rw-r--r-- | discord/message.cpp | 2 | ||||
-rw-r--r-- | discord/message.hpp | 1 | ||||
-rw-r--r-- | discord/snowflake.cpp | 2 | ||||
-rw-r--r-- | discord/snowflake.hpp | 2 | ||||
-rw-r--r-- | discord/sticker.cpp | 20 | ||||
-rw-r--r-- | discord/sticker.hpp | 11 | ||||
-rw-r--r-- | discord/store.cpp | 25 |
9 files changed, 102 insertions, 48 deletions
diff --git a/discord/discord.cpp b/discord/discord.cpp index 78036ad..8dc1ef8 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 { @@ -199,22 +205,17 @@ Snowflake DiscordClient::GetMemberHoistedRole(Snowflake guild_id, Snowflake user const auto data = GetMember(user_id, guild_id); if (!data.has_value()) return Snowflake::Invalid; - std::vector<RoleData> roles; + std::optional<RoleData> top_role; for (const auto &id : data->Roles) { const auto role = GetRole(id); if (role.has_value()) { - if (role->IsHoisted || (with_color && role->Color != 0)) - roles.push_back(*role); + if ((with_color && role->Color != 0x000000) || (!with_color && role->IsHoisted)) + if (!top_role.has_value() || top_role->Position < role->Position) + top_role = role; } } - if (roles.size() == 0) return Snowflake::Invalid; - - std::sort(roles.begin(), roles.end(), [this](const RoleData &a, const RoleData &b) -> bool { - return a.Position > b.Position; - }); - - return roles[0].ID; + return top_role.has_value() ? top_role->ID : Snowflake::Invalid; } std::optional<RoleData> DiscordClient::GetMemberHighestRole(Snowflake guild_id, Snowflake user_id) const { @@ -233,19 +234,19 @@ std::optional<RoleData> DiscordClient::GetMemberHighestRole(Snowflake guild_id, }); } -std::unordered_set<Snowflake> DiscordClient::GetUsersInGuild(Snowflake id) const { +std::set<Snowflake> 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<Snowflake>(); + return {}; } -std::unordered_set<Snowflake> DiscordClient::GetChannelsInGuild(Snowflake id) const { +std::set<Snowflake> 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<Snowflake>(); + return {}; } bool DiscordClient::HasGuildPermission(Snowflake user_id, Snowflake guild_id, Permission perm) const { @@ -953,12 +954,12 @@ PresenceStatus DiscordClient::GetUserStatus(Snowflake id) const { return PresenceStatus::Offline; } -std::unordered_map<Snowflake, RelationshipType> DiscordClient::GetRelationships() const { +std::map<Snowflake, RelationshipType> DiscordClient::GetRelationships() const { return m_user_relationships; } -std::unordered_set<Snowflake> DiscordClient::GetRelationships(RelationshipType type) const { - std::unordered_set<Snowflake> ret; +std::set<Snowflake> DiscordClient::GetRelationships(RelationshipType type) const { + std::set<Snowflake> ret; for (const auto &[id, rtype] : m_user_relationships) if (rtype == type) ret.insert(id); @@ -1682,7 +1683,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 +1888,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 <sigc++/sigc++.h> #include <nlohmann/json.hpp> #include <thread> -#include <unordered_map> +#include <map> #include <set> -#include <unordered_set> #include <mutex> #include <zlib.h> #include <glibmm.h> @@ -85,8 +84,8 @@ public: std::optional<BanData> GetBan(Snowflake guild_id, Snowflake user_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::unordered_set<Snowflake> GetUsersInGuild(Snowflake id) const; - std::unordered_set<Snowflake> GetChannelsInGuild(Snowflake id) const; + std::set<Snowflake> GetUsersInGuild(Snowflake id) const; + std::set<Snowflake> 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<Snowflake, RelationshipType> GetRelationships() const; - std::unordered_set<Snowflake> GetRelationships(RelationshipType type) const; + std::map<Snowflake, RelationshipType> GetRelationships() const; + std::set<Snowflake> GetRelationships(RelationshipType type) const; std::optional<RelationshipType> 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<Snowflake, std::unordered_set<Snowflake>> m_guild_to_users; + std::map<Snowflake, std::set<Snowflake>> m_guild_to_users; - std::unordered_map<Snowflake, std::unordered_set<Snowflake>> m_guild_to_channels; - std::unordered_map<Snowflake, GuildApplicationData> m_guild_join_requests; + std::map<Snowflake, std::set<Snowflake>> m_guild_to_channels; + std::map<Snowflake, GuildApplicationData> m_guild_join_requests; - std::unordered_map<Snowflake, PresenceStatus> m_user_to_status; + std::map<Snowflake, PresenceStatus> m_user_to_status; - std::unordered_map<Snowflake, RelationshipType> m_user_relationships; + std::map<Snowflake, RelationshipType> m_user_relationships; UserData m_user_data; UserSettings m_user_settings; @@ -272,8 +271,9 @@ private: Websocket m_websocket; std::atomic<bool> m_client_connected = false; std::atomic<bool> m_ready_received = false; + bool m_client_started = false; - std::unordered_map<std::string, GatewayEvent> m_event_map; + std::map<std::string, GatewayEvent> m_event_map; void LoadEventMap(); std::thread m_heartbeat_thread; diff --git a/discord/message.cpp b/discord/message.cpp index b072ba8..70c557d 100644 --- a/discord/message.cpp +++ b/discord/message.cpp @@ -218,6 +218,7 @@ void from_json(const nlohmann::json &j, Message &m) { m.ReferencedMessage = nullptr; } JS_O("interaction", m.Interaction); + JS_O("sticker_items", m.StickerItems); } void Message::from_json_edited(const nlohmann::json &j) { @@ -244,6 +245,7 @@ void Message::from_json_edited(const nlohmann::json &j) { JS_O("flags", Flags); JS_O("stickers", Stickers); JS_O("interaction", Interaction); + JS_O("sticker_items", StickerItems); } void Message::SetDeleted() { diff --git a/discord/message.hpp b/discord/message.hpp index e24f248..a6ea039 100644 --- a/discord/message.hpp +++ b/discord/message.hpp @@ -199,6 +199,7 @@ struct Message { std::optional<std::vector<StickerData>> Stickers; std::optional<std::shared_ptr<Message>> ReferencedMessage; // has_value && null means deleted std::optional<MessageInteractionData> Interaction; + std::optional<std::vector<StickerItem>> StickerItems; friend void from_json(const nlohmann::json &j, Message &m); void from_json_edited(const nlohmann::json &j); // for MESSAGE_UPDATE diff --git a/discord/snowflake.cpp b/discord/snowflake.cpp index 18c7805..cea9153 100644 --- a/discord/snowflake.cpp +++ b/discord/snowflake.cpp @@ -5,6 +5,8 @@ constexpr static uint64_t DiscordEpochSeconds = 1420070400; +const Snowflake Snowflake::Invalid = -1ULL; + Snowflake::Snowflake() : m_num(Invalid) {} diff --git a/discord/snowflake.hpp b/discord/snowflake.hpp index 4263bab..0b79723 100644 --- a/discord/snowflake.hpp +++ b/discord/snowflake.hpp @@ -26,7 +26,7 @@ struct Snowflake { return m_num; } - const static uint64_t Invalid = -1ULL; // makes sense to me + const static Snowflake Invalid; // makes sense to me const static uint64_t SecondsInterval = 4194304000ULL; // the "difference" between two snowflakes one second apart friend void from_json(const nlohmann::json &j, Snowflake &s); diff --git a/discord/sticker.cpp b/discord/sticker.cpp index 8e50a47..b92d031 100644 --- a/discord/sticker.cpp +++ b/discord/sticker.cpp @@ -30,3 +30,23 @@ std::string StickerData::GetURL() const { return "https://media.discordapp.net/stickers/" + std::to_string(ID) + "/" + *AssetHash + ".json"; return ""; } + +void to_json(nlohmann::json &j, const StickerItem &m) { + j["id"] = m.ID; + j["name"] = m.Name; + j["format_type"] = m.FormatType; +} + +void from_json(const nlohmann::json &j, StickerItem &m) { + JS_D("id", m.ID); + JS_D("name", m.Name); + JS_D("format_type", m.FormatType); +} + +std::string StickerItem::GetURL() const { + if (FormatType == StickerFormatType::PNG || FormatType == StickerFormatType::APNG) + return "https://media.discordapp.net/stickers/" + std::to_string(ID) + ".png?size=256"; + else if (FormatType == StickerFormatType::LOTTIE) + return "https://media.discordapp.net/stickers/" + std::to_string(ID) + ".json"; + return ""; +} diff --git a/discord/sticker.hpp b/discord/sticker.hpp index 89279b3..d23fe7b 100644 --- a/discord/sticker.hpp +++ b/discord/sticker.hpp @@ -27,3 +27,14 @@ struct StickerData { std::string GetURL() const; }; + +struct StickerItem { + StickerFormatType FormatType; + Snowflake ID; + std::string Name; + + friend void to_json(nlohmann::json &j, const StickerItem &m); + friend void from_json(const nlohmann::json &j, StickerItem &m); + + std::string GetURL() const; +}; diff --git a/discord/store.cpp b/discord/store.cpp index fc40108..2439da5 100644 --- a/discord/store.cpp +++ b/discord/store.cpp @@ -264,6 +264,12 @@ void Store::SetMessage(Snowflake id, const Message &message) { Bind(m_set_msg_stmt, 23, message.IsPending); Bind(m_set_msg_stmt, 24, message.Nonce); // sorry + if (message.StickerItems.has_value()) { + std::string tmp = nlohmann::json(*message.StickerItems).dump(); + Bind(m_set_msg_stmt, 25, tmp); + } else + Bind(m_set_msg_stmt, 25, nullptr); + if (!RunInsert(m_set_msg_stmt)) fprintf(stderr, "message insert failed: %s\n", sqlite3_errstr(m_db_err)); @@ -369,14 +375,18 @@ Message Store::GetMessageBound(sqlite3_stmt *stmt) const { Get(stmt, 22, ret.IsPending); Get(stmt, 23, ret.Nonce); + Get(stmt, 24, tmps); + if (tmps != "") + ret.StickerItems = nlohmann::json::parse(tmps).get<std::vector<StickerItem>>(); + // interaction data from join - if (!IsNull(stmt, 24)) { + if (!IsNull(stmt, 25)) { auto &interaction = ret.Interaction.emplace(); - Get(stmt, 24, interaction.ID); - Get(stmt, 25, interaction.Name); - Get(stmt, 26, interaction.Type); - Get(stmt, 27, interaction.User.ID); + Get(stmt, 25, interaction.ID); + Get(stmt, 26, interaction.Name); + Get(stmt, 27, interaction.Type); + Get(stmt, 28, interaction.User.ID); } Reset(stmt); @@ -837,7 +847,8 @@ bool Store::CreateTables() { deleted BOOL, /* extra */ edited BOOL, /* extra */ pending BOOL, /* extra */ - nonce TEXT + nonce TEXT, + sticker_items TEXT /* json */ ) )"; @@ -1056,7 +1067,7 @@ bool Store::CreateStatements() { const char *set_msg = R"( REPLACE INTO messages VALUES ( - ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? + ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) )"; |