Album commands and dynamic commands working, if a bit hacky for now

This commit is contained in:
Joey Hines 2025-03-16 15:23:29 -06:00
parent 05591d49e3
commit da59ae0bc9
Signed by: joeyahines
GPG Key ID: 38BA6F25C94C9382
2 changed files with 111 additions and 53 deletions

View File

@ -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<String>,
#[description = "Image to upload"] images: Vec<Attachment>,
) -> Result<(), Error> {
for attachment in &images {
let data = attachment.download().await?;
#[command]
#[min_args(1)]
#[description("Add an image to an album")]
#[usage("<album_name>")]
async fn add_image(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
let album_name = args.parse::<String>()?;
args.advance();
let tags: Vec<String> = args.rest().split(',').map(|s| s.to_string()).collect();
let mut data = ctx.data.write().await;
let global_data = data.get_mut::<GlobalData>().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),
)
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::<GlobalData>().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<String> = 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<bool, Error> {
let data = ctx.data.read().await;
let global_data = data.get::<GlobalData>().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),
};

View File

@ -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<GlobalData, Error> = 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()
};