Initial commit of poomer-discord-hellowrold with STB headers
This commit is contained in:
commit
78716fe006
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Ignore the bot token file
|
||||||
|
token.txt
|
||||||
|
|
||||||
|
# Ignore the build directory
|
||||||
|
# This directory contains temporary files, object files, and the executable.
|
||||||
|
# It should be regenerated with `cmake` and `make`.
|
||||||
|
/build/
|
||||||
|
|
||||||
|
# Ignore C++ build artifacts
|
||||||
|
*.o
|
||||||
|
*.out
|
||||||
|
*.exe
|
||||||
|
*.obj
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Ignore temporary files created by the bot
|
||||||
|
temp_*
|
||||||
|
flipped_*
|
||||||
34
CMakeLists.txt
Normal file
34
CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Minimum CMake version required, we'll just use the latest version.
|
||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
# Project name, version and description
|
||||||
|
project(discord-bot VERSION 1.0 DESCRIPTION "A discord bot")
|
||||||
|
|
||||||
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
|
# Create an executable
|
||||||
|
add_executable(${PROJECT_NAME}
|
||||||
|
src/main.cpp
|
||||||
|
src/ImageProcessor.cpp # Add your new source file here
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find our pre-installed DPP package (using FindDPP.cmake).
|
||||||
|
find_package(DPP REQUIRED)
|
||||||
|
|
||||||
|
# Link the pre-installed DPP package.
|
||||||
|
target_link_libraries(${PROJECT_NAME}
|
||||||
|
${DPP_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Include the DPP directories.
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||||
|
${DPP_INCLUDE_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/stb
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set C++ version
|
||||||
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
|
CXX_STANDARD 20
|
||||||
|
CXX_STANDARD_REQUIRED ON
|
||||||
|
)
|
||||||
7
cmake/FindDPP.cmake
Normal file
7
cmake/FindDPP.cmake
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
find_path(DPP_INCLUDE_DIR NAMES dpp/dpp.h HINTS ${DPP_ROOT_DIR})
|
||||||
|
|
||||||
|
find_library(DPP_LIBRARIES NAMES dpp "libdpp.a" HINTS ${DPP_ROOT_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(DPP DEFAULT_MSG DPP_LIBRARIES DPP_INCLUDE_DIR)
|
||||||
0
cmake/main.cpp
Normal file
0
cmake/main.cpp
Normal file
0
cmake/main.h
Normal file
0
cmake/main.h
Normal file
22
include/ImageProcessor.h
Normal file
22
include/ImageProcessor.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// ~/workdir/poomer-discord-helloworld/include/ImageProcessor.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <dpp/dpp.h>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class ImageProcessor {
|
||||||
|
public:
|
||||||
|
// The constructor will likely need a reference to the dpp::cluster
|
||||||
|
ImageProcessor(dpp::cluster& bot);
|
||||||
|
|
||||||
|
// This is the public method that will be called from the main event handler
|
||||||
|
void process_attachment(const dpp::message_create_t& event, const dpp::attachment& attachment);
|
||||||
|
|
||||||
|
private:
|
||||||
|
dpp::cluster& m_bot; // A reference to the bot cluster
|
||||||
|
|
||||||
|
// Helper methods for image manipulation can be private
|
||||||
|
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);
|
||||||
|
};
|
||||||
1
include/stb
Submodule
1
include/stb
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit f58f558c120e9b32c217290b80bad1a0729fbb2c
|
||||||
126
src/ImageProcessor.cpp
Normal file
126
src/ImageProcessor.cpp
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// ~/workdir/poomer-discord-helloworld/src/ImageProcessor.cpp
|
||||||
|
#include "../include/ImageProcessor.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <algorithm> // For std::swap
|
||||||
|
#include <cstring> // For std::memcpy
|
||||||
|
|
||||||
|
// You MUST define the implementation macros here, in the .cpp file,
|
||||||
|
// and include the stb headers. This is a crucial step for single-header libraries.
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
#include "stb_image_write.h"
|
||||||
|
|
||||||
|
ImageProcessor::ImageProcessor(dpp::cluster& bot) : m_bot(bot) {
|
||||||
|
// Constructor initializes the member variable
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageProcessor::flip_image_horizontally(unsigned char* data, int width, int height, int channels) {
|
||||||
|
// ... (your horizontal flip implementation from before)
|
||||||
|
/*for (int y = 0; y < height; ++y) {
|
||||||
|
unsigned char *left = data + y * width * channels;
|
||||||
|
unsigned char *right = left + (width - 1) * channels;
|
||||||
|
for (int x = 0; x < width / 2; ++x) {
|
||||||
|
for (int c = 0; c < channels; ++c) {
|
||||||
|
std::swap(left[(x * channels) + c], right[(0 * channels) + c]);
|
||||||
|
}
|
||||||
|
left += channels;
|
||||||
|
right -= 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 ImageProcessor::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageProcessor::process_attachment(const dpp::message_create_t& event, const dpp::attachment& attachment) {
|
||||||
|
std::string local_filename = "temp_" + std::to_string(attachment.id) + "_" + attachment.filename;
|
||||||
|
|
||||||
|
m_bot.request(attachment.url, dpp::http_method::m_get,
|
||||||
|
[this, 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)
|
||||||
|
m_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);
|
||||||
|
m_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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
116
src/main.cpp
Normal file
116
src/main.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include <dpp/dpp.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream> // Required for file operations
|
||||||
|
#include <vector> // Required for std::vector
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
#include "ImageProcessor.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
// --- Load the bot token from a file ---
|
||||||
|
string token_file_path = "token.txt";
|
||||||
|
|
||||||
|
ifstream token_file(token_file_path);
|
||||||
|
string bot_token;
|
||||||
|
if (!token_file.is_open()) {
|
||||||
|
// if not, try parent directory
|
||||||
|
if (!token_file.is_open()) {
|
||||||
|
token_file_path = "../token.txt";
|
||||||
|
token_file.open(token_file_path);
|
||||||
|
if (!token_file.is_open())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: Could not open token.txt. Please create the file and add your bot token." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getline(token_file, bot_token);
|
||||||
|
token_file.close();
|
||||||
|
|
||||||
|
if (bot_token.empty()) {
|
||||||
|
std::cerr << "ERROR: Token file is empty. Please add your bot token to token.txt." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dpp::cluster bot(bot_token, dpp::i_default_intents | dpp::i_message_content);
|
||||||
|
|
||||||
|
bot.on_log(dpp::utility::cout_logger()); // Corrected: no 'true' argument
|
||||||
|
|
||||||
|
std::cout<<"in main"<<endl;
|
||||||
|
// Create an instance of your ImageProcessor class
|
||||||
|
ImageProcessor image_processor(bot);
|
||||||
|
|
||||||
|
bot.on_slashcommand([&bot](const dpp::slashcommand_t& event) {
|
||||||
|
std::cout << "Received slash cmd" << std::endl << std::flush; // Keep for testing
|
||||||
|
bot.log(dpp::ll_info, "Received slash command: " + event.command.get_command_name());
|
||||||
|
if (event.command.get_command_name() == "ping") {
|
||||||
|
bot.log(dpp::ll_info, "Processing /ping command. Replying now!");
|
||||||
|
event.reply("Pong!");
|
||||||
|
} else {
|
||||||
|
bot.log(dpp::ll_info, "Received unknown slash command: " + event.command.get_command_name());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bot.on_ready([&bot](const dpp::ready_t& event) {
|
||||||
|
bot.log(dpp::ll_info, "Bot ready. Logged in as: " + bot.me.username);
|
||||||
|
|
||||||
|
if (dpp::run_once<struct register_bot_commands>()) {
|
||||||
|
bot.log(dpp::ll_info, "Registering global /ping command...");
|
||||||
|
bot.global_command_create(dpp::slashcommand("ping", "Ping pong!", bot.me.id));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bot.on_message_create([&image_processor, &bot](const dpp::message_create_t& 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;
|
||||||
|
|
||||||
|
image_processor.process_attachment(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;
|
||||||
|
|
||||||
|
bot.start(dpp::st_wait);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
7988
src/stb_image.h
Normal file
7988
src/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
1724
src/stb_image_write.h
Normal file
1724
src/stb_image_write.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user