2025-08-13 10:10:22 -06:00

200 lines
7.7 KiB
C++

#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <iostream>
#include <dpp/dpp.h>
#include <cstdio>
#include <algorithm> // for std::swap
#include <cstring> // 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 = "MTM5ODc5MjQ0Mzg2Mzc2MDk4Nw.Gtg_Hf.L_Na19lEgth4P4VR-jx6QMiVXoyVPjv6F1hQ2E";
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<void> {
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<struct register_bot_commands>()) {
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<const stbi_uc*>(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;
}