use chrono::{Datelike, Local}; use serenity::{all::{GuildId, UserId}, builder::{CreateEmbed, CreateMessage}, client::Context, http::Http, model::Colour}; // use anyhow::Ok; use sqlx::{Connection, FromRow, SqliteConnection}; use crate::util::debug::send_error; use crate::util::utilities; use std::{env, sync::Arc}; use tenorv2::{tenor, tenor_builder::Tenor, tenor_types::{ContentFilter, MediaFilter}}; // pub async fn notice_wrapper(http: Arc) { pub async fn notice_wrapper(ctx: Context) { match notice(ctx.http.clone()).await { Err(e) => { let _ = send_error(ctx.http.clone(), e.to_string()).await; return; }, Result::Ok(_) => return } } /// Send embed with event name and optional special message to guild's general channel async fn announce_event(guild_id: GuildId, name: &str, special_message: &str, http: Arc) -> anyhow::Result<()> { let mut event_embed = CreateEmbed::new() .color(Colour::new(rand::random::() % 0xFFFFFF)) .title("Today's event is:"); let system_channel = utilities::get_system_channel(guild_id, &http).await?; if special_message.contains("http") { event_embed = event_embed.description(name); system_channel.send_message(http.clone(), CreateMessage::new().add_embed(event_embed.clone()).content(special_message)).await?; // Ok(()); } event_embed = event_embed.field(name, special_message, true); system_channel.send_message(http.clone(), CreateMessage::new().add_embed(event_embed)).await?; Ok(()) } /// Send birthday embed to guild's general channel async fn celebrate_birthday(guild_id: GuildId, user_id: UserId, nick: &str, http: Arc) -> anyhow::Result<()> { const LIMIT: u8 = 20; let tenor_response = Tenor::new()? .random(true) .contentfilter(ContentFilter::low) .add_media_filter(MediaFilter::gif) .locale("sk".to_string()) .search("vsetko najlepsie").await?; let index = rand::random::() % LIMIT as usize; let gif_url = match tenor::get_gif_url(MediaFilter::gif, tenor_response) { Ok(urls) => Some(urls), Err(e) => { let _ = send_error(http.clone(), e.to_string()).await; None } }; let system_channel = utilities::get_system_channel(guild_id, &http).await?; let mut embed = CreateEmbed::new() .color(Colour::new(rand::random::() % 0xFFFFFF)) .title(format!("HAPPY BIRTHDAY {}!", nick)) .description(format!("<@{}>'s birthday is today!!! Yay!", user_id.get())); if gif_url.is_some() { embed = embed.image(gif_url.unwrap()[index].as_str()); } system_channel.send_message(http.clone(), CreateMessage::new().add_embed(embed.clone())).await?; Ok(()) } #[derive(Clone, FromRow, Debug)] struct BirthdayRow { #[sqlx(try_from="i64")] id: u64, nick: String, } #[derive(Clone, FromRow, Debug)] struct EventRow { id: u32, #[sqlx(try_from="i64")] guild: u64, name: String, year: i32, special_message: String, } /// Fetches guild/global events and birthdays for current day /// Sends notification to relevant channels async fn notice(http: Arc) -> anyhow::Result<()> { use anyhow::Context; let local = Local::now(); let day = local.day(); let month = local.month(); let year = local.year(); let db_path = env::var("DATABASE_URL").context("DATABASE_URL not found in env")?; let mut db = SqliteConnection::connect(db_path.as_str()).await?; let birtdays = sqlx::query_as::<_, BirthdayRow>( "SELECT id, nick FROM birthdays WHERE day=? AND month=?;" ) .bind(day) .bind(month) .fetch_all(&mut db) .await?; let global_events = sqlx::query_as::<_, EventRow>( "SELECT id, guild, name, year, special_message from events WHERE day=? AND month=? AND guild=0;" ) .bind(day) .bind(month) .fetch_all(&mut db) .await?; let guilds = http.get_guilds(None, None).await?; for guild in guilds { let guild_id = guild.id; for bd in &birtdays { let user_id = UserId::new(bd.id); match guild_id.member(http.clone(), user_id).await { Ok(_) => (), Err(_) => continue }; let _ = celebrate_birthday(guild_id, user_id, bd.nick.as_str(), http.clone()).await; } // TODO if has year delete it from announce and delete for e in &global_events { if e.year != 0 && e.year != year { continue; } let _ = announce_event(guild_id, e.name.as_str(), e.special_message.as_str(), http.clone()).await; } } let guild_events = sqlx::query_as::<_, EventRow>( "SELECT id, guild, name, year, special_message from events WHERE day=? AND month=? AND guild!=0;" ) .bind(day) .bind(month) .fetch_all(&mut db) .await?; // TODO if has year delete it from announce and delete for e in &guild_events { announce_event(GuildId::new(e.guild), e.name.as_str(), e.special_message.as_str(), http.clone()).await?; } Ok(()) }