summaryrefslogtreecommitdiff
path: root/discord
diff options
context:
space:
mode:
authorouwou <26526779+ouwou@users.noreply.github.com>2020-11-01 02:53:37 -0500
committerouwou <26526779+ouwou@users.noreply.github.com>2020-11-01 02:53:37 -0500
commit534bfccf2330bb85a19d0a3bb6d90df3c4d9d83a (patch)
tree7fb15e6aeea94c3d6570e03f5e24388703424f92 /discord
parent18f4f7ce5e597f83c67349a91f67cfa5a317069d (diff)
downloadabaddon-portaudio-534bfccf2330bb85a19d0a3bb6d90df3c4d9d83a.tar.gz
abaddon-portaudio-534bfccf2330bb85a19d0a3bb6d90df3c4d9d83a.zip
add set status for funsies
Diffstat (limited to 'discord')
-rw-r--r--discord/activity.cpp101
-rw-r--r--discord/activity.hpp92
-rw-r--r--discord/discord.cpp9
-rw-r--r--discord/discord.hpp1
-rw-r--r--discord/json.hpp21
-rw-r--r--discord/objects.cpp9
-rw-r--r--discord/objects.hpp10
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; //