#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION #include #include #include #include // for std::swap #include // for std::memcpy #include "stb_image.h" #include "stb_image_write.h" using namespace std; /* Be sure to place your token in the line below. * Follow steps here to get a token: * https://dpp.dev/creating-a-bot-application.html * When you invite the bot, be sure to invite it with the * scopes 'bot' and 'applications.commands', e.g. * https://discord.com/oauth2/authorize?client_id=940762342495518720&scope=bot+applications.commands&permissions=139586816064 */ const std::string BOT_TOKEN = "???"; void flip_image_horizontally(unsigned char* data, int width, int height, int channels); void flip_image_vertically(unsigned char* data, int width, int height, int channels); void process_attachment(dpp::cluster& bot, const dpp::message_create_t& event, const dpp::attachment& attachment); int main() { /* Create bot cluster */ dpp::cluster bot(BOT_TOKEN, dpp::i_default_intents | dpp::i_message_content); /* Output simple log messages to stdout */ bot.on_log(dpp::utility::cout_logger()); /* Handle slash command with the most recent addition to D++ features, coroutines! */ bot.on_slashcommand([](const dpp::slashcommand_t& event) -> dpp::task { if (event.command.get_command_name() == "ping") { co_await event.co_reply("Pong!"); } co_return; }); /* Register slash command here in on_ready */ bot.on_ready([&bot](const dpp::ready_t& event) { /* Wrap command registration in run_once to make sure it doesnt run on every full reconnection */ if (dpp::run_once()) { bot.global_command_create(dpp::slashcommand("ping", "Ping pong!", bot.me.id)); } }); bot.on_message_create([&bot](const dpp::message_create_t& event) { bot.log(dpp::ll_info, "Message create event"); // Check if the message has any attachments if (!event.msg.attachments.empty()) { // // Log that an attachment was found bot.log(dpp::ll_info, "Message from " + event.msg.author.username + " contains attachments!"); // You can iterate through the attachments if you need details about each one for (const auto& attachment : event.msg.attachments) { // bot.log(dpp::ll_info, " Attachment ID: " + std::to_string(attachment.id) + ", Filename: " + attachment.filename + ", Size: " + std::to_string(attachment.size) + " bytes"); // You can also get the URL of the attachment: attachment.url // And a proxied URL: attachment.proxy_url std::string filename = attachment.filename; if (filename.substr(strlen(filename.c_str())-3,3) == "jpg") { bot.log(dpp::ll_info, "jpg detected"); std::string local_filename = "temp_" + attachment.filename; process_attachment(bot,event,attachment); bot.log(dpp::ll_info, "image flipped horizontally"); // Download the attachment first //download_file(bot, event, attachment.url, local_filename); // // Note: The download is asynchronous. You would typically do // further processing in the http_request_completion_t handler. // For a simple example, you might call load_image from there. } } // Example: Reply to the user saying you detected an attachment // event.reply("Thanks for the attachment!"); } else { // Log if no attachments were found bot.log(dpp::ll_info, "Message from " + event.msg.author.username + " has no attachments."); } // You can also add logic for processing other types of messages or commands here }); std::cerr << "--- Direct stderr test: Bot is about to start listening ---" << std::endl; /* Start the bot */ bot.start(dpp::st_wait); return 0; } void process_attachment(dpp::cluster& bot, const dpp::message_create_t& event, const dpp::attachment& attachment) { std::string local_filename = "temp_" + std::to_string(attachment.id) + "_" + attachment.filename; bot.request(attachment.url, dpp::http_method::m_get, [ &bot, event, local_filename, attachment](const dpp::http_request_completion_t& completion) { if (completion.status < 400) { std::ofstream file(local_filename, std::ios::binary); if (file.is_open()) { file.write(completion.body.c_str(), completion.body.length()); file.close(); int width, height, channels; //unsigned char* image_data = stbi_load_from_memory(local_filename.c_str(), &width, &height, &channels, 0); unsigned char* image_data = stbi_load_from_memory( reinterpret_cast(completion.body.data()), completion.body.length(), &width, &height, &channels, 0 ); if (image_data) { // Flip the image horizontally (you can choose which flip to apply) bot.log(dpp::ll_info,"channels: " + std::to_string(channels)); flip_image_horizontally(image_data, width, height, channels); // --- Save the flipped image to a new temporary file --- std::string flipped_filename = "flipped_" + local_filename; stbi_write_jpg(flipped_filename.c_str(), width, height, channels, image_data, 100); // Quality 100 // --- NEW CODE STARTS HERE --- dpp::message msg; // Add the file to the message msg.add_file(flipped_filename, dpp::utility::read_file(flipped_filename)); // Create an embed and reference the attached file dpp::embed embed; embed.set_title("Image Info"); embed.set_description("Dimensions: " + std::to_string(width) + "x" + std::to_string(height)); embed.set_image("attachment://" + flipped_filename); // Reference the file here // Add the embed to the message msg.add_embed(embed); msg.set_channel_id(1398043078559797310); bot.message_create(msg); msg.set_content("Here's your horizontally flipped image"); event.reply(msg); // --- NEW CODE ENDS HERE --- stbi_image_free(image_data); std::remove(local_filename.c_str()); std::remove(flipped_filename.c_str()); // Clean up the flipped file } else { std::cerr << "Error: Failed to load image with stb from " << local_filename << std::endl; } std::remove(local_filename.c_str()); } else { std::cerr << "Failed to open local file for writing: " << local_filename << std::endl; } } else { std::cerr << "Failed to download image from " << attachment.url << ". HTTP status code: " << completion.status << std::endl; } }); } void flip_image_horizontally(unsigned char* data, int width, int height, int channels) { for (int y = 0; y < height; ++y) { // Get pointers to the start of the current row unsigned char* row_start = data + y * width * channels; // Loop through half the row, swapping pixels from left and right for (int x = 0; x < width / 2; ++x) { // Calculate the pointers to the left and right pixels unsigned char* left_pixel = row_start + x * channels; unsigned char* right_pixel = row_start + (width - 1 - x) * channels; // Swap each channel of the pixels for (int c = 0; c < channels; ++c) { std::swap(left_pixel[c], right_pixel[c]); } } } } void flip_image_vertically(unsigned char* data, int width, int height, int channels) { // ... (your vertical flip implementation from before) int row_stride = width * channels; unsigned char* temp_row = new unsigned char [row_stride]; for (int y = 0; y < height / 2; ++y) { unsigned char* top_row = data + y * row_stride; unsigned char* bottom_row = data + (height - 1 - y) * row_stride; std::memcpy(temp_row, top_row, row_stride); std::memcpy(top_row, bottom_row, row_stride); std::memcpy(bottom_row, temp_row, row_stride); } delete[] temp_row; }