FrenBot/src/discord/motivate.rs

130 lines
3.7 KiB
Rust

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<Vec<u8>, 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::<GlobalData>().unwrap();
let album_name = if args.is_empty() {
None
} else {
Some(args.parse::<String>()?)
};
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::<GlobalData>().unwrap();
let album = args.parse::<String>()?;
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(())
}