1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-11-26 11:07:17 +01:00

Update DPP.

This commit is contained in:
Sandu Liviu Catalin
2021-09-18 21:19:56 +03:00
parent 0f235ff6af
commit b978bc5046
22 changed files with 276 additions and 114 deletions

View File

@@ -327,7 +327,7 @@ void cluster::interaction_response_edit(const std::string &token, const message
void cluster::global_command_create(slashcommand &s, command_completion_event_t callback) {
this->post_rest(API_PATH "/applications", std::to_string(me.id), "commands", m_post, s.build_json(false), [s, callback] (json &j, const http_request_completion_t& http) mutable {
this->post_rest(API_PATH "/applications", std::to_string(s.application_id ? s.application_id : me.id), "commands", m_post, s.build_json(false), [s, callback] (json &j, const http_request_completion_t& http) mutable {
if (j.contains("id")) {
s.id = SnowflakeNotNull(&j, "id");
}
@@ -339,7 +339,7 @@ void cluster::global_command_create(slashcommand &s, command_completion_event_t
}
void cluster::guild_command_create(slashcommand &s, snowflake guild_id, command_completion_event_t callback) {
this->post_rest(API_PATH "/applications", std::to_string(me.id), "guilds/" + std::to_string(guild_id) + "/commands", m_post, s.build_json(false), [s, this, guild_id, callback] (json &j, const http_request_completion_t& http) mutable {
this->post_rest(API_PATH "/applications", std::to_string(s.application_id ? s.application_id : me.id), "guilds/" + std::to_string(guild_id) + "/commands", m_post, s.build_json(false), [s, this, guild_id, callback] (json &j, const http_request_completion_t& http) mutable {
if (j.contains("id")) {
s.id = SnowflakeNotNull(&j, "id");
}
@@ -355,11 +355,14 @@ void cluster::guild_command_create(slashcommand &s, snowflake guild_id, command_
}
void cluster::guild_bulk_command_create(const std::vector<slashcommand> &commands, snowflake guild_id, command_completion_event_t callback) {
if (commands.empty()) {
return;
}
json j = json::array();
for (auto & s : commands) {
j.push_back(json::parse(s.build_json(false)));
}
this->post_rest(API_PATH "/applications", std::to_string(me.id), "guilds/" + std::to_string(guild_id) + "/commands", m_put, j.dump(), [this, callback] (json &j, const http_request_completion_t& http) mutable {
this->post_rest(API_PATH "/applications", std::to_string(commands[0].application_id ? commands[0].application_id : me.id), "guilds/" + std::to_string(guild_id) + "/commands", m_put, j.dump(), [this, callback] (json &j, const http_request_completion_t& http) mutable {
slashcommand_map slashcommands;
for (auto & curr_slashcommand : j) {
slashcommands[SnowflakeNotNull(&curr_slashcommand, "id")] = slashcommand().fill_from_json(&curr_slashcommand);
@@ -371,11 +374,14 @@ void cluster::guild_bulk_command_create(const std::vector<slashcommand> &command
}
void cluster::global_bulk_command_create(const std::vector<slashcommand> &commands, command_completion_event_t callback) {
if (commands.empty()) {
return;
}
json j = json::array();
for (auto & s : commands) {
j.push_back(json::parse(s.build_json(false)));
}
this->post_rest(API_PATH "/applications", std::to_string(me.id), "commands", m_put, j.dump(), [this, callback] (json &j, const http_request_completion_t& http) mutable {
this->post_rest(API_PATH "/applications", std::to_string(commands[0].application_id ? commands[0].application_id : me.id), "commands", m_put, j.dump(), [this, callback] (json &j, const http_request_completion_t& http) mutable {
slashcommand_map slashcommands;
for (auto & curr_slashcommand : j) {
slashcommands[SnowflakeNotNull(&curr_slashcommand, "id")] = slashcommand().fill_from_json(&curr_slashcommand);
@@ -387,7 +393,7 @@ void cluster::global_bulk_command_create(const std::vector<slashcommand> &comman
}
void cluster::global_command_edit(const slashcommand &s, command_completion_event_t callback) {
this->post_rest(API_PATH "/applications", std::to_string(me.id), "commands/" + std::to_string(s.id), m_patch, s.build_json(true), [callback](json &j, const http_request_completion_t& http) {
this->post_rest(API_PATH "/applications", std::to_string(s.application_id ? s.application_id : me.id), "commands/" + std::to_string(s.id), m_patch, s.build_json(true), [callback](json &j, const http_request_completion_t& http) {
if (callback) {
callback(confirmation_callback_t("confirmation", confirmation(), http));
}
@@ -395,7 +401,7 @@ void cluster::global_command_edit(const slashcommand &s, command_completion_even
}
void cluster::guild_command_edit(const slashcommand &s, snowflake guild_id, command_completion_event_t callback) {
this->post_rest(API_PATH "/applications", std::to_string(me.id), "guilds/" + std::to_string(guild_id) + "/commands/" + std::to_string(s.id), m_patch, s.build_json(true), [callback](json &j, const http_request_completion_t& http) {
this->post_rest(API_PATH "/applications", std::to_string(s.application_id ? s.application_id : me.id), "guilds/" + std::to_string(guild_id) + "/commands/" + std::to_string(s.id), m_patch, s.build_json(true), [callback](json &j, const http_request_completion_t& http) {
if (callback) {
callback(confirmation_callback_t("confirmation", confirmation(), http));
}
@@ -414,7 +420,7 @@ void cluster::guild_command_edit_permissions(const slashcommand &s, snowflake gu
}
}
this->post_rest(API_PATH "/applications", std::to_string(me.id), "guilds/" + std::to_string(guild_id) + "/commands/" + std::to_string(s.id) + "/permissions", m_put, j.dump(), [callback](json &j, const http_request_completion_t& http) {
this->post_rest(API_PATH "/applications", std::to_string(s.application_id ? s.application_id : me.id), "guilds/" + std::to_string(guild_id) + "/commands/" + std::to_string(s.id) + "/permissions", m_put, j.dump(), [callback](json &j, const http_request_completion_t& http) {
if (callback) {
callback(confirmation_callback_t("confirmation", confirmation(), http));
}
@@ -1040,7 +1046,7 @@ void cluster::guild_ban_add(snowflake guild_id, snowflake user_id, uint32_t dele
j["reason"] = reason;
if (delete_message_days)
j["delete_message_days"] = delete_message_days;
this->post_rest(API_PATH "/guilds", std::to_string(guild_id), "bans/" + std::to_string(user_id), m_put, "", [callback](json &j, const http_request_completion_t& http) {
this->post_rest(API_PATH "/guilds", std::to_string(guild_id), "bans/" + std::to_string(user_id), m_put, j.dump(), [callback](json &j, const http_request_completion_t& http) {
if (callback) {
callback(confirmation_callback_t("confirmation", confirmation(), http));
}
@@ -1656,7 +1662,7 @@ void cluster::execute_webhook(const class webhook &wh, const struct message& m,
if (thread_id) {
parameters.append("&thread_id=" + std::to_string(thread_id));
}
this->post_rest(API_PATH "/webhooks", std::to_string(wh.id), dpp::url_encode(token), m_post, m.build_json(false), [callback](json &j, const http_request_completion_t& http) {
this->post_rest(API_PATH "/webhooks", std::to_string(wh.id), dpp::url_encode(!wh.token.empty() ? wh.token: token), m_post, m.build_json(false), [callback](json &j, const http_request_completion_t& http) {
if (callback) {
callback(confirmation_callback_t("message", message().fill_from_json(&j), http));
}
@@ -1665,7 +1671,7 @@ void cluster::execute_webhook(const class webhook &wh, const struct message& m,
void cluster::get_webhook_message(const class webhook &wh, command_completion_event_t callback)
{
this->post_rest(API_PATH "/webhooks", std::to_string(wh.id), dpp::url_encode(token) + "/messages/@original", m_get, "", [callback](json &j, const http_request_completion_t &http){
this->post_rest(API_PATH "/webhooks", std::to_string(wh.id), dpp::url_encode(!wh.token.empty() ? wh.token: token) + "/messages/@original", m_get, "", [callback](json &j, const http_request_completion_t &http){
if (callback){
callback(confirmation_callback_t("message", message().fill_from_json(&j), http));
}
@@ -1673,7 +1679,7 @@ void cluster::get_webhook_message(const class webhook &wh, command_completion_ev
}
void cluster::edit_webhook_message(const class webhook &wh, const struct message& m, command_completion_event_t callback) {
this->post_rest(API_PATH "/webhooks", std::to_string(wh.id), dpp::url_encode(token) + "/messages/" + std::to_string(m.id), m_patch, m.build_json(false), [callback](json &j, const http_request_completion_t& http) {
this->post_rest(API_PATH "/webhooks", std::to_string(wh.id), dpp::url_encode(!wh.token.empty() ? wh.token: token) + "/messages/" + std::to_string(m.id), m_patch, m.build_json(false), [callback](json &j, const http_request_completion_t& http) {
if (callback) {
callback(confirmation_callback_t("message", message().fill_from_json(&j), http));
}
@@ -1681,7 +1687,7 @@ void cluster::edit_webhook_message(const class webhook &wh, const struct message
}
void cluster::delete_webhook_message(const class webhook &wh, snowflake message_id, command_completion_event_t callback) {
this->post_rest(API_PATH "/webhooks", std::to_string(wh.id), dpp::url_encode(token) + "/messages/" + std::to_string(message_id), m_delete, "", [callback](json &j, const http_request_completion_t& http) {
this->post_rest(API_PATH "/webhooks", std::to_string(wh.id), dpp::url_encode(!wh.token.empty() ? wh.token: token) + "/messages/" + std::to_string(message_id), m_delete, "", [callback](json &j, const http_request_completion_t& http) {
if (callback) {
callback(confirmation_callback_t("confirmation", confirmation(), http));
}

View File

@@ -155,6 +155,10 @@ bool commandhandler::string_has_prefix(std::string &str)
return false;
}
/* Note that message based command routing relies on cache to resolve ping types (e.g. user, channel ping).
* There isn't really a way around this for many things because there is no 'resolved' member for it.
* We only get resolved information for the user issuing the command.
*/
void commandhandler::route(const dpp::message& msg)
{
std::string msg_content = msg.content;
@@ -226,8 +230,15 @@ void commandhandler::route(const dpp::message& msg)
snowflake uid = from_string<uint64_t>(x.substr(2, x.length() - 1), std::dec);
user* u = dpp::find_user(uid);
if (u) {
param = *u;
dpp::resolved_user m;
m.user = *u;
dpp::guild* g = dpp::find_guild(msg.guild_id);
if (g->members.find(uid) != g->members.end()) {
m.member = g->members[uid];
}
param = m;
}
}
}
break;
@@ -270,6 +281,7 @@ void commandhandler::route(const interaction_create_t & event)
* dont have prefixes at all.
*/
command_interaction cmd = std::get<command_interaction>(event.command.data);
auto found_cmd = commands.find(lowercase(cmd.name));
if (found_cmd != commands.end()) {
/* Command found; parse parameters */
@@ -277,57 +289,86 @@ void commandhandler::route(const interaction_create_t & event)
for (auto& p : found_cmd->second.parameters) {
command_parameter param;
const command_value& slash_parameter = event.get_parameter(p.first);
dpp::command_resolved res = event.command.resolved;
if (p.second.optional && slash_parameter.valueless_by_exception()) {
if (p.second.optional && slash_parameter.index() == 0 /* std::monostate */) {
/* Missing optional parameter, skip this */
continue;
}
try {
switch (p.second.type) {
case pt_string: {
std::string s = std::get<std::string>(slash_parameter);
param = s;
}
break;
case pt_role: {
snowflake rid = std::get<snowflake>(slash_parameter);
role* r = dpp::find_role(rid);
if (r) {
param = *r;
}
}
break;
case pt_channel: {
snowflake cid = std::get<snowflake>(slash_parameter);
channel* c = dpp::find_channel(cid);
if (c) {
param = *c;
}
}
break;
case pt_user: {
snowflake uid = std::get<snowflake>(slash_parameter);
user* u = dpp::find_user(uid);
if (u) {
param = *u;
}
}
break;
case pt_integer: {
int32_t i = std::get<int32_t>(slash_parameter);
param = i;
}
case pt_boolean: {
bool b = std::get<bool>(slash_parameter);
param = b;
}
break;
switch (p.second.type) {
case pt_string: {
std::string s = std::get<std::string>(slash_parameter);
param = s;
}
}
catch (const std::bad_variant_access& e) {
/* Missing optional parameter, skip this */
continue;
break;
case pt_role: {
snowflake rid = std::get<snowflake>(slash_parameter);
role* r = dpp::find_role(rid);
if (r) {
/* Use cache if the role is in the cache */
param = *r;
} else {
/* Otherwise use interaction resolved fields */
if (res.roles.find(rid) != res.roles.end()) {
param = res.roles[rid];
}
}
}
break;
case pt_channel: {
snowflake cid = std::get<snowflake>(slash_parameter);
channel* c = dpp::find_channel(cid);
if (c) {
/* Use cache if the channel is in the cache */
param = *c;
} else {
/* Otherwise use interaction resolved fields */
if (res.channels.find(cid) != res.channels.end()) {
param = res.channels[cid];
}
}
}
break;
case pt_user: {
snowflake uid = std::get<snowflake>(slash_parameter);
/* TODO: Make this used resolved, not cache */
user* u = dpp::find_user(uid);
if (u) {
/* Use the cache if the user is in the cache */
dpp::resolved_user m;
m.user = *u;
dpp::guild* g = dpp::find_guild(event.command.guild_id);
if (g->members.find(uid) != g->members.end()) {
m.member = g->members[uid];
}
param = m;
} else {
/* Otherwise use interaction resolved fields */
if (
event.command.resolved.users.find(uid) != event.command.resolved.users.end()
&&
event.command.resolved.members.find(uid) != event.command.resolved.members.end()
) {
/* Fill in both member and user info */
dpp::resolved_user m;
m.member = res.members[uid];
m.user = res.users[uid];
param = m;
}
}
}
break;
case pt_integer: {
int32_t i = std::get<int32_t>(slash_parameter);
param = i;
}
break;
case pt_boolean: {
bool b = std::get<bool>(slash_parameter);
param = b;
}
break;
}
/* Add parameter to the list */
@@ -357,4 +398,20 @@ void commandhandler::reply(const dpp::message &m, command_source source)
}
}
void commandhandler::thinking(command_source source)
{
dpp::message msg;
msg.content = "*";
msg.guild_id = source.guild_id;
msg.channel_id = source.channel_id;
if (!source.command_token.empty() && source.command_id) {
owner->interaction_response_create(source.command_id, source.command_token, dpp::interaction_response(ir_deferred_channel_message_with_source, msg));
}
}
void commandhandler::thonk(command_source source)
{
thinking(source);
}
};

View File

@@ -329,7 +329,7 @@ void discord_client::Error(uint32_t errorcode)
{ 1003, "Endpoint received an unsupported frame" },
{ 1004, "Reserved code" },
{ 1005, "Expected close status, received none" },
{ 1006, "No close code frame has been receieved" },
{ 1006, "No close code frame has been received" },
{ 1007, "Endpoint received inconsistent message (e.g. malformed UTF-8)" },
{ 1008, "Generic error" },
{ 1009, "Endpoint won't process large frame" },

View File

@@ -42,7 +42,7 @@ char* strptime(const char* s, const char* f, struct tm* tm) {
input.imbue(std::locale(setlocale(LC_ALL, nullptr)));
input >> std::get_time(tm, f);
if (input.fail()) {
return const_cast< char* >("");
return "";
}
return (char*)(s + input.tellg());
}
@@ -79,7 +79,7 @@ std::string StringNotNull(const json* j, const char *keyname) {
if (k != j->end()) {
return !k->is_null() && k->is_string() ? k->get<std::string>() : "";
} else {
return "";
return const_cast< char* >("");
}
}
@@ -311,7 +311,7 @@ void discord_client::HandleEvent(const std::string &event, json &j, const std::s
auto ev_iter = eventmap.find(event);
if (ev_iter != eventmap.end()) {
/* A handler with nullptr is silently ignored. We don't plan to make a handler for it
* so this usually some user-only thing thats crept into the API and shown to bots
* so this usually some user-only thing that's crept into the API and shown to bots
* that we dont care about.
*/
if (ev_iter->second != nullptr) {

View File

@@ -450,7 +450,7 @@ void discord_voice_client::Error(uint32_t errorcode)
{ 1003, "Endpoint received an unsupported frame" },
{ 1004, "Reserved code" },
{ 1005, "Expected close status, received none" },
{ 1006, "No close code frame has been receieved" },
{ 1006, "No close code frame has been received" },
{ 1007, "Endpoint received inconsistent message (e.g. malformed UTF-8)" },
{ 1008, "Generic error" },
{ 1009, "Endpoint won't process large frame" },

View File

@@ -517,11 +517,13 @@ reaction::reaction(json* j) {
emoji_name = StringNotNull(&emoji, "name");
}
attachment::attachment() {
id = 0;
size = 0;
width = 0;
height = 0;
attachment::attachment()
: id(0)
, size(0)
, width(0)
, height(0)
, ephemeral(false)
{
}
attachment::attachment(json *j) : attachment() {
@@ -533,6 +535,7 @@ attachment::attachment(json *j) : attachment() {
this->width = Int32NotNull(j, "width");
this->height = Int32NotNull(j, "height");
this->content_type = StringNotNull(j, "content_type");
this->ephemeral = BoolNotNull(j, "ephemeral");
}
std::string message::build_json(bool with_id, bool is_interaction_response) const {
@@ -553,6 +556,11 @@ std::string message::build_json(bool with_id, bool is_interaction_response) cons
j["content"] = content;
}
if(author != nullptr) {
/* Used for webhooks */
j["username"] = author->username;
}
/* Populate message reference */
if (message_reference.channel_id || message_reference.guild_id || message_reference.message_id) {
j["message_reference"] = json::object();
@@ -740,8 +748,8 @@ bool message::is_crosspost() const {
}
bool message::supress_embeds() const {
return flags & m_supress_embeds;
bool message::suppress_embeds() const {
return flags & m_suppress_embeds;
}
bool message::is_source_message_deleted() const {

View File

@@ -285,7 +285,7 @@ void request_queue::in_loop()
auto currbucket = buckets.find(bucket.first);
if (currbucket != buckets.end()) {
/* Theres a bucket for this request. Check its status. If the bucket says to wait,
/* There's a bucket for this request. Check its status. If the bucket says to wait,
* skip all requests in this bucket till its ok.
*/
if (currbucket->second.remaining < 1) {

View File

@@ -125,6 +125,7 @@ void to_json(json& j, const slashcommand& p) {
}
j["default_permission"] = p.default_permission;
j["application_id"] = std::to_string(p.application_id);
}
std::string slashcommand::build_json(bool with_id) const {
@@ -271,7 +272,6 @@ void from_json(const nlohmann::json& j, interaction& i) {
SetSnowflakeNotNull(&m, "id", i.message_id);
}
i.type = Int8NotNull(&j, "type");
i.token = StringNotNull(&j, "token");
i.version = Int8NotNull(&j, "version");
@@ -284,6 +284,47 @@ void from_json(const nlohmann::json& j, interaction& i) {
}
if (j.contains("data") && !j.at("data").is_null()) {
const json& data = j["data"];
/* Deal with 'resolved' data, e.g. users, members, roles, channels */
if (data.find("resolved") != data.end()) {
const json& d_resolved = data["resolved"];
/* Users */
if (d_resolved.find("users") != d_resolved.end()) {
for (auto v = d_resolved["users"].begin(); v != d_resolved["users"].end(); ++v) {
json f = *v;
dpp::snowflake id = strtoull(v.key().c_str(), nullptr, 10);
i.resolved.users[id] = dpp::user().fill_from_json(&f);
}
}
/* Roles */
if (d_resolved.find("roles") != d_resolved.end()) {
for (auto v = d_resolved["roles"].begin(); v != d_resolved["roles"].end(); ++v) {
json f = *v;
dpp::snowflake id = strtoull(v.key().c_str(), nullptr, 10);
i.resolved.roles[id] = dpp::role().fill_from_json(i.guild_id, &f);
}
}
/* Channels */
if (d_resolved.find("channels") != d_resolved.end()) {
for (auto v = d_resolved["channels"].begin(); v != d_resolved["channels"].end(); ++v) {
json f = *v;
dpp::snowflake id = strtoull(v.key().c_str(), nullptr, 10);
i.resolved.channels[id] = dpp::channel().fill_from_json(&f);
}
}
/* Members */
if (d_resolved.find("members") != d_resolved.end()) {
for (auto v = d_resolved["members"].begin(); v != d_resolved["members"].end(); ++v) {
json f = *v;
dpp::snowflake id = strtoull(v.key().c_str(), nullptr, 10);
i.resolved.members[id] = dpp::guild_member().fill_from_json(&f, i.guild_id, id);
}
}
}
if (i.type == it_application_command) {
command_interaction ci;
j.at("data").get_to(ci);

View File

@@ -25,7 +25,7 @@
using json = nlohmann::json;
/* A mapping of discord's flag values to our bitmap (theyre different bit positions to fit other stuff in) */
/* A mapping of discord's flag values to our bitmap (they're different bit positions to fit other stuff in) */
std::map<uint32_t, dpp::user_flags> usermap = {
{ 1 << 0, dpp::u_discord_employee },
{ 1 << 1, dpp::u_partnered_owner },
@@ -57,7 +57,7 @@ user::~user()
}
std::string user::get_avatar_url() const {
/* XXX: Discord were supposed to change their CDN over to discord.com, they havent.
/* XXX: Discord were supposed to change their CDN over to discord.com, they haven't.
* At some point in the future this URL *will* change!
*/
return fmt::format("https://cdn.discordapp.com/avatars/{}/{}{}.{}",

View File

@@ -51,8 +51,8 @@ voicestate& voicestate::fill_from_json(nlohmann::json* j) {
flags |= vs_self_stream;
if (BoolNotNull(j, "self_video"))
flags |= vs_self_video;
if (BoolNotNull(j, "supress"))
flags |= vs_supress;
if (BoolNotNull(j, "suppress"))
flags |= vs_suppress;
return *this;
}
@@ -80,8 +80,8 @@ bool voicestate::self_video() const {
return flags & vs_self_video;
}
bool voicestate::is_supressed() const {
return flags & vs_supress;
bool voicestate::is_suppressed() const {
return flags & vs_suppress;
}
std::string voicestate::build_json() const {

View File

@@ -304,7 +304,7 @@ void websocket_client::HandlePingPong(bool ping, const std::string &payload)
{
unsigned char out[MAXHEADERSIZE];
if (ping) {
/* For receving pings we echo back their payload with the type OP_PONG */
/* For receiving pings we echo back their payload with the type OP_PONG */
size_t s = this->FillHeader(out, payload.length(), OP_PONG);
std::string header((const char*)out, s);
ssl_client::write(header);