Skip to content

Commit

Permalink
handle rection add/remove events
Browse files Browse the repository at this point in the history
  • Loading branch information
Arkrissym committed Sep 7, 2024
1 parent 3f7acb6 commit bdaa136
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 14 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ target_include_directories( ${PROJECT_NAME} PRIVATE Discord.C++ )
if(MSVC)
set( CMAKE_CXX_FLAGS " /MP /O2 /GL /GS /W3 /sdl /Gd /EHa " )
else(MSVC)
set( CMAKE_CXX_FLAGS " -Wall -Wextra -Ofast " )
set( CMAKE_CXX_FLAGS " -Wall -Wextra -Wno-nan-infinity-disabled -Ofast " )
endif(MSVC)

find_package(OpenSSL REQUIRED)
Expand Down
15 changes: 13 additions & 2 deletions Discord.C++/Discord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,7 @@ void DiscordCPP::Discord::on_websocket_incoming_message(const json &payload) {
}
}

void DiscordCPP::Discord::handle_raw_event(const std::string &event_name,
const json &data) {
void DiscordCPP::Discord::handle_raw_event(const std::string &event_name, const json &data) {
// https://discordapp.com/developers/docs/topics/gateway#commands-and-events-gateway-events
if (event_name == "READY") {
_user = new User(data.at("user"), get_token());
Expand Down Expand Up @@ -409,6 +408,18 @@ void DiscordCPP::Discord::handle_raw_event(const std::string &event_name,
log.error("ignoring exception in on_message_delete: " + std::string(e.what()));
}
}
} else if (event_name == "MESSAGE_REACTION_ADD") {
try {
on_message_reaction(Reaction(data, get_token()));
} catch (const std::exception &e) {
log.error("ignoring exception in on_message_reaction: " + std::string(e.what()));
}
} else if (event_name == "MESSAGE_REACTION_REMOVE") {
try {
on_message_reaction_delete(Reaction(data, get_token()));
} catch (const std::exception &e) {
log.error("ignoring exception in on_message_reaction_remove: " + std::string(e.what()));
}
} else if (event_name == "TYPING_START") {
std::string channel_id = data.at("channel_id").get<std::string>();
User user;
Expand Down
12 changes: 12 additions & 0 deletions Discord.C++/Discord.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "DMChannel.h"
#include "DiscordObject.h"
#include "Embed.h"
#include "Emoji.h"
#include "Exceptions.h"
#include "FFmpegAudioSource.h"
#include "FileAudioSource.h"
Expand All @@ -22,6 +23,7 @@
#include "Logger.h"
#include "MainGateway.h"
#include "Message.h"
#include "Reaction.h"
#include "Threadpool.h"
#include "User.h"
#include "VoiceChannel.h"
Expand Down Expand Up @@ -82,6 +84,16 @@ class Discord : public DiscordObject {
*/
virtual void on_message_delete(Message message) {}

/** called when a Reaction was added to Message
@param[in] reaction the reaction that has been created
*/
virtual void on_message_reaction(Reaction reaction) {}

/** called when a Reaction was remove from a Message
@param[in] reaction the reaction that has been deleted
*/
virtual void on_message_reaction_delete(Reaction reaction) {}

/** called when a Member was banned
@param[in] user the User who has been banned
@param[in] guild the Guild the User has been banned from
Expand Down
14 changes: 9 additions & 5 deletions Discord.C++/DiscordObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,21 @@ static bool cache_manager_active = false;

void manage_cache();

DiscordCPP::DiscordObject::DiscordObject(std::string token)
DiscordCPP::BaseDiscordObject::BaseDiscordObject(std::string token)
: _token(std::move(token)) {
if (cache_manager_active == false) {
cache_manager_active = true;
manage_cache();
}
}

DiscordCPP::DiscordObject::DiscordObject(std::string token)
: DiscordCPP::BaseDiscordObject::BaseDiscordObject(token) {
}

DiscordCPP::DiscordObject::DiscordObject(std::string token, std::string id)
: _token(std::move(token)),
id(std::move(id)) {
: DiscordCPP::BaseDiscordObject::BaseDiscordObject(token) {
this->id = std::move(id);
}

void manage_cache() {
Expand Down Expand Up @@ -68,7 +72,7 @@ void manage_cache() {
@return json::value API response
@throws HTTPError
*/
json DiscordCPP::DiscordObject::api_call(const std::string& url, const std::string& method, const json& data, const std::string& content_type, const bool cache) {
json DiscordCPP::BaseDiscordObject::api_call(const std::string& url, const std::string& method, const json& data, const std::string& content_type, const bool cache) {
if (method == "GET" && cache == true) {
for (auto& i : _cache) {
if (i->at("url").get<std::string>() == url) {
Expand Down Expand Up @@ -133,7 +137,7 @@ json DiscordCPP::DiscordObject::api_call(const std::string& url, const std::stri
return ret;
}

DiscordCPP::DiscordObject::http_response DiscordCPP::DiscordObject::request_internal(const std::string& target, const std::string& method, const std::string& data, const std::string& content_type) {
DiscordCPP::BaseDiscordObject::http_response DiscordCPP::BaseDiscordObject::request_internal(const std::string& target, const std::string& method, const std::string& data, const std::string& content_type) {
Logger("discord.object.request_internal").debug("sending message " + data + " via " + method + " to https://" + DISCORD_HOST + target);

ssl::context ssl_context(ssl::context::tlsv13);
Expand Down
21 changes: 16 additions & 5 deletions Discord.C++/DiscordObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
#include <map>
#include <string>

#include "Exceptions.h"
#include "static.h"

namespace DiscordCPP {

class DiscordObject {
class BaseDiscordObject {
private:
struct http_response {
unsigned int status_code;
Expand All @@ -19,19 +20,29 @@ class DiscordObject {
/// token to authentificate with the discord api
std::string _token;

/// the id of the object
std::string id;

protected:
[[nodiscard]] std::string get_token() const { return _token; }
/// helper function to communicate with the http api
json api_call(const std::string& url, const std::string& method = "GET", const json& data = json(), const std::string& content_type = "", const bool cache = true);

public:
DLL_EXPORT BaseDiscordObject() = default;
/// @param[in] token Discord token
DLL_EXPORT explicit BaseDiscordObject(std::string token);
};

class DiscordObject : public BaseDiscordObject {
private:
/// the id of the object
std::string id;

public:
DLL_EXPORT DiscordObject() = default;
/// @param[in] token Discord token
DLL_EXPORT explicit DiscordObject(std::string token);
/// @param[in] token Discord token
/** @param[in] token Discord token
@param[in] id the object's id
*/
DLL_EXPORT explicit DiscordObject(std::string token, std::string id);

/// @return the id of the object
Expand Down
20 changes: 20 additions & 0 deletions Discord.C++/Emoji.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "Emoji.h"

DiscordCPP::Emoji::Emoji(const json& data, const std::string& token)
: DiscordObject(token, data.at("id").get<std::string>()) {
name = get_optional<std::string>(data, "name");

if (has_value(data, "roles")) {
for (json role : data.at("roles")) {
role_ids.push_back(role.get<std::string>());
}
}
if (has_value(data, "data")) {
user = User(data.at("user"), get_token());
}

require_colons = get_or_else<bool>(data, "require_colons", false);
managed = get_or_else<bool>(data, "managed", false);
animated = get_or_else<bool>(data, "animated", false);
available = get_or_else<bool>(data, "available", true);
}
47 changes: 47 additions & 0 deletions Discord.C++/Emoji.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include <optional>
#include <string>
#include <vector>

#include "DiscordObject.h"
#include "User.h"

namespace DiscordCPP {
class Emoji : public DiscordObject {
private:
/// emoji name
std::optional<std::string> name;
/// roles allowed to use this emoji
std::vector<std::string> role_ids;
/// user that created this emoji
std::optional<User> user;
/// wether this emoji must be wrapped in colons
bool require_colons;
/// wether this emoji is managed
bool managed;
/// wether this emoji is animated
bool animated;
/// whether this emoji can be used, may be false due to loss of Server Boosts
bool available;

public:
DLL_EXPORT Emoji() = default;
DLL_EXPORT Emoji(const json& data, const std::string& token);

/// @return emoji name
std::optional<std::string> get_name() { return name; }
/// @return roles allowed to use this emoji
std::vector<std::string> get_role_ids() { return role_ids; }
/// @return user that created this emoji
std::optional<User> get_user() { return user; }
/// @return wether this emoji must be wrapped in colons
bool requires_colons() { return require_colons; }
/// @return wether this emoji is managed
bool is_managed() { return managed; }
/// @return wether this emoji is animated
bool is_animated() { return animated; }
/// @return whether this emoji can be used, may be false due to loss of Server Boosts
bool is_available() { return available; }
};
} // namespace DiscordCPP
1 change: 0 additions & 1 deletion Discord.C++/Message.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#pragma once
#include <iostream>

#include "DiscordObject.h"
#include "Embed.h"
Expand Down
64 changes: 64 additions & 0 deletions Discord.C++/Reaction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "Reaction.h"

DiscordCPP::Reaction::Reaction(const json& data, const std::string& token) : BaseDiscordObject(token) {
user_id = data.at("user_id").get<std::string>();
channel_id = data.at("channel_id").get<std::string>();
message_id = data.at("message_id").get<std::string>();
guild_id = get_optional<std::string>(data, "guild_id");

if (has_value(data, "member")) {
member = Member(data.at("member"), token);
}

emoji = Emoji(data.at("emoji"), get_token());
message_author_id = get_optional<std::string>(data, "message_author_id");
burst = get_or_else<bool>(data, "burst", false);

if (has_value(data, "burst_colors")) {
for (json color : data.at("burst_colors")) {
burst_colors.push_back(color.get<std::string>());
}
}

type = static_cast<Type>(data.at("type").get<int>());
}

DiscordCPP::User DiscordCPP::Reaction::get_user() {
if (!user.has_value()) {
user = User(user_id, get_token());
}

return user.value();
}

DiscordCPP::TextChannel DiscordCPP::Reaction::get_channel() {
if (!channel.has_value()) {
channel = TextChannel(channel_id, get_token());
}

return channel.value();
}

DiscordCPP::Message DiscordCPP::Reaction::get_message() {
if (!message.has_value()) {
message = Message(message_id, get_token());
}

return message.value();
}

std::optional<DiscordCPP::Guild> DiscordCPP::Reaction::get_guild() {
if (!guild_id.has_value() && guild_id.has_value()) {
guild = Guild(nullptr, guild_id.value(), get_token());
}

return guild;
}

std::optional<DiscordCPP::User> DiscordCPP::Reaction::get_message_author() {
if (!message_author.has_value() && message_author_id.has_value()) {
message_author = User(message_author_id.value(), get_token());
}

return message_author;
}
90 changes: 90 additions & 0 deletions Discord.C++/Reaction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#pragma once

#include <optional>
#include <string>
#include <vector>

#include "DiscordObject.h"
#include "Emoji.h"
#include "Guild.h"
#include "Member.h"
#include "Message.h"
#include "TextChannel.h"
#include "Threadpool.h"
#include "User.h"

namespace DiscordCPP {
class Reaction : public BaseDiscordObject {
public:
enum Type {
NORMAL = 0,
BURST = 1
};

private:
/// id of the user
std::string user_id;
/// the user who sent the reaction
std::optional<User> user;
/// id of the channel
std::string channel_id;
/// the channel of the message
std::optional<TextChannel> channel;
/// id of the message
std::string message_id;
/// the message of this reaction
std::optional<Message> message;
/// id of the guild
std::optional<std::string> guild_id;
/// the guild of the channel
std::optional<Guild> guild;
/// the guild member who reacted
std::optional<Member> member;
/// emoji used to react
Emoji emoji;
/// id of the message author
std::optional<std::string> message_author_id;
/// the message author
std::optional<User> message_author;
/// true if this is a super reaction
bool burst;
/// colors used for super reaction im #rrggbb format
std::vector<std::string> burst_colors;
/// the type of the reaction
Type type;

public:
DLL_EXPORT Reaction(const json& data, const std::string& token);

/// @return id of the user
std::string get_user_id() { return user_id; }
/// @return the user who sent the reaction
User get_user();
/// @return id of the channel
std::string get_channel_id() { return channel_id; }
/// @return the channel of the message
TextChannel get_channel();
/// @return id of the message
std::string get_message_id() { return message_id; }
/// @return the message of this reaction
Message get_message();
/// @return id of the guild
std::optional<std::string> get_guild_id() { return guild_id; }
/// @return the guild of the channel
std::optional<Guild> get_guild();
/// @return the guild member who reacted
std::optional<Member> get_member() { return member; }
/// @return emoji used to react
Emoji get_emoji() { return emoji; }
/// @return id of the message author
std::optional<std::string> get_message_author_id() { return message_author_id; }
/// @return the message author
std::optional<User> get_message_author();
/// @return true if this is a super reaction
bool is_burst() { return burst; }
/// @return colors used for super reaction im #rrggbb format
std::vector<std::string> get_burst_colors() { return burst_colors; }
/// @return the type of the reaction
Type get_type() { return type; }
};
} // namespace DiscordCPP
Loading

0 comments on commit bdaa136

Please sign in to comment.