diff --git a/src/discord/album.rs b/src/discord/album.rs index a758f60..8e0f74e 100644 --- a/src/discord/album.rs +++ b/src/discord/album.rs @@ -1,56 +1,37 @@ use crate::album_manager::AlbumQuery; +use crate::config::GlobalData; +use crate::discord::Context; use crate::error::Error; -use crate::{command, group, GlobalData}; -use serenity::client::Context; -use serenity::framework::standard::{Args, CommandResult}; -use serenity::model::channel::Message; +use poise::serenity_prelude::{Attachment, MessageBuilder}; -#[group] -#[commands(add_image, list_albums)] -pub struct AlbumCmd; +#[poise::command(prefix_command, category = "Albums")] +pub async fn add_image( + ctx: Context<'_>, + #[description = "Album to add image to"] album_name: String, + #[description = "Image tags"] tags: Vec, + #[description = "Image to upload"] images: Vec, +) -> Result<(), Error> { + for attachment in &images { + let data = attachment.download().await?; -#[command] -#[min_args(1)] -#[description("Add an image to an album")] -#[usage("")] -async fn add_image(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { - let album_name = args.parse::()?; - args.advance(); - let tags: Vec = args.rest().split(',').map(|s| s.to_string()).collect(); - - let mut data = ctx.data.write().await; - - let global_data = data.get_mut::().unwrap(); - - for attachment in &msg.attachments { - let data = attachment.download().await.unwrap(); - - global_data + ctx.data() .picox .add_image(&album_name, tags.clone(), &attachment.filename, data) .await?; } - let plural = if msg.attachments.len() > 1 { "s" } else { "" }; + let plural = if images.len() > 1 { "s" } else { "" }; - msg.reply( - &ctx.http, - format!("Image{} added to {}!", plural, album_name), - ) - .await?; + ctx.reply(format!("Image{} added to {}!", plural, album_name)) + .await?; Ok(()) } -#[command] -#[aliases("albums")] -#[description("List all album commands.")] -async fn list_albums(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { - let data = ctx.data.read().await; - - let global_data = data.get::().unwrap(); - - let albums = global_data +#[poise::command(prefix_command, category = "Albums")] +pub async fn list_albums(ctx: Context<'_>) -> Result<(), Error> { + let albums = ctx + .data() .picox .query_album(AlbumQuery { album_name: None }) .await?; @@ -58,29 +39,30 @@ async fn list_albums(ctx: &Context, msg: &Message, _args: Args) -> CommandResult let album_names: Vec = albums.iter().map(|a| a.album_name.clone()).collect(); if album_names.is_empty() { - msg.reply(&ctx.http, "There are no albums in picox!") - .await?; + ctx.reply("There are no albums in picox!").await?; } else { - msg.reply( - &ctx.http, - format!("**Albums**:\n{}", album_names.join("\n")), - ) - .await?; + let mut message_builder = MessageBuilder::new(); + + message_builder.push_bold_line("Albums:"); + + for album in &album_names { + message_builder.push_line(format!("* {}", album)); + } + + ctx.reply(message_builder.build()).await?; } Ok(()) } pub async fn parse_album( - ctx: &Context, - msg: &Message, + ctx: &poise::serenity_prelude::Context, + msg: &poise::serenity_prelude::Message, + data: &GlobalData, album_name: &str, tags: Vec<&str>, ) -> Result { - let data = ctx.data.read().await; - let global_data = data.get::().unwrap(); - - let img = match global_data.picox.get_random_image(album_name, tags).await { + let img = match data.picox.get_random_image(album_name, tags).await { Ok(img) => img, Err(_) => return Ok(false), }; diff --git a/src/discord/mod.rs b/src/discord/mod.rs index 4fcaceb..2a98d3b 100644 --- a/src/discord/mod.rs +++ b/src/discord/mod.rs @@ -1,13 +1,83 @@ mod admin; +mod album; mod celeryman; use crate::config::GlobalData; use crate::error::Error; +use log::info; +use magick_rust::bindings::wchar_t; -use poise::{serenity_prelude as serenity, FrameworkOptions}; +use poise::serenity_prelude::Message; +use poise::{find_command, serenity_prelude as serenity, FrameworkOptions}; pub type Context<'a> = poise::Context<'a, GlobalData, Error>; +async fn event_handler( + ctx: &serenity::Context, + event: &serenity::FullEvent, + framework: poise::FrameworkContext<'_, GlobalData, Error>, + data: &GlobalData, +) -> Result<(), Error> { + match event { + serenity::FullEvent::Ready { data_about_bot, .. } => { + info!("Bot ready, and logged in as {}", data_about_bot.user.name); + } + serenity::FullEvent::Message { new_message } => { + if new_message.content.starts_with("!") { + if find_command( + &framework.options.commands, + &new_message.content, + true, + &mut Vec::new(), + ) + .is_none() + { + handle_unrecognised_commands(ctx, new_message, data).await?; + } + } + } + _ => {} + } + Ok(()) +} + +async fn handle_unrecognised_commands( + ctx: &serenity::Context, + message: &Message, + data: &GlobalData, +) -> Result<(), Error> { + let command_parts: Vec<&str> = message.content.split(" ").collect(); + let command = command_parts[0].replace("!", ""); + + let tags = if command_parts.len() > 1 { + command_parts[1..].to_vec() + } else { + Vec::new() + }; + + let parsed_album = album::parse_album(ctx, message, data, &command, tags) + .await + .unwrap_or_else(|e| { + println!("Error processing album command: {}", e); + true + }); + + if !parsed_album { + // handle random later + } + + Ok(()) +} + +async fn pre_command(ctx: Context<'_>) { + info!( + "User '{}' is running command '{}' in channel '{}'", + ctx.author().name, + ctx.invoked_command_name(), + ctx.channel_id() + ); +} + pub async fn run_bot(global_data: GlobalData) { let framework_options: FrameworkOptions = poise::FrameworkOptions { prefix_options: poise::PrefixFrameworkOptions { @@ -29,7 +99,13 @@ pub async fn run_bot(global_data: GlobalData) { admin::debug_buddy(), admin::op_give(), admin::list_tasks(), + album::add_image(), + album::list_albums(), ], + event_handler: |ctx, event, framework, data| { + Box::pin(event_handler(ctx, event, framework, data)) + }, + pre_command: |ctx| Box::pin(pre_command(ctx)), ..Default::default() };