From 9bff843b6486441b395df363dccf0f789185ac46 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 15 Aug 2026 19:26:06 +0300 Subject: [PATCH] Upgraded beginner command, coding command, added security checks to suggestion.cpp --- CMakeLists.txt | 8 +- README.md | 15 +- src/commands/beginner.cpp | 54 +++++++ src/commands/coding_cmd.cpp | 97 +++++++++++- src/commands/commands.h | 30 +++- src/commands/project_cmd.cpp | 65 ++++---- src/config.json | 1 - src/config.json.example | 10 ++ src/globals/globals.cpp | 102 +++++++++++++ src/globals/globals.h | 28 +++- src/main.cpp | 52 +++++-- src/res/coding/advanced.txt | 60 ++++++++ src/res/coding/beginner.txt | 46 ++++++ src/res/{ => coding}/coding.txt | 0 src/res/coding/expert.txt | 88 +++++++++++ src/res/coding/intermediate.txt | 64 ++++++++ src/res/coding/master.txt | 227 ++++++++++++++++++++++++++++ src/utils/suggestion/suggestion.cpp | 152 +++++++++++++++---- 18 files changed, 991 insertions(+), 108 deletions(-) create mode 100644 src/commands/beginner.cpp delete mode 100644 src/config.json create mode 100644 src/config.json.example create mode 100644 src/globals/globals.cpp create mode 100644 src/res/coding/advanced.txt create mode 100644 src/res/coding/beginner.txt rename src/res/{ => coding}/coding.txt (100%) create mode 100644 src/res/coding/expert.txt create mode 100644 src/res/coding/intermediate.txt create mode 100644 src/res/coding/master.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index be98ca1..35dbed9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,13 +25,18 @@ else() message(STATUS "Using system-installed DPP") endif() -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/config.json DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/config.json) + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/config.json DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +else() + message(STATUS "src/config.json not found; skipping config copy") +endif() file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/res DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) add_executable(bot src/main.cpp #globals + src/globals/globals.cpp src/globals/globals.h # commands @@ -44,6 +49,7 @@ add_executable(bot src/commands/code_cmd.cpp src/commands/project_cmd.cpp src/commands/rule_cmd.cpp + src/commands/beginner.cpp # utils src/utils/suggestion/suggestion.cpp diff --git a/README.md b/README.md index 00120d6..ef758f9 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,20 @@ ```git clone https://github.com/cppdiscord/bot.git``` #### 2. Create the config file -Create a file called config.json in the src directory: ``{ "token": "bot token" }`` +Create a file called config.json in the src directory with the following values: + +```json +{ + "token": "your bot token", + "emoji_yes_id": "your yes emoji id", + "emoji_no_id": "your no emoji id", + "channel_rules_id": "your rules channel id", + "channel_jail_id": "your jail channel id", + "category_ticket_id": "your ticket category id", + "role_staff_id": "your staff role id", + "role_jail_id": "your jail role id" +} +``` ## Contributing We appreciate contributions to this community. Connect with other contributors through our [discord server](https://discord.gg/cpp), where we have dedicated channels for chatting and collaborating. diff --git a/src/commands/beginner.cpp b/src/commands/beginner.cpp new file mode 100644 index 0000000..a9eeb82 --- /dev/null +++ b/src/commands/beginner.cpp @@ -0,0 +1,54 @@ +#include "commands.h" +#include "../globals/globals.h" + +void cmd::beginnerCommand(dpp::cluster& bot, const dpp::slashcommand_t& event) +{ + const dpp::embed embed = dpp::embed() + .set_color(globals::color::defaultColor) + .set_title("👋 New to C++? Start here!") + .set_url("https://www.learncpp.com/") + .set_description("Essential resources for C++ beginners") + .add_field("📘 **Best Beginner Tutorial**", + "LearnCpp.com is widely considered the best free resource:\nhttps://www.learncpp.com/", false) + .add_field("📖 **CPP Reference**", + "The definitive C++ language reference:\nhttps://en.cppreference.com/", false) + .add_field("🛠️ **Practice**", + "Start with small projects:\n" + "- Calculator\n" + "- Guess game\n" + "- Dice game", false) + .add_field("✅ **Do this**", + "- Learn Modern C++\n" + "- Use a great IDE\n" + "- Practice what you learn\n" + "- Learn OOP basics\n" + "- Write clean, readable code", true) + .add_field("❌ **Dont do this**", + "- Don't learn from outdated C++ resources\n" + "- Don't let AI write code for you\n" + "- Don't use `using namespace std;` (it's bad practice)\n" + "- Don't ignore compiler warnings", true) + .set_footer(dpp::embed_footer() + .set_text("Need help? Ask in <#" + std::to_string(globals::channels::HELP_CHANNEL_ID) + ">")) + .set_timestamp(dpp::utility::time_f()); + + dpp::message message(event.command.channel_id, embed); + message.add_component( + dpp::component() + .add_component( + dpp::component() + .set_type(dpp::cot_button) + .set_label("Learn C++") + .set_url("https://www.learncpp.com/") + .set_style(dpp::cos_link) + ) + .add_component( + dpp::component() + .set_type(dpp::cot_button) + .set_label("CPP Reference") + .set_url("https://en.cppreference.com/") + .set_style(dpp::cos_link) + ) + ); + event.reply(message); +} diff --git a/src/commands/coding_cmd.cpp b/src/commands/coding_cmd.cpp index 59fb592..1a8d29d 100644 --- a/src/commands/coding_cmd.cpp +++ b/src/commands/coding_cmd.cpp @@ -1,15 +1,96 @@ #include "commands.h" #include "../globals/globals.h" +#include +#include +#include +#include +#include +#include + +namespace cmd + { + namespace coding + { + const std::map difficultyFiles = { + {"Beginner", "src/res/coding/beginner.txt"}, + {"Intermediate", "src/res/coding/intermediate.txt"}, + {"Advanced", "src/res/coding/advanced.txt"}, + {"Expert", "src/res/coding/expert.txt"}, + {"Master", "src/res/coding/master.txt"} + }; + + std::map> questionCache; + bool loaded = false; + + void loadQuestions() { + if (loaded) return; + + for (const auto& [difficulty, filepath] : difficultyFiles) { + std::ifstream file(filepath); + + if (!file.is_open()) { + std::cerr << "Failed to open: " << filepath << std::endl; + continue; + } + + std::vector questions; + std::string line; + + while (std::getline(file, line)) { + if (!line.empty()) { + questions.push_back(line); + } + } + file.close(); + + std::random_device rd; + std::mt19937 gen(rd()); + std::shuffle(questions.begin(), questions.end(), gen); + + questionCache[difficulty] = questions; + } + loaded = true; + } + + std::string getRandomQuestion(const std::string& difficulty) { + auto it = questionCache.find(difficulty); + if (it == questionCache.end() || it->second.empty()) { + return "No questions available for " + difficulty + " difficulty."; + } + + static std::map indices; + int& index = indices[difficulty]; + const std::vector& questions = it->second; + + std::string question = questions[index % questions.size()]; + index++; + + return question; + } + } + } void cmd::codingCommand(dpp::cluster& bot, const dpp::slashcommand_t& event) -{ - static int index; - const std::string question = cmd::utils::readFileLine("res/coding.txt", index); + { + coding::loadQuestions(); + std::string difficulty = "Beginner"; + try { + auto param = event.get_parameter("difficulty"); + if (!std::holds_alternative(param)) { + difficulty = std::get(param); + } + } + catch (...) {} - const dpp::embed embed = dpp::embed() + std::string question = coding::getRandomQuestion(difficulty); + dpp::embed embed = dpp::embed() .set_color(globals::color::defaultColor) - .add_field(question, ""); + .set_title("Coding Challenge - " + difficulty) + .set_description(question) + .add_field("Difficulty", difficulty, true) + .add_field("Need help?", "Ask in <#" + std::to_string(globals::channels::HELP_CHANNEL_ID) + ">", true) + .set_footer(dpp::embed_footer().set_text("Good luck! Share your solution in #code-review")) + .set_timestamp(time(0)); - const dpp::message message(event.command.channel_id, embed); - event.reply(message); -} + event.reply(embed); + } \ No newline at end of file diff --git a/src/commands/commands.h b/src/commands/commands.h index ed5bb73..e145bea 100644 --- a/src/commands/commands.h +++ b/src/commands/commands.h @@ -7,10 +7,10 @@ #include namespace cmd -{ + { /** - * @brief Replies with a question in the chat to change the topic - * @param bot cluster + * @brief Replies with a question in the chat to change the topic + * @param bot cluster * @param event slash command event */ void topicCommand(dpp::cluster& bot, const dpp::slashcommand_t& event); @@ -50,6 +50,13 @@ namespace cmd */ void projectCommand(dpp::cluster& bot, const dpp::slashcommand_t& event); + /** + * @brief Handles hint button clicks for project ideas + * @param bot cluster + * @param event button click event + */ + void handleProjectHintButton(dpp::cluster& bot, const dpp::button_click_t& event); + /** * @brief Replies with the rules * @param bot cluster @@ -57,8 +64,15 @@ namespace cmd */ void ruleCommand(dpp::cluster& bot, const dpp::slashcommand_t& event); + /** + * @brief Replies with a beginner's guide to C++ + * @param bot cluster + * @param event slash command event + */ + void beginnerCommand(dpp::cluster& bot, const dpp::slashcommand_t& event); + namespace utils - { + { /** * @brief Read next line of file, jump to beginning if no next line * @param path to the file @@ -66,19 +80,19 @@ namespace cmd * @return content of next line */ std::string readFileLine(const std::string& path, int& index); + } } -} struct cmdStruct -{ + { std::string name; std::string desc; typedef std::function cmdFunc; cmdFunc function; - std::list args; + std::vector args; dpp::permissions permissions; -}; + }; #endif // COMMANDS_H diff --git a/src/commands/project_cmd.cpp b/src/commands/project_cmd.cpp index a2214c4..e0019bf 100644 --- a/src/commands/project_cmd.cpp +++ b/src/commands/project_cmd.cpp @@ -3,6 +3,37 @@ using json = nlohmann::json; +void cmd::handleProjectHintButton(dpp::cluster& bot, const dpp::button_click_t& event) +{ + // Remove button + dpp::message updatedMsg = event.command.get_context_message(); + updatedMsg.components.clear(); + bot.message_edit(updatedMsg); + + json data; + try + { + std::ifstream projectFile("res/project.json"); + projectFile >> data; + } + catch (const json::parse_error& e) + { + event.reply("Failed to parse project file."); + return; + } + + const int hintButtonIndex = std::stoi(event.custom_id.substr(event.custom_id.rfind('_') + 1)); + const auto& project = data["projects"][hintButtonIndex]; + const std::string hint = project.contains("hint") ? project["hint"] : "No hint available."; + + dpp::embed hintEmbed = dpp::embed() + .set_color(globals::color::defaultColor) + .add_field("Hint", hint); + + dpp::message hintMessage(event.command.channel_id, hintEmbed); + event.reply(hintMessage); +} + void cmd::projectCommand(dpp::cluster& bot, const dpp::slashcommand_t& event) { static int index = 0; @@ -68,39 +99,5 @@ void cmd::projectCommand(dpp::cluster& bot, const dpp::slashcommand_t& event) event.reply(message); - bot.on_button_click([&bot](const dpp::button_click_t& event) { - // Ignore if button id does not start with hint_button_ - if (event.custom_id.rfind("hint_button_", 0) != 0) - return; - - // Remove button - dpp::message updatedMsg = event.command.get_context_message(); - updatedMsg.components.clear(); - bot.message_edit(updatedMsg); - - json data; - try - { - std::ifstream projectFile("res/project.json"); - projectFile >> data; - } - catch (const json::parse_error& e) - { - event.reply("Failed to parse project file."); - return; - } - - const int hintButtonIndex = std::stoi(event.custom_id.substr(event.custom_id.rfind('_') + 1)); - const auto& project = data["projects"][hintButtonIndex]; - const std::string hint = project.contains("hint") ? project["hint"] : "No hint available."; - - dpp::embed hintEmbed = dpp::embed() - .set_color(globals::color::defaultColor) - .add_field("Hint", hint); - - dpp::message hintMessage(event.command.channel_id, hintEmbed); - event.reply(hintMessage); - }); - index++; } diff --git a/src/config.json b/src/config.json deleted file mode 100644 index 917d0a1..0000000 --- a/src/config.json +++ /dev/null @@ -1 +0,0 @@ -{ "token": "bot token" } diff --git a/src/config.json.example b/src/config.json.example new file mode 100644 index 0000000..3a4955c --- /dev/null +++ b/src/config.json.example @@ -0,0 +1,10 @@ +{ + "token": "bot token", + "emoji_yes_id": "1226134958872199229", + "emoji_no_id": "1226134940006219817", + "channel_rules_id": "1130464978860785705", + "channel_jail_id": "1513269975844917409", + "category_ticket_id": "1234179713182732374", + "role_staff_id": "1130473404345110621", + "role_jail_id": "1506351798900887582" +} diff --git a/src/globals/globals.cpp b/src/globals/globals.cpp new file mode 100644 index 0000000..7c14267 --- /dev/null +++ b/src/globals/globals.cpp @@ -0,0 +1,102 @@ +#include "globals.h" + +#include +#include + +namespace +{ + bool parseSnowflake(const nlohmann::json& config, const char* key, dpp::snowflake& out) + { + if (!config.contains(key)) + return false; + + const auto& value = config.at(key); + + if (value.is_string()) + { + out = dpp::snowflake(value.get()); + return true; + } + + if (value.is_number_unsigned() || value.is_number_integer()) + { + out = dpp::snowflake(value.get()); + return true; + } + + return false; + } +} + +namespace globals +{ + namespace emoji + { + dpp::snowflake yes{}; + dpp::snowflake no{}; + } + + namespace channel + { + dpp::snowflake rulesId{}; + dpp::snowflake jailId{}; + } + + namespace category + { + dpp::snowflake ticketId{}; + } + + namespace role + { + dpp::snowflake staffId{}; + dpp::snowflake jailId{}; + } + + bool loadFromConfig(const nlohmann::json& config, std::string& error) + { + if (!parseSnowflake(config, "emoji_yes_id", emoji::yes)) + { + error = "Missing or invalid config key: emoji_yes_id"; + return false; + } + + if (!parseSnowflake(config, "emoji_no_id", emoji::no)) + { + error = "Missing or invalid config key: emoji_no_id"; + return false; + } + + if (!parseSnowflake(config, "channel_rules_id", channel::rulesId)) + { + error = "Missing or invalid config key: channel_rules_id"; + return false; + } + + if (!parseSnowflake(config, "channel_jail_id", channel::jailId)) + { + error = "Missing or invalid config key: channel_jail_id"; + return false; + } + + if (!parseSnowflake(config, "category_ticket_id", category::ticketId)) + { + error = "Missing or invalid config key: category_ticket_id"; + return false; + } + + if (!parseSnowflake(config, "role_staff_id", role::staffId)) + { + error = "Missing or invalid config key: role_staff_id"; + return false; + } + + if (!parseSnowflake(config, "role_jail_id", role::jailId)) + { + error = "Missing or invalid config key: role_jail_id"; + return false; + } + + return true; + } +} diff --git a/src/globals/globals.h b/src/globals/globals.h index c095d3b..8f753f3 100644 --- a/src/globals/globals.h +++ b/src/globals/globals.h @@ -2,6 +2,7 @@ #define GLOBALS_H #include +#include namespace globals { @@ -10,27 +11,40 @@ namespace globals static constexpr int defaultColor = 0x004482; } + namespace channels + { + constexpr dpp::snowflake HELP_CHANNEL_ID = 1130466207431135394ULL; + } + + /** + * @brief Load configured IDs used by the bot. + * @param config Parsed config JSON object. + * @param error Output error message when loading fails. + * @return true when all required IDs were loaded successfully. + */ + bool loadFromConfig(const nlohmann::json& config, std::string& error); + namespace emoji { - static constexpr dpp::snowflake yes = 1226134958872199229; - static constexpr dpp::snowflake no = 1226134940006219817; + extern dpp::snowflake yes; + extern dpp::snowflake no; } namespace channel { - static constexpr dpp::snowflake rulesId = 1130464978860785705; - static constexpr dpp::snowflake jailId = 1513269975844917409; + extern dpp::snowflake rulesId; + extern dpp::snowflake jailId; } namespace category { - static constexpr dpp::snowflake ticketId = 1234179713182732374; + extern dpp::snowflake ticketId; } namespace role { - static constexpr dpp::snowflake staffId = 1130473404345110621; - static constexpr dpp::snowflake jailId = 1506351798900887582; + extern dpp::snowflake staffId; + extern dpp::snowflake jailId; } } diff --git a/src/main.cpp b/src/main.cpp index 459c1b5..20172de 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include #include "commands/commands.h" +#include "globals/globals.h" #include "utils/suggestion/suggestion.h" #include "utils/moderation/moderation.h" @@ -11,19 +12,36 @@ using json = nlohmann::json; std::vector cmdList = { { "topic", "Get a topic question", cmd::topicCommand }, - { "coding", "Get a coding question", cmd::codingCommand }, + { "beginner", "Get a beginner's guide to C++", cmd::beginnerCommand }, + { "coding", "Get a coding question", cmd::codingCommand, + { + dpp::command_option(dpp::co_string, "difficulty", "Select difficulty", false) + .add_choice(dpp::command_option_choice("Beginner", "Beginner")) + .add_choice(dpp::command_option_choice("Intermediate", "Intermediate")) + .add_choice(dpp::command_option_choice("Advanced", "Advanced")) + .add_choice(dpp::command_option_choice("Expert", "Expert")) + .add_choice(dpp::command_option_choice("Master", "Master")) + } +}, { "close", "Close a ticket or forum post", cmd::closeCommand }, { "ticket", "Open a ticket", cmd::ticketCommand, { dpp::command_option(dpp::command_option_type::co_user, "participant", "Add participant", false) }}, { "code", "Formatting code on Discord", cmd::codeCommand }, { "project", "Get a project idea", cmd::projectCommand }, { "rule", "Get the server rules", cmd::ruleCommand, { dpp::command_option(dpp::command_option_type::co_integer, "number", "Rule to mention", false) }} -}; + }; int main() -{ + { std::ifstream configFile("config.json"); json config = json::parse(configFile); + std::string globalsConfigError; + if (!globals::loadFromConfig(config, globalsConfigError)) + { + std::cerr << "[!] Invalid configuration: " << globalsConfigError << std::endl; + return 1; + } + dpp::cluster bot(config["token"], dpp::i_default_intents | dpp::i_message_content); ModerationService moderationService(bot); @@ -32,10 +50,10 @@ int main() bot.set_presence(dpp::presence(dpp::presence_status::ps_online, dpp::activity_type::at_watching, "cppdiscord.com")); if (dpp::run_once()) - { + { std::vector slashcommands; for (const auto& item : cmdList) - { + { dpp::slashcommand slashCommand; slashCommand.set_name(item.name); slashCommand.set_description(item.desc); @@ -48,21 +66,21 @@ int main() slashCommand.set_default_permissions(dpp::permission(item.permissions)); slashcommands.push_back(slashCommand); - } + } bot.global_bulk_command_create(slashcommands); - } - }); + } + }); bot.on_slashcommand([&bot](const dpp::slashcommand_t& event) { for (const auto& item : cmdList) - { - if (item.name == event.command.get_command_name()) { + if (item.name == event.command.get_command_name()) + { item.function(bot, event); return; + } } - } - }); + }); bot.on_message_create([&bot, &moderationService](const dpp::message_create_t& event) { if (moderationService.handleMessage(event)) @@ -72,20 +90,22 @@ int main() if (channel && channel->name == "suggestions") utils::suggestion::createSuggestion(bot, event); - }); + }); bot.on_button_click([&bot](const dpp::button_click_t& event) { if (event.custom_id == "delSuggestion") utils::suggestion::deleteSuggestion(bot, event); else if (event.custom_id == "editSuggestion") utils::suggestion::editSuggestion(bot, event); - }); + else if (event.custom_id.starts_with("hint_button_")) + cmd::handleProjectHintButton(bot, event); + }); bot.on_form_submit([&bot](const dpp::form_submit_t& event) { if (event.custom_id == "editModal") utils::suggestion::showSuggestionEditModal(bot, event); - }); + }); bot.start(dpp::st_wait); return 0; -} + } diff --git a/src/res/coding/advanced.txt b/src/res/coding/advanced.txt new file mode 100644 index 0000000..56fd22d --- /dev/null +++ b/src/res/coding/advanced.txt @@ -0,0 +1,60 @@ +What is the difference between std::list and std::vector? +What is the difference between std::endl and '\n'? +How does the static keyword affect a class member? +What is the purpose of the decltype keyword? +What is move semantics in C++? +What is perfect forwarding? +What are variadic templates? +What is SFINAE? +What is the difference between lvalue and rvalue? +What are smart pointers and why use them? +What is the rule of three/five/zero? +What is CRTP (Curiously Recurring Template Pattern)? +What is type erasure in C++? +What is the difference between std::function and a function pointer? +What is the difference between std::shared_ptr and std::unique_ptr? +What is the difference between std::weak_ptr and std::shared_ptr? +What is the difference between std::move and std::forward? +What is the difference between std::vector and std::deque? +What is the difference between std::map and std::unordered_map? +What is the difference between std::set and std::unordered_set? +What is the difference between std::multiset and std::set? +What is the difference between std::multimap and std::map? +What is the difference between std::array and std::vector? +What is the difference between std::string and std::string_view? +What is the difference between std::tuple and std::pair? +What is the difference between std::variant and std::any? +What is the difference between std::optional and std::variant? +What is the difference between std::async and std::thread? +What is the difference between std::mutex and std::recursive_mutex? +What is the difference between std::lock_guard and std::unique_lock? +What is the difference between std::atomic and std::mutex? +What is the difference between std::condition_variable and std::atomic? +What is the difference between std::future and std::promise? +What is the difference between std::packaged_task and std::async? +What is the difference between std::chrono::system_clock and std::chrono::steady_clock? +What is the difference between std::istream and std::ostream? +What is the difference between std::ifstream and std::ofstream? +What is the difference between std::stringstream and std::fstream? +What is the difference between std::ios::in and std::ios::out? +What is the difference between std::ios::app and std::ios::ate? +What is the difference between std::ios::binary and std::ios::text? +What is the difference between std::exception and std::logic_error? +What is the difference between std::runtime_error and std::logic_error? +What is the difference between std::bad_alloc and std::bad_cast? +What is the difference between std::bad_typeid and std::bad_exception? +What is the difference between std::uncaught_exception and std::uncaught_exceptions? +What is the difference between std::terminate and std::abort? +What is the difference between std::set_terminate and std::set_unexpected? +What is the difference between std::nothrow and std::terminate? +What is the difference between std::make_shared and std::shared_ptr? +What is the difference between std::make_unique and std::unique_ptr? +What is the difference between std::allocator and std::pmr::polymorphic_allocator? +What is the difference between std::vector and std::vector? +What is the difference between std::initializer_list and std::array? +What is the difference between std::span and std::array_view? +What is the difference between std::byte and char? +What is the difference between std::error_code and std::error_condition? +What is the difference between std::system_error and std::logic_error? +What is the difference between std::filesystem::path and std::string? +What is the difference between std::filesystem::directory_iterator and std::filesystem::recursive_directory_iterator? \ No newline at end of file diff --git a/src/res/coding/beginner.txt b/src/res/coding/beginner.txt new file mode 100644 index 0000000..9060859 --- /dev/null +++ b/src/res/coding/beginner.txt @@ -0,0 +1,46 @@ +What is the difference between C and C++? +What is the difference between an integer and an unsigned integer? +How can you get the length of a std::string? +How can you add a new element to the end of a vector? +How can you get the size of a std::array? +What's the output of std::cout << 14 % 4;? Why? +What is a pointer? +What is OOP? +What is a reference? +Which came first, C or C++? +How many bytes does a char use? +What are the parameters of `int main(int argc, char* argv[])` for? +What is the difference between ++var and var++? +What is the "const" keyword? and when is it used? +How do you create a constructor? +How do you create a destructor? +What is the "protected" access modifier? +What is the "public" access modifier? +What is the "private" access modifier? +What does the sizeof operator do? +When is the delete keyword used? +When is the new keyword used? +How do you get the current time? +How do you get a random number? +How do you open a file? +What is the difference between a pointer and a reference? +How do you initialize a std::map? +What is the purpose of the namespace keyword? +What is the difference between struct and class in C++? +What does the override keyword do? +How can you handle exceptions in C++? +What is the role of the explicit keyword? +What does the keyword inline mean? +What is the difference between typedef and using? +How do you iterate over a std::vector? +How does a for-each loop work in C++? +What is the difference between malloc and new? +What is the difference between free and delete? +How do you declare a constant pointer? +How do you copy a std::std::string? +What is the difference between std::endl and '\n'? +How can you sort a std::vector? +How does the static keyword affect a class member? +How can you create a multi-dimensional array in C++? +How do you initialize a std::pair? +What is the purpose of the decltype keyword? \ No newline at end of file diff --git a/src/res/coding.txt b/src/res/coding/coding.txt similarity index 100% rename from src/res/coding.txt rename to src/res/coding/coding.txt diff --git a/src/res/coding/expert.txt b/src/res/coding/expert.txt new file mode 100644 index 0000000..0164277 --- /dev/null +++ b/src/res/coding/expert.txt @@ -0,0 +1,88 @@ +What is SFINAE and how is it used in template metaprogramming? +What is the difference between std::enable_if and concepts in C++20? +What is CRTP (Curiously Recurring Template Pattern) and when would you use it? +What is type erasure and how can you implement it in C++? +What is the difference between std::decay and std::remove_reference? +What are variadic templates and how do you use parameter packs? +What is perfect forwarding and how does std::forward work? +What is the difference between lvalue, rvalue, xvalue, glvalue, and prvalue? +What are move semantics and how do they improve performance? +What is the rule of three/five/zero and why is it important? +How does std::shared_ptr implement reference counting? +What is the difference between std::weak_ptr and std::shared_ptr? +What is the difference between std::unique_ptr and std::auto_ptr? +What is the difference between std::move and std::forward? +What is the difference between std::function and a function pointer? +What is the difference between std::bind and lambda expressions? +What is the difference between std::async and std::thread? +What is the difference between std::future and std::promise? +What is the difference between std::packaged_task and std::async? +What is the difference between std::condition_variable and std::atomic? +What is the difference between std::mutex and std::recursive_mutex? +What is the difference between std::lock_guard and std::unique_lock? +What is the difference between std::atomic and std::mutex? +What is the difference between std::chrono::system_clock and std::chrono::steady_clock? +What is the difference between std::chrono::high_resolution_clock and std::chrono::steady_clock? +What is the difference between std::filesystem::path and std::string? +What is the difference between std::filesystem::directory_iterator and std::recursive_directory_iterator? +What is the difference between std::pmr::polymorphic_allocator and std::allocator? +What is the difference between std::vector and std::vector? +What is the difference between std::span and std::string_view? +What is the difference between std::byte and char? +What is the difference between std::error_code and std::error_condition? +What is the difference between std::system_error and std::logic_error? +What is the difference between std::nested_exception and std::exception_ptr? +What is the difference between std::uncaught_exception and std::uncaught_exceptions? +What is the difference between std::terminate and std::abort? +What is the difference between std::set_terminate and std::set_unexpected? +What is the difference between std::nothrow and std::terminate? +What is the difference between std::make_shared and std::shared_ptr? +What is the difference between std::make_unique and std::unique_ptr? +What is the difference between std::initializer_list and std::array? +What is the difference between std::tuple and std::pair? +What is the difference between std::variant and std::any? +What is the difference between std::optional and std::variant? +What is the difference between std::nullopt and std::monostate? +What is the difference between std::in_place and std::in_place_type? +What is the difference between std::launch::async and std::launch::deferred? +What is the difference between std::memory_order_relaxed and std::memory_order_acquire? +What is the difference between std::memory_order_release and std::memory_order_acq_rel? +What is the difference between std::memory_order_seq_cst and std::memory_order_acquire? +What is the difference between std::memory_order_consume and std::memory_order_acquire? +What is the difference between std::memory_order_relaxed and std::memory_order_consume? +What is the difference between std::atomic_flag and std::atomic? +What is the difference between std::atomic_thread_fence and std::atomic_signal_fence? +What is the difference between std::call_once and std::mutex? +What is the difference between std::once_flag and std::call_once? +What is the difference between std::shared_future and std::future? +What is the difference between std::future_status and std::future_errc? +What is the difference between std::future_error and std::system_error? +What is the difference between std::bad_alloc and std::bad_array_new_length? +What is the difference between std::type_info and std::type_index? +What is the difference between std::bad_typeid and std::bad_exception? +What is the difference between std::exception_ptr and std::nested_exception? +What is the difference between std::rethrow_exception and std::rethrow_if_nested? +What is the difference between std::current_exception and std::get_current_exception? +What is the difference between std::make_exception_ptr and std::exception_ptr? +What is the difference between std::terminate_handler and std::unexpected_handler? +What is the difference between std::set_terminate and std::set_unexpected? +What is the difference between std::get_terminate and std::get_unexpected? +What is the difference between std::uncaught_exception and std::uncaught_exceptions? +What is the difference between std::nothrow_t and std::nothrow? +What is the difference between std::align_val_t and std::size_t? +What is the difference between std::new_handler and std::set_new_handler? +What is the difference between std::get_new_handler and std::set_new_handler? +What is the difference between std::bad_alloc and std::bad_array_new_length? +What is the difference between std::nothrow and std::new_handler? +What is the difference between std::launder and std::addressof? +What is the difference between std::assume_aligned and std::align? +What is the difference between std::align and std::aligned_alloc? +What is the difference between std::hardware_destructive_interference_size and std::hardware_constructive_interference_size? +What is the difference between std::has_single_bit and std::has_zero_bit? +What is the difference between std::bit_ceil and std::bit_floor? +What is the difference between std::bit_width and std::countr_zero? +What is the difference between std::countl_zero and std::countr_zero? +What is the difference between std::countl_one and std::countr_one? +What is the difference between std::rotl and std::rotr? +What is the difference between std::byteswap and std::swap? +What is the difference between std::endian and std::byte? \ No newline at end of file diff --git a/src/res/coding/intermediate.txt b/src/res/coding/intermediate.txt new file mode 100644 index 0000000..5d382d1 --- /dev/null +++ b/src/res/coding/intermediate.txt @@ -0,0 +1,64 @@ +What is the difference between int const * and int * const? +What is the "const" keyword and when is it used? +What is the virtual function specifier? +How do you create a constructor? +How do you create a destructor? +What is the "protected" access modifier? +What is the "public" access modifier? +What is the "private" access modifier? +What does the sizeof operator do? +When is the delete keyword used? +When is the new keyword used? +What are templates? +What is Generic programming? +How do you get the current time? +How do you get a random number? +How do you open a file? +What is the difference between a pointer and a reference? +How do you initialize a std::map? +What is the purpose of the namespace keyword? +What is a lambda function in C++? +How do you use a std::set? +What is the difference between struct and class in C++? +What does the override keyword do? +How can you handle exceptions in C++? +What is the role of the explicit keyword? +What does the keyword inline mean? +What is the difference between typedef and using? +How do you iterate over a std::vector? +How does a for-each loop work in C++? +What is the difference between malloc and new? +What is the difference between free and delete? +What is a virtual destructor, and why is it needed? +How does polymorphism work in C++? +How do you implement a pure virtual function? +What is an abstract class? +What is a friend function? +What is the difference between std::list and std::vector? +How do you declare a constant pointer? +How do you copy a std::string? +What is the difference between std::endl and '\n'? +How can you sort a std::vector? +How does the static keyword affect a class member? +How can you create a multi-dimensional array in C++? +How do you initialize a std::pair? +What is the purpose of the decltype keyword? +What is the difference between std::array and std::vector? +What is the difference between std::string and std::string_view? +What is the difference between std::tuple and std::pair? +What is the difference between std::optional and std::variant? +What is the difference between std::function and a function pointer? +What is the difference between std::shared_ptr and std::unique_ptr? +What is the difference between std::weak_ptr and std::shared_ptr? +What is the difference between std::move and std::forward? +What is the difference between std::vector and std::deque? +What is the difference between std::map and std::unordered_map? +What is the difference between std::set and std::unordered_set? +What is the difference between std::multiset and std::set? +What is the difference between std::multimap and std::map? +What is the difference between std::exception and std::logic_error? +What is the difference between std::runtime_error and std::logic_error? +What is the difference between std::bad_alloc and std::bad_cast? +What is the difference between std::ios::in and std::ios::out? +What is the difference between std::ifstream and std::ofstream? +What is the difference between std::stringstream and std::fstream? \ No newline at end of file diff --git a/src/res/coding/master.txt b/src/res/coding/master.txt new file mode 100644 index 0000000..0f54e7d --- /dev/null +++ b/src/res/coding/master.txt @@ -0,0 +1,227 @@ +What is undefined behavior and how can you avoid it? +What is the One Definition Rule (ODR) and why is it important? +What is the difference between static and dynamic linking? +How does the C++ compilation process work from source to executable? +What is the difference between a translation unit and a module? +What is the as-if rule in C++? +What is the difference between stack and heap memory allocation? +What is memory alignment and why is it important? +How does cache memory affect C++ performance? +What is false sharing in multithreaded C++ programs? +What is the difference between copy elision and RVO (Return Value Optimization)? +What is the difference between NRVO and RVO? +What is the difference between constexpr and consteval? +What is the difference between constinit and constexpr? +What is the difference between std::is_constant_evaluated and constexpr? +What is the difference between if constexpr and if statement? +What is the difference between fold expressions and recursive templates? +What is the difference between structured bindings and std::tie? +What is the difference between designated initializers and aggregate initialization? +What is the difference between modules and header files? +What is the difference between import and include in C++20? +What is the difference between contracts and assertions? +What is the difference between std::expect and std::assume? +What is the difference between [[likely]] and [[unlikely]] attributes? +What is the difference between [[nodiscard]] and [[maybe_unused]]? +What is the difference between [[deprecated]] and [[noreturn]]? +What is the difference between [[carries_dependency]] and [[noreturn]]? +What is the difference between [[fallthrough]] and [[nodiscard]]? +What is the difference between [[gnu::unused]] and [[maybe_unused]]? +What is the difference between std::source_location and __LINE__? +What is the difference between std::stacktrace and std::exception? +What is the difference between std::identity and std::forward? +What is the difference between std::invoke and std::apply? +What is the difference between std::bind_front and std::bind? +What is the difference between std::to_address and std::addressof? +What is the difference between std::assume_aligned and std::align? +What is the difference between std::launder and std::addressof? +What is the difference between std::bit_cast and reinterpret_cast? +What is the difference between std::start_lifetime_as and std::launder? +What is the difference between std::to_chars and std::from_chars? +What is the difference between std::format and std::stringstream? +What is the difference between std::print and std::cout? +What is the difference between std::to_string and std::format? +What is the difference between std::chrono::zoned_time and std::chrono::time_zone? +What is the difference between std::chrono::utc_clock and std::chrono::system_clock? +What is the difference between std::chrono::tai_clock and std::chrono::utc_clock? +What is the difference between std::chrono::gps_clock and std::chrono::utc_clock? +What is the difference between std::chrono::file_clock and std::chrono::system_clock? +What is the difference between std::chrono::hh_mm_ss and std::chrono::duration? +What is the difference between std::chrono::day and std::chrono::month? +What is the difference between std::chrono::year and std::chrono::year_month_day? +What is the difference between std::chrono::weekday and std::chrono::weekday_indexed? +What is the difference between std::chrono::leap_second and std::chrono::time_zone? +What is the difference between std::chrono::tzdb and std::chrono::time_zone? +What is the difference between std::chrono::get_tzdb and std::chrono::get_tzdb_list? +What is the difference between std::chrono::current_zone and std::chrono::locate_zone? +What is the difference between std::chrono::zoned_time and std::chrono::local_time? +What is the difference between std::chrono::zoned_traits and std::chrono::time_zone? +What is the difference between std::chrono::nozone and std::chrono::time_zone? +What is the difference between std::chrono::sys_info and std::chrono::local_info? +What is the difference between std::chrono::choose and std::chrono::time_zone? +What is the difference between std::chrono::ambiguous_local_time and std::chrono::nonexistent_local_time? +What is the difference between std::chrono::tzdb_list and std::chrono::time_zone? +What is the difference between std::chrono::reload_tzdb and std::chrono::remote_version? +What is the difference between std::chrono::weekday and std::chrono::weekday_iso? +What is the difference between std::chrono::month_weekday and std::chrono::month_day? +What is the difference between std::chrono::month_day_last and std::chrono::month_weekday_last? +What is the difference between std::chrono::year_month and std::chrono::year_month_day? +What is the difference between std::chrono::year_month_weekday and std::chrono::year_month_day? +What is the difference between std::chrono::leap_second and std::chrono::time_zone? +What is the difference between std::chrono::sys_days and std::chrono::local_days? +What is the difference between std::chrono::days and std::chrono::weeks? +What is the difference between std::chrono::years and std::chrono::months? +What is the difference between std::chrono::duration_cast and std::chrono::floor? +What is the difference between std::chrono::ceil and std::chrono::round? +What is the difference between std::chrono::abs and std::chrono::duration_cast? +What is the difference between std::chrono::time_point_cast and std::chrono::ceil? +What is the difference between std::chrono::floor and std::chrono::ceil? +What is the difference between std::chrono::duration_values and std::chrono::duration? +What is the difference between std::chrono::treat_as_floating_point and std::chrono::duration? +What is the difference between std::chrono::duration and std::chrono::time_point? +What is the difference between std::chrono::clock and std::chrono::system_clock? +What is the difference between std::chrono::steady_clock and std::chrono::high_resolution_clock? +What is the difference between std::chrono::is_clock and std::chrono::clock? +What is the difference between std::chrono::clock_time_conversion and std::chrono::time_point? +What is the difference between std::chrono::clock_cast and std::chrono::time_point_cast? +What is the difference between std::chrono::clock_time_conversion and std::chrono::clock_cast? +What is the difference between std::chrono::utc_clock and std::chrono::tai_clock? +What is the difference between std::chrono::tai_clock and std::chrono::gps_clock? +What is the difference between std::chrono::gps_clock and std::chrono::utc_clock? +What is the difference between std::chrono::file_clock and std::chrono::utc_clock? +What is the difference between std::chrono::clock and std::chrono::time_zone? +What is the difference between std::chrono::time_zone and std::chrono::zoned_time? +What is the difference between std::chrono::zoned_time and std::chrono::local_time? +What is the difference between std::chrono::local_time and std::chrono::sys_time? +What is the difference between std::chrono::sys_seconds and std::chrono::local_seconds? +What is the difference between std::chrono::sys_days and std::chrono::local_days? +What is the difference between std::chrono::sys_time and std::chrono::local_time? +What is the difference between std::chrono::sys_info and std::chrono::local_info? +What is the difference between std::chrono::choose and std::chrono::time_zone? +What is the difference between std::chrono::ambiguous_local_time and std::chrono::nonexistent_local_time? +What is the difference between std::chrono::tzdb and std::chrono::time_zone? +What is the difference between std::chrono::tzdb_list and std::chrono::time_zone? +What is the difference between std::chrono::get_tzdb and std::chrono::get_tzdb_list? +What is the difference between std::chrono::current_zone and std::chrono::locate_zone? +What is the difference between std::chrono::reload_tzdb and std::chrono::remote_version? +What is the difference between std::chrono::zoned_traits and std::chrono::time_zone? +What is the difference between std::chrono::nozone and std::chrono::time_zone? +What is the difference between std::chrono::leap_second_info and std::chrono::time_zone? +What is the difference between std::chrono::time_zone_link and std::chrono::time_zone? +What is the difference between std::chrono::time_zone and std::chrono::zoned_time? +What is the difference between std::chrono::zoned_time and std::chrono::local_time? +What is the difference between std::chrono::local_time and std::chrono::sys_time? +What is the difference between std::chrono::sys_seconds and std::chrono::local_seconds? +What is the difference between std::chrono::sys_days and std::chrono::local_days? +What is the difference between std::chrono::sys_time and std::chrono::local_time? +What is the difference between std::chrono::sys_info and std::chrono::local_info? +What is the difference between std::chrono::choose and std::chrono::time_zone? +What is the difference between std::chrono::ambiguous_local_time and std::chrono::nonexistent_local_time? +What is the difference between std::chrono::tzdb and std::chrono::time_zone? +What is the difference between std::chrono::tzdb_list and std::chrono::time_zone? +What is the difference between std::chrono::get_tzdb and std::chrono::get_tzdb_list? +What is the difference between std::chrono::current_zone and std::chrono::locate_zone? +What is the difference between std::chrono::reload_tzdb and std::chrono::remote_version? +What is the difference between std::chrono::zoned_traits and std::chrono::time_zone? +What is the difference between std::chrono::nozone and std::chrono::time_zone? +What is the difference between std::chrono::leap_second_info and std::chrono::time_zone? +What is the difference between std::chrono::time_zone_link and std::chrono::time_zone? +What is the difference between std::memory_order and std::memory_order_*? +What is the difference between std::atomic and std::atomic_flag? +What is the difference between std::atomic_ref and std::atomic? +What is the difference between std::shared_mutex and std::shared_timed_mutex? +What is the difference between std::scoped_lock and std::lock_guard? +What is the difference between std::unique_lock and std::scoped_lock? +What is the difference between std::latch and std::barrier? +What is the difference between std::barrier and std::flex_barrier? +What is the difference between std::counting_semaphore and std::binary_semaphore? +What is the difference between std::semaphore and std::mutex? +What is the difference between std::notify_all_at_thread_exit and std::condition_variable? +What is the difference between std::notify_all and std::notify_one? +What is the difference between std::wait and std::wait_for? +What is the difference between std::wait_until and std::wait_for? +What is the difference between std::stop_source and std::stop_token? +What is the difference between std::stop_callback and std::stop_token? +What is the difference between std::jthread and std::thread? +What is the difference between std::thread and std::jthread? +What is the difference between std::this_thread::sleep_for and std::this_thread::sleep_until? +What is the difference between std::this_thread::yield and std::this_thread::sleep_for? +What is the difference between std::this_thread::get_id and std::thread::id? +What is the difference between std::thread::hardware_concurrency and std::thread::native_handle? +What is the difference between std::thread::detach and std::thread::join? +What is the difference between std::thread::join and std::thread::detach? +What is the difference between std::thread::swap and std::thread::operator=? +What is the difference between std::jthread::request_stop and std::jthread::stop_source? +What is the difference between std::jthread::get_stop_token and std::jthread::stop_token? +What is the difference between std::jthread::get_stop_source and std::jthread::stop_source? +What is the difference between std::jthread::request_stop and std::jthread::stop_source? +What is the difference between std::stop_token and std::stop_source? +What is the difference between std::stop_callback and std::stop_token? +What is the difference between std::stop_callback and std::function? +What is the difference between std::stop_callback and std::move_only_function? +What is the difference between std::move_only_function and std::function? +What is the difference between std::function and std::move_only_function? +What is the difference between std::function and std::copyable_function? +What is the difference between std::copyable_function and std::function? +What is the difference between std::function and std::any_invocable? +What is the difference between std::any_invocable and std::function? +What is the difference between std::function and std::reference_wrapper? +What is the difference between std::reference_wrapper and std::function? +What is the difference between std::reference_wrapper and std::weak_ptr? +What is the difference between std::weak_ptr and std::reference_wrapper? +What is the difference between std::weak_ptr and std::shared_ptr? +What is the difference between std::shared_ptr and std::intrusive_ptr? +What is the difference between std::intrusive_ptr and std::shared_ptr? +What is the difference between std::intrusive_ptr and std::unique_ptr? +What is the difference between std::unique_ptr and std::intrusive_ptr? +What is the difference between std::unique_ptr and std::shared_ptr? +What is the difference between std::shared_ptr and std::weak_ptr? +What is the difference between std::weak_ptr and std::shared_ptr? +What is the difference between std::weak_ptr and std::intrusive_ptr? +What is the difference between std::observer_ptr and std::weak_ptr? +What is the difference between std::observer_ptr and std::reference_wrapper? +What is the difference between std::observer_ptr and std::unique_ptr? +What is the difference between std::out_ptr and std::inout_ptr? +What is the difference between std::out_ptr_t and std::inout_ptr_t? +What is the difference between std::out_ptr and std::inout_ptr? +What is the difference between std::to_address and std::addressof? +What is the difference between std::launder and std::assume_aligned? +What is the difference between std::bit_cast and std::start_lifetime_as? +What is the difference between std::start_lifetime_as and std::launder? +What is the difference between std::assume_aligned and std::align? +What is the difference between std::align and std::aligned_alloc? +What is the difference between std::aligned_alloc and std::aligned_alloc? +What is the difference between std::aligned_alloc and std::malloc? +What is the difference between std::malloc and std::calloc? +What is the difference between std::calloc and std::realloc? +What is the difference between std::realloc and std::free? +What is the difference between std::free and std::operator delete? +What is the difference between std::operator new and std::operator delete? +What is the difference between std::operator new and std::malloc? +What is the difference between std::operator delete and std::free? +What is the difference between std::nothrow and std::new_handler? +What is the difference between std::new_handler and std::set_new_handler? +What is the difference between std::set_new_handler and std::get_new_handler? +What is the difference between std::get_new_handler and std::new_handler? +What is the difference between std::bad_alloc and std::bad_array_new_length? +What is the difference between std::bad_array_new_length and std::bad_alloc? +What is the difference between std::bad_alloc and std::bad_exception? +What is the difference between std::bad_exception and std::bad_alloc? +What is the difference between std::bad_exception and std::exception? +What is the difference between std::exception and std::logic_error? +What is the difference between std::logic_error and std::runtime_error? +What is the difference between std::runtime_error and std::system_error? +What is the difference between std::system_error and std::ios_base::failure? +What is the difference between std::ios_base::failure and std::system_error? +What is the difference between std::system_error and std::future_error? +What is the difference between std::future_error and std::system_error? +What is the difference between std::future_error and std::logic_error? +What is the difference between std::future_error and std::runtime_error? +What is the difference between std::future_status and std::future_errc? +What is the difference between std::future_errc and std::future_status? +What is the difference between std::future_status and std::future_errc? +What is the difference between std::future_status and std::future_status? +What is the difference between std::future_status and std::launch? +What is the difference between std::launch and std::future_status? +What is the difference between std::launch and std::future_status? +What is the difference between std::launch and std::future_status? \ No newline at end of file diff --git a/src/utils/suggestion/suggestion.cpp b/src/utils/suggestion/suggestion.cpp index 65ed685..fc32df0 100644 --- a/src/utils/suggestion/suggestion.cpp +++ b/src/utils/suggestion/suggestion.cpp @@ -2,10 +2,16 @@ #include "../../globals/globals.h" void utils::suggestion::createSuggestion(dpp::cluster& bot, const dpp::message_create_t& event) -{ + { dpp::user user = event.msg.author; if (!user.is_bot()) - { + { + bot.message_delete(event.msg.id, event.msg.channel_id); + if (event.msg.content.empty()) + { + event.reply(dpp::message("You cannot send an empty suggestion. Please add text to your message.").set_flags(dpp::m_ephemeral)); + return; + } dpp::embed result = dpp::embed() .set_color(globals::color::defaultColor) .set_title("Suggestion") @@ -36,51 +42,83 @@ void utils::suggestion::createSuggestion(dpp::cluster& bot, const dpp::message_c bot.message_create(msg, [&bot](const dpp::confirmation_callback_t& callback) { if (!callback.is_error()) - { + { const dpp::message msg = std::get(callback.value); + const dpp::snowflake messageId = msg.id; + const dpp::snowflake channelId = msg.channel_id; const auto yesEmoji = dpp::find_emoji(globals::emoji::yes); const auto noEmoji = dpp::find_emoji(globals::emoji::no); if (yesEmoji && noEmoji) - { - bot.message_add_reaction(msg.id, msg.channel_id, yesEmoji->format(), [&bot, &msg, &noEmoji](const dpp::confirmation_callback_t& reactionCallback) { + { + const std::string yesEmojiText = yesEmoji->format(); + const std::string noEmojiText = noEmoji->format(); + + bot.message_add_reaction(messageId, channelId, yesEmojiText, [&bot, messageId, channelId, noEmojiText](const dpp::confirmation_callback_t& reactionCallback) { if (!reactionCallback.is_error()) - bot.message_add_reaction(msg.id, msg.channel_id, noEmoji->format()); - }); - } + bot.message_add_reaction(messageId, channelId, noEmojiText); + }); + } else - { + { // fallback - bot.message_add_reaction(msg.id, msg.channel_id, "👍", [&bot, &msg](const dpp::confirmation_callback_t& reactionCallback) { + bot.message_add_reaction(messageId, channelId, "👍", [&bot, messageId, channelId](const dpp::confirmation_callback_t& reactionCallback) { if (!reactionCallback.is_error()) - bot.message_add_reaction(msg.id, msg.channel_id, "👎"); - }); + bot.message_add_reaction(messageId, channelId, "👎"); + }); + } } - } - }); - bot.message_delete(event.msg.id, event.msg.channel_id); + }); + } } -} void utils::suggestion::deleteSuggestion(dpp::cluster& bot, const dpp::button_click_t& event) -{ + { + if (event.command.msg.embeds.empty()) + { + event.reply(dpp::message("Error: This message is not a valid suggestion.").set_flags(dpp::m_ephemeral)); + return; + } + + if (!event.command.msg.embeds[0].author) + { + event.reply(dpp::message("Error: Could not determine the author of this suggestion.").set_flags(dpp::m_ephemeral)); + return; + } + std::string clicker = event.command.get_issuing_user().format_username(); std::string originalAuthor = event.command.msg.embeds[0].author->name; if (clicker == originalAuthor) + { bot.message_delete(event.command.msg.id, event.command.msg.channel_id); + } else + { event.reply(dpp::message("You can only delete your own suggestions.").set_flags(dpp::m_ephemeral)); -} + } + } void utils::suggestion::editSuggestion(dpp::cluster& bot, const dpp::button_click_t& event) -{ + { + if (event.command.msg.embeds.empty()) + { + event.reply(dpp::message("Error: This message is not a valid suggestion.").set_flags(dpp::m_ephemeral)); + return; + } + + if (!event.command.msg.embeds[0].author) + { + event.reply(dpp::message("Error: Could not determine the author of this suggestion.").set_flags(dpp::m_ephemeral)); + return; + } + std::string clicker = event.command.get_issuing_user().format_username(); std::string originalAuthor = event.command.msg.embeds[0].author->name; if (clicker == originalAuthor) - { + { dpp::interaction_modal_response modal("editModal", "Edit suggestion"); modal.add_component( @@ -95,28 +133,78 @@ void utils::suggestion::editSuggestion(dpp::cluster& bot, const dpp::button_clic ); event.dialog(modal); - } + } else + { event.reply(dpp::message("You can only edit your own suggestions.").set_flags(dpp::m_ephemeral)); -} + } + } void utils::suggestion::showSuggestionEditModal(dpp::cluster& bot, const dpp::form_submit_t& event) -{ - std::string v = std::get(event.components[0].components[0].value); + { + if (event.components.empty()) + { + event.reply(dpp::message("Error: No data received from the modal.").set_flags(dpp::m_ephemeral)); + return; + } + + if (event.components[0].components.empty()) + { + event.reply(dpp::message("Error: No input data received from the modal.").set_flags(dpp::m_ephemeral)); + return; + } - bot.message_get(event.command.msg.id, event.command.msg.channel_id, [&bot, event, v](const dpp::confirmation_callback_t& callback) { - if (!callback.is_error()) + std::string v; + try { + v = std::get(event.components[0].components[0].value); + } + catch (const std::exception& e) + { + event.reply(dpp::message("Error: Could not read the edited text.").set_flags(dpp::m_ephemeral)); + return; + } + + if (v.empty()) + { + event.reply(dpp::message("Error: You cannot submit an empty suggestion.").set_flags(dpp::m_ephemeral)); + return; + } + + if (event.command.msg.embeds.empty()) + { + event.reply(dpp::message("Error: This suggestion has no embed to edit.").set_flags(dpp::m_ephemeral)); + return; + } + + bot.message_get(event.command.msg.id, event.command.msg.channel_id, [&bot, event, v](const dpp::confirmation_callback_t& callback) { + if (callback.is_error()) + { + event.reply(dpp::message("Error: Could not find the original message.").set_flags(dpp::m_ephemeral)); + return; + } + dpp::message msg = std::get(callback.value); - dpp::embed embed = event.command.msg.embeds[0]; + if (msg.embeds.empty()) + { + event.reply(dpp::message("Error: The original message has no embed.").set_flags(dpp::m_ephemeral)); + return; + } + + dpp::embed embed = msg.embeds[0]; embed.set_description(v); msg.embeds[0] = embed; - bot.message_edit(msg, [&bot, event, embed](const dpp::confirmation_callback_t& callback) { + bot.message_edit(msg, [&bot, event](const dpp::confirmation_callback_t& callback) { if (!callback.is_error()) - event.reply(dpp::message("Edited!").set_flags(dpp::m_ephemeral)); + { + event.reply(dpp::message("Suggestion edited successfully.").set_flags(dpp::m_ephemeral)); + } + else + { + event.reply(dpp::message(" Failed to edit the suggestion. Please try again.").set_flags(dpp::m_ephemeral)); + } + }); }); - } - }); -} + } \ No newline at end of file