use crate::album_manager::AlbumQuery; use crate::models::motivation::{Motivation, MotivationConfig}; use crate::{command, group, GlobalData}; use magick_rust::{DrawingWand, MagickWand, PixelWand}; use reqwest::Client; use serenity::builder::{CreateAttachment, CreateMessage}; use serenity::client::Context; use serenity::framework::standard::{Args, CommandError, CommandResult}; use serenity::model::channel::Message; use std::borrow::Cow; #[group] #[commands(motivation, motivation_add_album)] pub struct Motivate; pub async fn create_motivation_image(motivation: Motivation) -> Result, CommandError> { let client = Client::new(); let motivation_image_blob = client .get(motivation.image.link) .send() .await? .bytes() .await? .to_vec(); let text = format!("{} {}", motivation.action, motivation.goal); let mut wand = MagickWand::new(); let mut border_wand = PixelWand::new(); wand.read_image_blob(motivation_image_blob)?; border_wand.set_color(&motivation.border_color)?; let width = wand.get_image_width(); let border = width / 100; wand.border_image( &border_wand, border, border, magick_rust::bindings::CompositeOperator_OverCompositeOp.into(), )?; border_wand.set_color("black")?; let width = wand.get_image_width(); let border = width * 20 / 100; wand.border_image( &border_wand, border, border, magick_rust::bindings::CompositeOperator_OverCompositeOp.into(), )?; let text_pos_x = wand.get_image_width() as f64 / 2.0; let text_pos_y = wand.get_image_height() as f64 - (wand.get_image_height() as f64 * 0.05); let mut text_wand = DrawingWand::new(); let mut text_color_wand = PixelWand::new(); text_color_wand.set_color("white")?; text_wand.set_fill_color(&text_color_wand); text_wand.set_font_size(0.07 * (wand.get_image_width() as f64)); text_wand.set_text_alignment(magick_rust::AlignType::Center); wand.annotate_image(&text_wand, text_pos_x, text_pos_y, 0.0, &text)?; Ok(wand.write_image_blob("jpg")?) } #[command] #[description("Let's give you motivation")] async fn motivation(ctx: &Context, msg: &Message, args: Args) -> CommandResult { let data = ctx.data.read().await; let global_data = data.get::().unwrap(); let album_name = if args.is_empty() { None } else { Some(args.parse::()?) }; let motivation = MotivationConfig::generate_motivation( &global_data.db, &global_data.picox, "white", album_name, ) .await?; let image = create_motivation_image(motivation).await?; msg.channel_id .send_message( &ctx.http, CreateMessage::new() .content("Today's motivation") .add_file(CreateAttachment::bytes( Cow::from(image), "motivate.jpg".to_string(), )), ) .await?; Ok(()) } #[command] #[description("Add imgur album to the motivation generator")] async fn motivation_add_album(ctx: &Context, msg: &Message, args: Args) -> CommandResult { let data = ctx.data.read().await; let global_data = data.get::().unwrap(); let album = args.parse::()?; let albums = global_data .picox .query_album(AlbumQuery { album_name: Some(album), }) .await?; let album = if let Some(album) = albums.first().cloned() { album } else { msg.reply(&ctx.http, "Fake album tbh, try again!").await?; return Ok(()); }; MotivationConfig::add_album(&global_data.db, album.id)?; msg.reply(&ctx.http, "Done ;)").await?; Ok(()) }