From cd8ed8bc5793985df2c1692072a932ceee517b95 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 8 Jul 2026 02:13:35 +0200 Subject: OPEN THE RUST GATES Signed-off-by: salmonik --- src/commands/trigger.rs | 199 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 src/commands/trigger.rs (limited to 'src/commands/trigger.rs') diff --git a/src/commands/trigger.rs b/src/commands/trigger.rs new file mode 100644 index 0000000..7453e03 --- /dev/null +++ b/src/commands/trigger.rs @@ -0,0 +1,199 @@ +use poise::serenity_prelude as serenity; + +use super::autocomplete::trigger_name; +use crate::Data; +use crate::database; +use crate::error::{Error, Result}; +use crate::lang; + +type Context<'a> = poise::Context<'a, Data, Error>; + +/// Trigger keyword management +#[poise::command( + slash_command, + subcommands("create", "add", "remove", "delete", "list", "help",) +)] +pub async fn trigger(_ctx: Context<'_>) -> Result<()> { + Ok(()) +} + +/// Create a new trigger group +#[poise::command(slash_command)] +pub async fn create( + ctx: Context<'_>, + #[description = "Logical group name"] + #[autocomplete = "trigger_name"] + name: String, +) -> Result<()> { + match database::create_trigger(&ctx.data().db_pool, &name).await { + Ok(_) => { + ctx.data().reload_triggers().await; + ctx.say(lang::fmt_trigger_created(&name)).await?; + } + Err(e) => { + ctx.say(lang::fmt_trigger_failed(&e)).await?; + } + } + Ok(()) +} + +/// Add keywords and/or responses to a trigger group +#[poise::command(slash_command)] +pub async fn add( + ctx: Context<'_>, + #[description = "Existing group name"] + #[autocomplete = "trigger_name"] + name: String, + #[description = "Keywords separated by \\"] trigger_keywords: Option, + #[description = "Responses separated by \\"] response: Option, +) -> Result<()> { + let t = database::get_trigger_by_name(&ctx.data().db_pool, &name) + .await? + .ok_or_else(|| lang::err_trigger_not_found())?; + + let mut modified = false; + if let Some(kw) = trigger_keywords { + for keyword in kw.split('\\') { + let k = keyword.trim(); + if !k.is_empty() { + database::add_keyword(&ctx.data().db_pool, t.id, k).await?; + modified = true; + } + } + } + if let Some(r) = response { + for resp in r.split('\\') { + let r = resp.trim(); + if !r.is_empty() { + database::add_response(&ctx.data().db_pool, t.id, r).await?; + modified = true; + } + } + } + + if modified { + ctx.data().reload_triggers().await; + } + ctx.say(lang::L_TRIGGER_UPDATED).await?; + Ok(()) +} + +/// Remove keyword or response from a group +#[poise::command(slash_command)] +pub async fn remove( + ctx: Context<'_>, + #[description = "Group name"] + #[autocomplete = "trigger_name"] + name: String, + #[description = "Keyword to remove"] trigger_keyword: Option, + #[description = "Response to remove"] response: Option, +) -> Result<()> { + let t = database::get_trigger_by_name(&ctx.data().db_pool, &name) + .await? + .ok_or_else(|| lang::err_trigger_not_found())?; + + let mut modified = false; + if let Some(kw) = trigger_keyword { + database::remove_keyword(&ctx.data().db_pool, t.id, &kw).await?; + modified = true; + } + if let Some(r) = response { + database::remove_response(&ctx.data().db_pool, t.id, &r).await?; + modified = true; + } + + if modified { + ctx.data().reload_triggers().await; + } + ctx.say(lang::L_TRIGGER_UPDATED).await?; + Ok(()) +} + +/// Delete an entire trigger group +#[poise::command(slash_command)] +pub async fn delete( + ctx: Context<'_>, + #[description = "Group name"] + #[autocomplete = "trigger_name"] + name: String, +) -> Result<()> { + let t = database::get_trigger_by_name(&ctx.data().db_pool, &name) + .await? + .ok_or_else(|| lang::err_trigger_not_found())?; + + database::delete_trigger(&ctx.data().db_pool, t.id).await?; + ctx.data().reload_triggers().await; + ctx.say(lang::fmt_trigger_deleted(&name)).await?; + Ok(()) +} + +/// List keywords and responses for a group +#[poise::command(slash_command)] +pub async fn list( + ctx: Context<'_>, + #[description = "Group name"] + #[autocomplete = "trigger_name"] + name: String, +) -> Result<()> { + let t = database::get_trigger_by_name(&ctx.data().db_pool, &name) + .await? + .ok_or_else(|| lang::err_trigger_not_found())?; + + let keywords = database::get_keywords(&ctx.data().db_pool, t.id).await?; + let responses = database::get_responses(&ctx.data().db_pool, t.id).await?; + + let mut embed = serenity::CreateEmbed::default() + .title(lang::fmt_trigger_title(&name)) + .color(0x00aaff); + + embed = embed.field( + "Keywords", + if keywords.is_empty() { + lang::L_TRIGGER_KW_NONE.into() + } else { + keywords + .iter() + .map(|r| format!("{r}")) + .collect::>() + .join("\n") + }, + false, + ); + embed = embed.field( + "Responses", + if responses.is_empty() { + lang::L_TRIGGER_KW_NONE.into() + } else { + responses + .iter() + .map(|r| format!("{r}")) + .collect::>() + .join("\n") + }, + false, + ); + + ctx.send(poise::CreateReply::default().embed(embed)).await?; + Ok(()) +} + +/// Display trigger command usage info +#[poise::command(slash_command)] +pub async fn help(ctx: Context<'_>) -> Result<()> { + let help = [ + "**Trigger Commands**", + "`/trigger create ` — Create new trigger group", + "`/trigger add ` — Add keywords/responses (separate with \\)", + "`/trigger remove ` — Remove keywords/responses", + "`/trigger delete ` — Delete entire group", + "`/trigger list ` — View group details", + ] + .join("\n"); + + ctx.say(help).await?; + Ok(()) +} + +pub fn commands() -> Vec> { + vec![trigger()] +} -- cgit v1.2.3