diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-11-01 02:53:37 -0500 |
---|---|---|
committer | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-11-01 02:53:37 -0500 |
commit | 534bfccf2330bb85a19d0a3bb6d90df3c4d9d83a (patch) | |
tree | 7fb15e6aeea94c3d6570e03f5e24388703424f92 /discord | |
parent | 18f4f7ce5e597f83c67349a91f67cfa5a317069d (diff) | |
download | abaddon-portaudio-534bfccf2330bb85a19d0a3bb6d90df3c4d9d83a.tar.gz abaddon-portaudio-534bfccf2330bb85a19d0a3bb6d90df3c4d9d83a.zip |
add set status for funsies
Diffstat (limited to 'discord')
-rw-r--r-- | discord/activity.cpp | 101 | ||||
-rw-r--r-- | discord/activity.hpp | 92 | ||||
-rw-r--r-- | discord/discord.cpp | 9 | ||||
-rw-r--r-- | discord/discord.hpp | 1 | ||||
-rw-r--r-- | discord/json.hpp | 21 | ||||
-rw-r--r-- | discord/objects.cpp | 9 | ||||
-rw-r--r-- | discord/objects.hpp | 10 |
7 files changed, 239 insertions, 4 deletions
diff --git a/discord/activity.cpp b/discord/activity.cpp new file mode 100644 index 0000000..b7285a9 --- /dev/null +++ b/discord/activity.cpp @@ -0,0 +1,101 @@ +#include "activity.hpp" + +void from_json(const nlohmann::json &j, ActivityTimestamps &m) { + JS_O("start", m.Start); + JS_O("end", m.End); +} + +void to_json(nlohmann::json &j, const ActivityTimestamps &m) { + JS_IF("start", m.Start); + JS_IF("end", m.End); +} + +void from_json(const nlohmann::json &j, ActivityEmoji &m) { + JS_D("name", m.Name); + JS_O("id", m.ID); + JS_O("animated", m.IsAnimated); +} + +void to_json(nlohmann::json &j, const ActivityEmoji &m) { + j["name"] = m.Name; + if (m.ID.has_value()) + j["id"] = *m.ID; + if (m.IsAnimated.has_value()) + j["animated"] = *m.IsAnimated; +} + +void from_json(const nlohmann::json &j, ActivityParty &m) { + JS_O("id", m.ID); + JS_O("size", m.Size); +} + +void to_json(nlohmann::json &j, const ActivityParty &m) { + JS_IF("id", m.ID); + JS_IF("size", m.Size); +} + +void from_json(const nlohmann::json &j, ActivityAssets &m) { + JS_O("large_image", m.LargeImage); + JS_O("large_text", m.LargeText); + JS_O("small_image", m.SmallImage); + JS_O("small_text", m.SmallText); +} + +void to_json(nlohmann::json &j, const ActivityAssets &m) { + JS_IF("large_image", m.LargeImage); + JS_IF("large_text", m.LargeText); + JS_IF("small_image", m.SmallImage); + JS_IF("small_text", m.SmallText); +} + +void from_json(const nlohmann::json &j, ActivitySecrets &m) { + JS_O("join", m.Join); + JS_O("spectate", m.Spectate); + JS_O("match", m.Match); +} + +void to_json(nlohmann::json &j, const ActivitySecrets &m) { + JS_IF("join", m.Join); + JS_IF("spectate", m.Spectate); + JS_IF("match", m.Match); +} + +void from_json(const nlohmann::json &j, Activity &m) { + JS_D("name", m.Name); + JS_D("type", m.Type); + JS_ON("url", m.URL); + JS_D("created_at", m.CreatedAt); + JS_O("timestamps", m.Timestamps); + JS_O("application_id", m.ApplicationID); + JS_ON("details", m.Details); + JS_ON("state", m.State); + JS_ON("emoji", m.Emoji); + JS_ON("party", m.Party); + JS_O("assets", m.Assets); + JS_O("secrets", m.Secrets); + JS_O("instance", m.IsInstance); + JS_O("flags", m.Flags); +} + +void to_json(nlohmann::json &j, const Activity &m) { + if (m.Type == ActivityType::Custom) { + j["name"] = "Custom Status"; + j["state"] = m.Name; + } else { + j["name"] = m.Name; + JS_IF("state", m.State); + } + + j["type"] = m.Type; + JS_IF("url", m.URL); + JS_IF("created_at", m.CreatedAt); + JS_IF("timestamps", m.Timestamps); + JS_IF("application_id", m.ApplicationID); + JS_IF("details", m.Details); + JS_IF("emoji", m.Emoji); + JS_IF("party", m.Party); + JS_IF("assets", m.Assets); + JS_IF("secrets", m.Secrets); + JS_IF("instance", m.IsInstance); + JS_IF("flags", m.Flags); +} diff --git a/discord/activity.hpp b/discord/activity.hpp new file mode 100644 index 0000000..90040ca --- /dev/null +++ b/discord/activity.hpp @@ -0,0 +1,92 @@ +#pragma once +#include <string> +#include <optional> +#include "../util.hpp" +#include "json.hpp" +#include "snowflake.hpp" + +enum class ActivityType : int { + Game = 0, + Streaming = 1, + Listening = 2, + Watching = 3, // not documented + Custom = 4, + Competing = 5, +}; + +enum class ActivityFlags { + INSTANCE = (1 << 0), + JOIN = (1 << 1), + SPECTATE = (1 << 2), + JOIN_REQUEST = (1 << 3), + SYNC = (1 << 4), + PLAY = (1 << 5), +}; +template<> +struct Bitwise<ActivityFlags> { + static const bool enable = true; +}; + +struct ActivityTimestamps { + std::optional<std::string> Start; // opt + std::optional<std::string> End; // opt + + friend void from_json(const nlohmann::json &j, ActivityTimestamps &m); + friend void to_json(nlohmann::json &j, const ActivityTimestamps &m); +}; + +struct ActivityEmoji { + std::string Name; + std::optional<Snowflake> ID; + std::optional<bool> IsAnimated; + + friend void from_json(const nlohmann::json &j, ActivityEmoji &m); + friend void to_json(nlohmann::json &j, const ActivityEmoji &m); +}; + +struct ActivityParty { + std::optional<std::string> ID; + std::optional<std::array<int, 2>> Size; + + friend void from_json(const nlohmann::json &j, ActivityParty &m); + friend void to_json(nlohmann::json &j, const ActivityParty &m); +}; + +struct ActivityAssets { + std::optional<std::string> LargeImage; + std::optional<std::string> LargeText; + std::optional<std::string> SmallImage; + std::optional<std::string> SmallText; + + friend void from_json(const nlohmann::json &j, ActivityAssets &m); + friend void to_json(nlohmann::json &j, const ActivityAssets &m); +}; + +struct ActivitySecrets { + std::optional<std::string> Join; + std::optional<std::string> Spectate; + std::optional<std::string> Match; + + friend void from_json(const nlohmann::json &j, ActivitySecrets &m); + friend void to_json(nlohmann::json &j, const ActivitySecrets &m); +}; + +struct Activity { + std::string Name; // + ActivityType Type; // + std::optional<std::string> URL; // null + std::optional<uint64_t> CreatedAt; // + std::optional<ActivityTimestamps> Timestamps; // + std::optional<Snowflake> ApplicationID; // + std::optional<std::string> Details; // null + std::optional<std::string> State; // null + std::optional<ActivityEmoji> Emoji; // null + std::optional<ActivityParty> Party; // + std::optional<ActivityAssets> Assets; // + std::optional<ActivitySecrets> Secrets; // + std::optional<bool> IsInstance; // + std::optional<ActivityFlags> Flags; // + + friend void from_json(const nlohmann::json &j, Activity &m); + friend void to_json(nlohmann::json &j, const Activity &m); +}; diff --git a/discord/discord.cpp b/discord/discord.cpp index a1b0e05..7c4d551 100644 --- a/discord/discord.cpp +++ b/discord/discord.cpp @@ -397,6 +397,15 @@ void DiscordClient::BanUser(Snowflake user_id, Snowflake guild_id) { m_http.MakePUT("/guilds/" + std::to_string(guild_id) + "/bans/" + std::to_string(user_id), "{}", [](auto) {}); } +void DiscordClient::UpdateStatus(const std::string &status, bool is_afk, const Activity &obj) { + UpdateStatusMessage msg; + msg.Status = status; + msg.IsAFK = is_afk; + msg.Activities.push_back(obj); + + m_websocket.Send(nlohmann::json(msg)); +} + void DiscordClient::UpdateToken(std::string token) { if (!IsStarted()) { m_token = token; diff --git a/discord/discord.hpp b/discord/discord.hpp index 42fa281..de0ef27 100644 --- a/discord/discord.hpp +++ b/discord/discord.hpp @@ -103,6 +103,7 @@ public: 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(const std::string &status, bool is_afk, const Activity &obj); void UpdateToken(std::string token); diff --git a/discord/json.hpp b/discord/json.hpp index 40f078f..beb1592 100644 --- a/discord/json.hpp +++ b/discord/json.hpp @@ -37,7 +37,7 @@ inline void json_nullable(const ::nlohmann::json &j, const char *key, T &val) { if (!at.is_null()) val = at.get<T::value_type>(); else - val = std::nullopt; + val = ::std::nullopt; } else { const auto &at = j.at(key); if (!at.is_null()) @@ -53,9 +53,9 @@ inline void json_optional_nullable(const ::nlohmann::json &j, const char *key, T if (!at.is_null()) val = at.get<T::value_type>(); else - val = std::nullopt; + val = ::std::nullopt; } else { - val = std::nullopt; + val = ::std::nullopt; } } else { if (j.contains(key)) { @@ -74,7 +74,7 @@ inline void json_update_optional_nullable(const ::nlohmann::json &j, const char if (!at.is_null()) val = at.get<T::value_type>(); else - val = std::nullopt; + val = ::std::nullopt; } } else { if (j.contains(key)) { @@ -109,32 +109,45 @@ inline void json_update_optional_nullable_default(const ::nlohmann::json &j, con } } // namespace detail +// get a json value that is guaranteed to be present and non-null #define JS_D(k, t) \ do { \ detail::json_direct(j, k, t); \ } while (0) +// get a json value that may not be present #define JS_O(k, t) \ do { \ detail::json_optional(j, k, t); \ } while (0) +// get a json value that may be null #define JS_N(k, t) \ do { \ detail::json_nullable(j, k, t); \ } while (0) +// get a json value that may not be present or may be null #define JS_ON(k, t) \ do { \ detail::json_optional_nullable(j, k, t); \ } while (0) +// set from a json value only if it is present. null will assign default-constructed value #define JS_RD(k, t) \ do { \ detail::json_update_optional_nullable(j, k, t); \ } while (0) +// set from a json value only if it is present. null will assign the given default #define JS_RV(k, t, d) \ do { \ detail::json_update_optional_nullable_default(j, k, t, d); \ } while (0) + +// set a json value from a std::optional only if it has a value +#define JS_IF(k, v) \ + do { \ + if (v.has_value()) \ + j[k] = *v; \ + } while (0) diff --git a/discord/objects.cpp b/discord/objects.cpp index 1f6d109..5299a79 100644 --- a/discord/objects.cpp +++ b/discord/objects.cpp @@ -83,6 +83,15 @@ void to_json(nlohmann::json &j, const LazyLoadRequestMessage &m) { j["d"]["members"] = m.Members; } +void to_json(nlohmann::json &j, const UpdateStatusMessage &m) { + j["op"] = GatewayOp::UpdateStatus; + j["d"] = nlohmann::json::object(); + j["d"]["activities"] = m.Activities; + j["d"]["status"] = m.Status; + j["d"]["afk"] = m.IsAFK; + j["d"]["since"] = nullptr; +} + void from_json(const nlohmann::json &j, ReadyEventData &m) { JS_D("v", m.GatewayVersion); JS_D("user", m.User); diff --git a/discord/objects.hpp b/discord/objects.hpp index b660a6a..d71c1fc 100644 --- a/discord/objects.hpp +++ b/discord/objects.hpp @@ -14,6 +14,7 @@ #include "invite.hpp" #include "permissions.hpp" #include "emoji.hpp" +#include "activity.hpp" // most stuff below should just be objects that get processed and thrown away immediately @@ -21,6 +22,7 @@ enum class GatewayOp : int { Event = 0, Heartbeat = 1, Identify = 2, + UpdateStatus = 3, Hello = 10, HeartbeatAck = 11, LazyLoadRequest = 14, @@ -134,6 +136,14 @@ struct LazyLoadRequestMessage { friend void to_json(nlohmann::json &j, const LazyLoadRequestMessage &m); }; +struct UpdateStatusMessage { + std::vector<Activity> Activities; // null (but never sent as such) + std::string Status; + bool IsAFK; + + friend void to_json(nlohmann::json &j, const UpdateStatusMessage &m); +}; + struct ReadyEventData { int GatewayVersion; // User User; // |