Skip to content

Commit afac39c

Browse files
authored
Work around Discord's privileged intents restrictions (#1294)
* Work around the upcoming restrictions to Discord's privileged intents, implement a button to register slash commands, fix and improve readability of certain commands. * Implement requested fixes.
1 parent 99dc0c8 commit afac39c

6 files changed

Lines changed: 93 additions & 93 deletions

File tree

SerialPrograms/Source/Integrations/DiscordIntegrationSettings.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ DiscordIntegrationSettingsOption::DiscordIntegrationSettingsOption()
3232
LockMode::LOCK_WHILE_RUNNING,
3333
false
3434
)
35+
, register_slash_button(
36+
"<b>Register Slash Commands on Start:</b><br>Only needs to be run once, or after additional commands are added.",
37+
"Register Slash Commands"
38+
)
3539
, command_type(
3640
"<b>Discord Integration Command Type:</b><br>Restart the program for this to take effect.",
3741
{
@@ -72,6 +76,7 @@ DiscordIntegrationSettingsOption::DiscordIntegrationSettingsOption()
7276
)
7377
{
7478
PA_ADD_OPTION(run_on_start);
79+
PA_ADD_OPTION(register_slash_button);
7580
PA_ADD_OPTION(command_type);
7681
PA_ADD_OPTION(token);
7782
PA_ADD_OPTION(command_prefix);

SerialPrograms/Source/Integrations/DiscordIntegrationSettings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "Common/Cpp/Options/BooleanCheckBoxOption.h"
1313
#include "Common/Cpp/Options/StringOption.h"
1414
#include "Common/Cpp/Options/EnumDropdownOption.h"
15+
#include "Common/Cpp/Options/ButtonOption.h"
1516
#include "Common/Qt/Options/GroupWidget.h"
1617
#include "DiscordIntegrationTable.h"
1718

@@ -30,6 +31,7 @@ class DiscordIntegrationSettingsOption
3031
virtual void on_config_value_changed(void* object) override;
3132

3233
BooleanCheckBoxOption run_on_start;
34+
ButtonOption register_slash_button;
3335

3436
enum class CommandType{
3537
SlashCommands,

SerialPrograms/Source/Integrations/DppIntegration/DppClient.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Client& Client::instance(){
2929

3030

3131
Client::~Client(){
32+
GlobalSettings::instance().DISCORD->integration.register_slash_button.remove_listener(*this);
3233
disconnect();
3334
}
3435

@@ -48,7 +49,12 @@ void Client::connect(){
4849
return;
4950

5051
std::string token = settings.integration.token;
51-
uint32_t intents = intents::i_default_intents | intents::i_guild_members | intents::i_message_content;
52+
auto cmd_type = GlobalSettings::instance().DISCORD->integration.command_type.get();
53+
uint32_t intents = intents::i_default_intents;
54+
if (cmd_type == DiscordIntegrationSettingsOption::CommandType::MessageCommands){
55+
intents = intents::i_default_intents | intents::i_message_content;
56+
}
57+
5258
try{
5359
m_bot = std::make_unique<cluster>(token, intents);
5460
m_handler = std::make_unique<commandhandler>(m_bot.get(), false);
@@ -154,14 +160,8 @@ void Client::run(const std::string& token){
154160
Handler::initialize(*m_bot.get(), *m_handler.get());
155161
m_bot->set_websocket_protocol(websocket_protocol_t::ws_etf);
156162
m_bot->start(st_return);
157-
m_bot->set_presence(
158-
presence(
159-
presence_status::ps_online,
160-
activity_type::at_game,
161-
(std::string)GlobalSettings::instance().DISCORD->integration.game_status
162-
)
163-
);
164163
m_is_connected.store(true, std::memory_order_release);
164+
GlobalSettings::instance().DISCORD->integration.register_slash_button.add_listener(*this);
165165
}catch (std::exception& e){
166166
Handler::log_dpp("DPP thew an exception: " + (std::string)e.what(), "run()", ll_critical);
167167
m_handler.reset();

SerialPrograms/Source/Integrations/DppIntegration/DppClient.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <Integrations/DppIntegration/DppCommandHandler.h>
88
#include "Common/Cpp/Concurrency/AsyncTask.h"
99
#include "CommonFramework/Notifications/MessageAttachment.h"
10+
#include "Common/Cpp/Options/ButtonOption.h"
1011

1112
namespace PokemonAutomation{
1213
class JsonObject;
@@ -15,7 +16,7 @@ namespace DppClient{
1516

1617

1718

18-
class Client : protected DppCommandHandler::Handler{
19+
class Client : protected DppCommandHandler::Handler, public ButtonListener{
1920
public:
2021
Client() : m_is_connected(false) {}
2122
~Client();
@@ -42,12 +43,26 @@ class Client : protected DppCommandHandler::Handler{
4243

4344
private:
4445
void run(const std::string& token);
46+
virtual void on_press() override{
47+
std::lock_guard<std::mutex> lg(m_register_lock);
48+
if (m_handler && m_handler->slash_commands_enabled){
49+
GlobalSettings::instance().DISCORD->integration.register_slash_button.set_enabled(false);
50+
log_dpp("Registering commands...", "Slash Command Registration", dpp::ll_info);
51+
m_handler->register_commands();
52+
log_dpp("Registered commands with Discord. You may have to wait or restart Discord for changes to take effect.", "Slash Command Registration", dpp::ll_info);
53+
GlobalSettings::instance().DISCORD->integration.register_slash_button.set_enabled(true);
54+
return;
55+
}
56+
57+
log_dpp("Failed to register commands. Make sure the bot is connected and Slash commands are enabled.", "Slash Command Registration", dpp::ll_error);
58+
};
4559

4660
private:
4761
std::unique_ptr<dpp::cluster> m_bot = nullptr;
4862
std::unique_ptr<dpp::commandhandler> m_handler = nullptr;
4963
std::atomic<bool> m_is_connected;
5064
std::mutex m_client_lock;
65+
std::mutex m_register_lock;
5166
AsyncTask m_start_thread;
5267
};
5368

SerialPrograms/Source/Integrations/DppIntegration/DppCommandHandler.cpp

Lines changed: 61 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#ifdef PA_DPP
22

33
#include <format>
4+
#include <unordered_set>
45
#include "Common/Cpp/Concurrency/ScheduledTaskRunner.h"
56
#include "CommonFramework/Globals.h"
6-
#include "CommonFramework/GlobalSettingsPanel.h"
77
#include "CommonFramework/Notifications/MessageAttachment.h"
88
#include "Integrations/IntegrationsAPI.h"
99
#include "Integrations/DiscordSettingsOption.h"
@@ -37,7 +37,7 @@ void Handler::initialize(cluster& bot, commandhandler& handler){
3737
if (cmd_type == DiscordIntegrationSettingsOption::CommandType::MessageCommands && !prefix.empty()){
3838
handler.add_prefix(prefix);
3939
}else{
40-
handler.add_prefix("/").add_prefix("_cmd ");
40+
handler.add_prefix("/");
4141
}
4242

4343
bot.on_ready([&bot, &handler, this](const ready_t&){
@@ -53,6 +53,13 @@ void Handler::initialize(cluster& bot, commandhandler& handler){
5353
log_dpp("Application Name: " + app.name, "Current App", ll_info);
5454
log_dpp("Application ID: " + std::to_string(app.id), "Current App", ll_info);
5555
owner = app.owner;
56+
bot.set_presence(
57+
presence(
58+
presence_status::ps_online,
59+
activity_type::at_game,
60+
(std::string)GlobalSettings::instance().DISCORD->integration.game_status
61+
)
62+
);
5663
});
5764
#else
5865
log_dpp("Logged in as: " + bot.current_user_get_sync().format_username() + ".", "Ready", ll_info);
@@ -76,48 +83,18 @@ void Handler::initialize(cluster& bot, commandhandler& handler){
7683
}
7784
});
7885

79-
bot.on_guild_member_add([this](const guild_member_add_t& event){
80-
#if DPP_VERSION_LONG >= 0x00100100 // (dpp version 10.1.0)
81-
std::string id = std::to_string(event.adding_guild.id);
82-
if (!user_counts.empty() && user_counts.count(id)){
83-
log_dpp("New member joined " + event.adding_guild.name + ". Incrementing member count.", "Guild Member Add", ll_info);
84-
user_counts.at(id)++;
85-
}
86-
#else
87-
std::string id = std::to_string(event.adding_guild->id);
88-
if (!user_counts.empty() && user_counts.count(id)){
89-
log_dpp("New member joined " + event.adding_guild->name + ". Incrementing member count.", "Guild Member Add", ll_info);
90-
user_counts.at(id)++;
91-
}
92-
#endif
93-
});
94-
95-
bot.on_guild_member_remove([this](const guild_member_remove_t& event){
96-
#if DPP_VERSION_LONG >= 0x00100100 // (dpp version 10.1.0)
97-
std::string id = std::to_string(event.removing_guild.id);
98-
if (!user_counts.empty() && user_counts.count(id)){
99-
log_dpp("Member left " + event.removing_guild.name + ". Decrementing member count.", "Guild Member Remove", ll_info);
100-
user_counts.at(id)--;
101-
}
102-
#else
103-
std::string id = std::to_string(event.removing_guild->id);
104-
if (!user_counts.empty() && user_counts.count(id)){
105-
log_dpp("Member left " + event.removing_guild->name + ". Decrementing member count.", "Guild Member Remove", ll_info);
106-
user_counts.at(id)--;
107-
}
108-
#endif
109-
});
110-
111-
bot.on_message_create([&handler](const message_create_t& event){
112-
std::string content = event.msg.content;
113-
if (!event.msg.author.is_bot() && handler.string_has_prefix(content)){
114-
auto channels = GlobalSettings::instance().DISCORD->integration.channels.command_channels();
115-
auto channel = std::find(channels.begin(), channels.end(), std::to_string(event.msg.channel_id));
116-
if (channel != channels.end()){
117-
handler.route(event);
86+
if (cmd_type == DiscordIntegrationSettingsOption::CommandType::MessageCommands){
87+
bot.on_message_create([&handler](const message_create_t& event){
88+
std::string content = event.msg.content;
89+
if (!event.msg.author.is_bot() && handler.string_has_prefix(content)){
90+
auto channels = GlobalSettings::instance().DISCORD->integration.channels.command_channels();
91+
auto channel = std::find(channels.begin(), channels.end(), std::to_string(event.msg.channel_id));
92+
if (channel != channels.end()){
93+
handler.route(event);
94+
}
11895
}
119-
}
120-
});
96+
});
97+
}
12198

12299
bot.on_slashcommand([&handler](const slashcommand_t& event){
123100
if (!event.command.usr.is_bot() && handler.slash_commands_enabled){
@@ -611,65 +588,65 @@ void Handler::create_unified_commands(commandhandler& handler){
611588
embed embed;
612589
embed.set_color((uint32_t)color).set_title("Command List");
613590

591+
static const std::unordered_set<std::string> base_commands{
592+
"hi", "ping", "about", "status", "help"
593+
};
594+
static const std::unordered_set<std::string> button_commands{
595+
"click", "joystick"
596+
};
597+
598+
std::unordered_set<std::string> allowed = base_commands;
599+
if (GlobalSettings::instance().DISCORD->integration.allow_buttons_from_users){
600+
allowed.insert(button_commands.begin(), button_commands.end());
601+
}
602+
614603
auto& commands = handler.commands;
615604
for (auto& cmd : commands){
616-
std::string name = cmd.first;
617-
log_dpp(name, "help command", ll_info);
618-
if (!GlobalSettings::instance().DISCORD->integration.allow_buttons_from_users &&
619-
src.issuer.id != owner.id && name != "hi" && name != "ping" && name != "about" && name != "status" && name != "help"
620-
){
605+
const std::string& cmd_name = cmd.first;
606+
if (src.issuer.id != owner.id && allowed.find(cmd_name) == allowed.end()){
621607
continue;
622608
}
623609

624-
std::string param_info;
625-
for (auto& param : cmd.second.parameters){
626-
param_info += ("\n**- " + param.first + "** - " + param.second.description);
610+
auto& params = cmd.second.parameters;
611+
std::string signature;
612+
if (!params.empty()){
613+
signature = cmd_name + "(";
614+
for (size_t i = 0; i < params.size(); ++i){
615+
signature += params[i].first;
616+
if (i + 1 < params.size()){
617+
signature += ", ";
618+
}
619+
}
620+
signature += ")";
621+
}else{
622+
signature = cmd_name;
623+
}
624+
625+
std::string param_details;
626+
for (auto& param : params){
627+
param_details += ("\n-" + param.first + ": " + param.second.description);
627628
if (!param.second.choices.empty()){
628-
param_info += " (";
629-
for (auto& choice : param.second.choices){
630-
param_info += (choice.second + ", ");
629+
std::string choices;
630+
for (auto& c : param.second.choices){
631+
choices += c.second + ", ";
632+
}
633+
if (!choices.empty()){
634+
choices = choices.substr(0, choices.size() - 2);
631635
}
632-
param_info = param_info.substr(0, param_info.size() - 2);
633-
param_info += ")";
636+
param_details += " (" + choices + ")";
634637
}
635638
}
636-
embed.add_field(name, param_info);
639+
embed.add_field(signature, param_details);
637640
}
638641
embed_footer footer;
639642
footer.set_text("Commands are case-sensitive!");
640643
embed.set_footer(footer);
641644
message.add_embed(embed);
642645
handler.reply(message, src);
643646
},
644-
"View the command list.")
645-
646-
.add_command(
647-
"register",
648-
{},
649-
[&handler, this](const std::string& command, const parameter_list_t&, command_source src){
650-
log_dpp("Executing " + command + "...", "Unified Command Handler", ll_info);
651-
if (src.issuer.id != owner.id){
652-
handler.reply(message("You do not have permission to use this command."), src);
653-
return;
654-
}
655-
656-
if (handler.slash_commands_enabled){
657-
handler.thinking(src);
658-
log_dpp("Registering commands.", "Command Registration", ll_info);
659-
handler.register_commands();
660-
661-
embed embed;
662-
std::string desc = "Slash commands registered! Restart your Discord client or wait a few minutes for them to show up!";
663-
embed.set_color((uint32_t)color).set_description(desc).set_title("Slash Command Registration");
664-
Handler::update_response(src, embed, "", nullptr);
665-
}else{
666-
handler.reply(message("Enable slash commands before registering them."), src);
667-
}
668-
},
669-
"Register global slash commands. For first-time slash command use and for updating commands.");
647+
"View the command list.");
670648
}
671649

672-
673650
}
674651
}
675652
}

SerialPrograms/Source/Integrations/DppIntegration/DppCommandHandler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <Integrations/DppIntegration/DppUtility.h>
66
#include "Common/Cpp/Concurrency/ScheduledTaskRunner.h"
77
#include "CommonFramework/Notifications/MessageAttachment.h"
8+
#include "CommonFramework/GlobalSettingsPanel.h"
89
#include "CommonFramework/Tools/GlobalThreadPools.h"
910
#include "Integrations/DiscordSettingsOption.h"
1011

0 commit comments

Comments
 (0)