use poise::serenity_prelude as serenity; use super::autocomplete::audio_file; use crate::Data; use crate::database; use crate::error::{Error, Result}; use crate::lang; type Context<'a> = poise::Context<'a, Data, Error>; /// Cron job management #[poise::command( slash_command, subcommands("dodaj_audio", "dodaj_wiadomość", "pokaż", "usuń", "pauza", "wznów",) )] pub async fn cron(_ctx: Context<'_>) -> Result<()> { Ok(()) } /// Schedule audio playback #[poise::command(slash_command)] pub async fn dodaj_audio( ctx: Context<'_>, #[description = "Cron expression (e.g. \"37 21 * * *\" = every day at 21:37)"] cron_expression: String, #[description = "Target voice channel"] channel: serenity::Channel, #[description = "Copyparty URL of audio file"] #[autocomplete = "audio_file"] audio_filename: String, ) -> Result<()> { let channel_id = match channel { serenity::Channel::Guild(ch) => ch.id.get() as i64, _ => return Err(lang::err_bad_channel_type()), }; database::add_cron_job( &ctx.data().db_pool, &cron_expression, "audio", channel_id, Some(&audio_filename), None, ) .await?; ctx.say(lang::fmt_cron_audio_queued(&cron_expression)) .await?; Ok(()) } /// Schedule a periodic message #[poise::command(slash_command)] pub async fn dodaj_wiadomość( ctx: Context<'_>, #[description = "Cron expression (e.g. \"37 21 * * *\" = every day at 21:37)"] cron_expression: String, #[description = "Docelowy kanał tekstowy"] channel: serenity::Channel, #[description = "Zawartość wiadomości"] message: String, ) -> Result<()> { let channel_id = match channel { serenity::Channel::Guild(ch) => ch.id.get() as i64, _ => return Err(lang::err_bad_channel_type()), }; database::add_cron_job( &ctx.data().db_pool, &cron_expression, "wiadomość", channel_id, None, Some(&message), ) .await?; ctx.say(lang::L_CRON_QUEUED).await?; Ok(()) } /// List all cron jobs #[poise::command(slash_command)] pub async fn pokaż(ctx: Context<'_>) -> Result<()> { let jobs = database::list_cron_jobs(&ctx.data().db_pool).await?; if jobs.is_empty() { ctx.say(lang::L_CRON_NONE).await?; return Ok(()); } let mut embed = serenity::CreateEmbed::default() .title(lang::L_CRON_TITLE) .color(0x00aaff); for job in &jobs { let status = if job.active == 1 { lang::L_CRON_ACTIVE } else { lang::L_CRON_PAUSED }; let desc = match job.r#type.as_str() { "audio" => lang::fmt_cron_label_audio(job.audio_filename.as_deref().unwrap_or("?")), _ => lang::fmt_cron_label_msg(job.message.as_deref().unwrap_or("?")), }; embed = embed.field( lang::fmt_cron_job_status(job.id, status), lang::fmt_cron_field(&job.cron_expression, job.channel_id, &desc), false, ); } ctx.send(poise::CreateReply::default().embed(embed)).await?; Ok(()) } /// Remove a cron job #[poise::command(slash_command)] pub async fn usuń( ctx: Context<'_>, #[description = "ID pracy do usunięcia"] job_id: i64, ) -> Result<()> { if database::delete_cron_job(&ctx.data().db_pool, job_id).await? { ctx.say(lang::fmt_cron_deleted(job_id)).await?; } else { ctx.say(lang::fmt_cron_not_found(job_id)).await?; } Ok(()) } /// Pause a cron job #[poise::command(slash_command)] pub async fn pauza( ctx: Context<'_>, #[description = "ID pracy do zapauzowania"] job_id: i64, ) -> Result<()> { if database::set_cron_job_active(&ctx.data().db_pool, job_id, false).await? { ctx.say(lang::fmt_cron_paused(job_id)).await?; } else { ctx.say(lang::fmt_cron_not_found(job_id)).await?; } Ok(()) } /// Resume a paused cron job #[poise::command(slash_command)] pub async fn wznów( ctx: Context<'_>, #[description = "ID pracy cron do wznowienia"] job_id: i64, ) -> Result<()> { if database::set_cron_job_active(&ctx.data().db_pool, job_id, true).await? { ctx.say(lang::fmt_cron_resumed(job_id)).await?; } else { ctx.say(lang::fmt_cron_not_found(job_id)).await?; } Ok(()) } pub fn commands() -> Vec> { vec![cron()] }