mirror of
https://gitlab.com/niansa/SomeBot.git
synced 2025-03-06 20:48:26 +01:00
168 lines
9.5 KiB
C++
168 lines
9.5 KiB
C++
#include "../bot.hpp"
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
class Moderation {
|
|
Bot *bot;
|
|
|
|
void db_add_guild(const dpp::snowflake& guild_id) {
|
|
bot->db << "INSERT OR IGNORE INTO moderation_guild_settings (id) VALUES (?);"
|
|
<< std::to_string(guild_id);
|
|
}
|
|
void db_add_member(const dpp::snowflake& guild_id, const dpp::snowflake& user_id) {
|
|
bot->db << "INSERT OR IGNORE INTO moderation_guild_user_warnings (guild_id, user_id) VALUES (?);"
|
|
<< std::to_string(guild_id) << std::to_string(user_id);
|
|
}
|
|
dpp::snowflake get_moderation_role(const dpp::snowflake& guild_id) {
|
|
std::string fres;
|
|
bot->db << "SELECT moderation_role FROM moderation_guild_settings "
|
|
"WHERE id = ?;"
|
|
<< std::to_string(guild_id)
|
|
>> [&] (const std::string& moderation_role) {
|
|
fres = moderation_role;
|
|
};
|
|
return fres.empty()?"0":fres;
|
|
}
|
|
bool has_moderation_role(const dpp::guild_member& member) {
|
|
auto moderation_role = get_moderation_role(member.guild_id);
|
|
if (!moderation_role) {
|
|
return false;
|
|
}
|
|
const auto& roles = member.get_roles();
|
|
return std::find_if(roles.begin(), roles.end(), [moderation_role](auto a) {
|
|
return a == moderation_role;
|
|
}) != roles.end();
|
|
}
|
|
|
|
public:
|
|
Moderation(Bot *_bot) : bot(_bot) {
|
|
bot->db << "CREATE TABLE IF NOT EXISTS moderation_guild_settings ("
|
|
" id TEXT PRIMARY KEY NOT NULL,"
|
|
" moderation_role TEXT,"
|
|
" logs_channel TEXT,"
|
|
" UNIQUE(id)"
|
|
");";
|
|
bot->db << "CREATE TABLE IF NOT EXISTS moderation_guild_user_warnings ("
|
|
" guild_id TEXT NOT NULL,"
|
|
" user_id TEXT NOT NULL,"
|
|
" amount INTEGER,"
|
|
" reasons TEXT,"
|
|
" UNIQUE(guild_id, user_id)"
|
|
");";
|
|
|
|
bot->add_chatcommand(Bot::ChatCommand({"purge"}, "Delete recent messages", dpp::slashcommand().add_option(dpp::command_option(dpp::command_option_type::co_integer, "amount", "Amount of messages to delete", true))), [&](const dpp::slashcommand_t& event) {
|
|
unsigned long amount = std::get<long>(event.get_parameter("amount"));
|
|
// Check that user has the correct permissions
|
|
if (!has_moderation_role(event.command.member) && !event.command.get_guild().base_permissions(event.command.member).has(dpp::permissions::p_manage_messages)) {
|
|
event.reply(dpp::message("You need message management permission to use this command.").set_flags(dpp::message_flags::m_ephemeral));
|
|
return;
|
|
}
|
|
// Start message deletion in new thread
|
|
std::thread([this, amount, channel_id = event.command.channel_id, member = event.command.member] () mutable {
|
|
// Collect messages
|
|
std::unordered_map<dpp::snowflake, dpp::message> messages;
|
|
while (amount > 0) {
|
|
try {
|
|
// Get messages
|
|
dpp::snowflake last_msg;
|
|
if (!messages.empty()) {
|
|
last_msg = (*messages.begin()).second.id;
|
|
} else {
|
|
last_msg = 0;
|
|
}
|
|
auto requested_amount = std::min(amount, 100UL);
|
|
auto new_messages = bot->cluster.messages_get_sync(channel_id, 0, last_msg, 0, requested_amount);
|
|
// Update counters
|
|
amount -= new_messages.size();
|
|
// Add them to sorted vector
|
|
for (auto& [message_id, message] : new_messages) {
|
|
messages[message_id] = std::move(message);
|
|
}
|
|
// Break out if requested amount wasn't reached
|
|
if (new_messages.size() < requested_amount) {
|
|
break;
|
|
}
|
|
} catch (...) {
|
|
break;
|
|
}
|
|
}
|
|
// Start deleting messages
|
|
unsigned errors = 0;
|
|
for (const auto& [message_id, message] : messages) {
|
|
try {
|
|
bot->cluster.message_delete_sync(message_id, message.channel_id);
|
|
} catch (...) {
|
|
errors++;
|
|
}
|
|
}
|
|
// Report sucess or errors that might have occured
|
|
std::string message = "On request of "+member.get_mention()+" **"+std::to_string(messages.size()-errors)+"** messages were deleted.";
|
|
if (errors) {
|
|
message += "\n**Warning:** "+std::to_string(errors)+" messages could not be deleted (they may be too old).";
|
|
}
|
|
bot->cluster.message_create(dpp::message(message).set_channel_id(channel_id));
|
|
}).detach();
|
|
// Report success
|
|
event.reply(dpp::message("Done! Starting to delete messages...").set_flags(dpp::message_flags::m_ephemeral));
|
|
});
|
|
bot->add_chatcommand(Bot::ChatCommand({"ban"}, "Ban someone from the server", dpp::slashcommand().add_option(dpp::command_option(dpp::command_option_type::co_user, "member", "Member to ban", true)).add_option(dpp::command_option(dpp::command_option_type::co_string, "reason", "For what reason?", true))), [&](const dpp::slashcommand_t& event) {
|
|
auto member_id = std::get<dpp::snowflake>(event.get_parameter("member"));
|
|
auto reason = std::get<std::string>(event.get_parameter("reason"));
|
|
// Check that user has the correct permissions
|
|
if (!has_moderation_role(event.command.member) && !event.command.get_guild().base_permissions(event.command.member).has(dpp::permissions::p_ban_members)) {
|
|
event.reply(dpp::message("You need the ban permission to use this command.").set_flags(dpp::message_flags::m_ephemeral));
|
|
return;
|
|
}
|
|
// Send ban DM
|
|
dpp::embed embed;
|
|
embed.set_title("You've been banned")
|
|
.set_description("You have been banned from "+event.command.get_guild().name+"!\n\n> "+reason);
|
|
bot->cluster.direct_message_create(member_id, dpp::message().add_embed(embed), [this, member_id, event] (const dpp::confirmation_callback_t& ccb) {
|
|
// Ban
|
|
bot->cluster.guild_ban_add(event.command.guild_id, member_id, 0, [this, event, dm_ccb = ccb] (const dpp::confirmation_callback_t& ccb) {
|
|
if (ccb.is_error()) {
|
|
event.reply(dpp::message("I am not able to ban this member.").set_flags(dpp::message_flags::m_ephemeral));
|
|
// Delete DM message because it's not valid
|
|
if (!dm_ccb.is_error()) {
|
|
auto dm_msg = dm_ccb.get<dpp::message>();
|
|
bot->cluster.message_delete(dm_msg.id, dm_msg.channel_id);
|
|
}
|
|
} else {
|
|
event.reply(dpp::message("Done!").set_flags(dpp::message_flags::m_ephemeral));
|
|
}
|
|
});
|
|
});
|
|
});
|
|
bot->add_chatcommand(Bot::ChatCommand({"kick"}, "Kick someone from the server", dpp::slashcommand().add_option(dpp::command_option(dpp::command_option_type::co_user, "member", "Member to kick", true)).add_option(dpp::command_option(dpp::command_option_type::co_string, "reason", "For what reason?", true))), [&](const dpp::slashcommand_t& event) {
|
|
auto member_id = std::get<dpp::snowflake>(event.get_parameter("member"));
|
|
auto reason = std::get<std::string>(event.get_parameter("reason"));
|
|
// Check that user has the correct permissions
|
|
if (!has_moderation_role(event.command.member) && !event.command.get_guild().base_permissions(event.command.member).has(dpp::permissions::p_kick_members)) {
|
|
event.reply(dpp::message("You need the kick permissoin to use this command.").set_flags(dpp::message_flags::m_ephemeral));
|
|
return;
|
|
}
|
|
// Send kick DM
|
|
dpp::embed embed;
|
|
embed.set_title("You've been kicked")
|
|
.set_description("You have been kicked from "+event.command.get_guild().name+"!\n\n> "+reason);
|
|
bot->cluster.direct_message_create(member_id, dpp::message().add_embed(embed), [this, member_id, event] (const dpp::confirmation_callback_t& ccb) {
|
|
// Kick
|
|
bot->cluster.guild_member_kick(event.command.guild_id, member_id, [this, event, dm_ccb = ccb] (const dpp::confirmation_callback_t& ccb) {
|
|
if (ccb.is_error()) {
|
|
event.reply(dpp::message("I am not able to kick this member.").set_flags(dpp::message_flags::m_ephemeral));
|
|
// Delete DM message because it's not valid
|
|
if (!dm_ccb.is_error()) {
|
|
auto dm_msg = dm_ccb.get<dpp::message>();
|
|
bot->cluster.message_delete(dm_msg.id, dm_msg.channel_id);
|
|
}
|
|
} else {
|
|
event.reply(dpp::message("Done!").set_flags(dpp::message_flags::m_ephemeral));
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
};
|
|
BOT_ADD_MODULE(Moderation);
|