diff options
| author | salmonik <raisersoft@proton.me> | 2026-07-08 02:13:35 +0200 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-07-08 02:13:35 +0200 |
| commit | cd8ed8bc5793985df2c1692072a932ceee517b95 (patch) | |
| tree | 42d18a4140259b5c68b4dd05b7fcb398f78b8d7f /src/commands/trigger.rs | |
| parent | Merge pull request 'Voice related fixes, alongside simplifying assistant' (#5... (diff) | |
| download | senator-sperma-cd8ed8bc5793985df2c1692072a932ceee517b95.tar.gz senator-sperma-cd8ed8bc5793985df2c1692072a932ceee517b95.zip | |
OPEN THE RUST GATES
Signed-off-by: salmonik <raisersoft@proton.me>
Diffstat (limited to '')
| -rw-r--r-- | src/commands/trigger.rs | 199 |
1 files changed, 199 insertions, 0 deletions
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 @@ | |||
| 1 | use poise::serenity_prelude as serenity; | ||
| 2 | |||
| 3 | use super::autocomplete::trigger_name; | ||
| 4 | use crate::Data; | ||
| 5 | use crate::database; | ||
| 6 | use crate::error::{Error, Result}; | ||
| 7 | use crate::lang; | ||
| 8 | |||
| 9 | type Context<'a> = poise::Context<'a, Data, Error>; | ||
| 10 | |||
| 11 | /// Trigger keyword management | ||
| 12 | #[poise::command( | ||
| 13 | slash_command, | ||
| 14 | subcommands("create", "add", "remove", "delete", "list", "help",) | ||
| 15 | )] | ||
| 16 | pub async fn trigger(_ctx: Context<'_>) -> Result<()> { | ||
| 17 | Ok(()) | ||
| 18 | } | ||
| 19 | |||
| 20 | /// Create a new trigger group | ||
| 21 | #[poise::command(slash_command)] | ||
| 22 | pub async fn create( | ||
| 23 | ctx: Context<'_>, | ||
| 24 | #[description = "Logical group name"] | ||
| 25 | #[autocomplete = "trigger_name"] | ||
| 26 | name: String, | ||
| 27 | ) -> Result<()> { | ||
| 28 | match database::create_trigger(&ctx.data().db_pool, &name).await { | ||
| 29 | Ok(_) => { | ||
| 30 | ctx.data().reload_triggers().await; | ||
| 31 | ctx.say(lang::fmt_trigger_created(&name)).await?; | ||
| 32 | } | ||
| 33 | Err(e) => { | ||
| 34 | ctx.say(lang::fmt_trigger_failed(&e)).await?; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | Ok(()) | ||
| 38 | } | ||
| 39 | |||
| 40 | /// Add keywords and/or responses to a trigger group | ||
| 41 | #[poise::command(slash_command)] | ||
| 42 | pub async fn add( | ||
| 43 | ctx: Context<'_>, | ||
| 44 | #[description = "Existing group name"] | ||
| 45 | #[autocomplete = "trigger_name"] | ||
| 46 | name: String, | ||
| 47 | #[description = "Keywords separated by \\"] trigger_keywords: Option<String>, | ||
| 48 | #[description = "Responses separated by \\"] response: Option<String>, | ||
| 49 | ) -> Result<()> { | ||
| 50 | let t = database::get_trigger_by_name(&ctx.data().db_pool, &name) | ||
| 51 | .await? | ||
| 52 | .ok_or_else(|| lang::err_trigger_not_found())?; | ||
| 53 | |||
| 54 | let mut modified = false; | ||
| 55 | if let Some(kw) = trigger_keywords { | ||
| 56 | for keyword in kw.split('\\') { | ||
| 57 | let k = keyword.trim(); | ||
| 58 | if !k.is_empty() { | ||
| 59 | database::add_keyword(&ctx.data().db_pool, t.id, k).await?; | ||
| 60 | modified = true; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } | ||
| 64 | if let Some(r) = response { | ||
| 65 | for resp in r.split('\\') { | ||
| 66 | let r = resp.trim(); | ||
| 67 | if !r.is_empty() { | ||
| 68 | database::add_response(&ctx.data().db_pool, t.id, r).await?; | ||
| 69 | modified = true; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | if modified { | ||
| 75 | ctx.data().reload_triggers().await; | ||
| 76 | } | ||
| 77 | ctx.say(lang::L_TRIGGER_UPDATED).await?; | ||
| 78 | Ok(()) | ||
| 79 | } | ||
| 80 | |||
| 81 | /// Remove keyword or response from a group | ||
| 82 | #[poise::command(slash_command)] | ||
| 83 | pub async fn remove( | ||
| 84 | ctx: Context<'_>, | ||
| 85 | #[description = "Group name"] | ||
| 86 | #[autocomplete = "trigger_name"] | ||
| 87 | name: String, | ||
| 88 | #[description = "Keyword to remove"] trigger_keyword: Option<String>, | ||
| 89 | #[description = "Response to remove"] response: Option<String>, | ||
| 90 | ) -> Result<()> { | ||
| 91 | let t = database::get_trigger_by_name(&ctx.data().db_pool, &name) | ||
| 92 | .await? | ||
| 93 | .ok_or_else(|| lang::err_trigger_not_found())?; | ||
| 94 | |||
| 95 | let mut modified = false; | ||
| 96 | if let Some(kw) = trigger_keyword { | ||
| 97 | database::remove_keyword(&ctx.data().db_pool, t.id, &kw).await?; | ||
| 98 | modified = true; | ||
| 99 | } | ||
| 100 | if let Some(r) = response { | ||
| 101 | database::remove_response(&ctx.data().db_pool, t.id, &r).await?; | ||
| 102 | modified = true; | ||
| 103 | } | ||
| 104 | |||
| 105 | if modified { | ||
| 106 | ctx.data().reload_triggers().await; | ||
| 107 | } | ||
| 108 | ctx.say(lang::L_TRIGGER_UPDATED).await?; | ||
| 109 | Ok(()) | ||
| 110 | } | ||
| 111 | |||
| 112 | /// Delete an entire trigger group | ||
| 113 | #[poise::command(slash_command)] | ||
| 114 | pub async fn delete( | ||
| 115 | ctx: Context<'_>, | ||
| 116 | #[description = "Group name"] | ||
| 117 | #[autocomplete = "trigger_name"] | ||
| 118 | name: String, | ||
| 119 | ) -> Result<()> { | ||
| 120 | let t = database::get_trigger_by_name(&ctx.data().db_pool, &name) | ||
| 121 | .await? | ||
| 122 | .ok_or_else(|| lang::err_trigger_not_found())?; | ||
| 123 | |||
| 124 | database::delete_trigger(&ctx.data().db_pool, t.id).await?; | ||
| 125 | ctx.data().reload_triggers().await; | ||
| 126 | ctx.say(lang::fmt_trigger_deleted(&name)).await?; | ||
| 127 | Ok(()) | ||
| 128 | } | ||
| 129 | |||
| 130 | /// List keywords and responses for a group | ||
| 131 | #[poise::command(slash_command)] | ||
| 132 | pub async fn list( | ||
| 133 | ctx: Context<'_>, | ||
| 134 | #[description = "Group name"] | ||
| 135 | #[autocomplete = "trigger_name"] | ||
| 136 | name: String, | ||
| 137 | ) -> Result<()> { | ||
| 138 | let t = database::get_trigger_by_name(&ctx.data().db_pool, &name) | ||
| 139 | .await? | ||
| 140 | .ok_or_else(|| lang::err_trigger_not_found())?; | ||
| 141 | |||
| 142 | let keywords = database::get_keywords(&ctx.data().db_pool, t.id).await?; | ||
| 143 | let responses = database::get_responses(&ctx.data().db_pool, t.id).await?; | ||
| 144 | |||
| 145 | let mut embed = serenity::CreateEmbed::default() | ||
| 146 | .title(lang::fmt_trigger_title(&name)) | ||
| 147 | .color(0x00aaff); | ||
| 148 | |||
| 149 | embed = embed.field( | ||
| 150 | "Keywords", | ||
| 151 | if keywords.is_empty() { | ||
| 152 | lang::L_TRIGGER_KW_NONE.into() | ||
| 153 | } else { | ||
| 154 | keywords | ||
| 155 | .iter() | ||
| 156 | .map(|r| format!("{r}")) | ||
| 157 | .collect::<Vec<_>>() | ||
| 158 | .join("\n") | ||
| 159 | }, | ||
| 160 | false, | ||
| 161 | ); | ||
| 162 | embed = embed.field( | ||
| 163 | "Responses", | ||
| 164 | if responses.is_empty() { | ||
| 165 | lang::L_TRIGGER_KW_NONE.into() | ||
| 166 | } else { | ||
| 167 | responses | ||
| 168 | .iter() | ||
| 169 | .map(|r| format!("{r}")) | ||
| 170 | .collect::<Vec<_>>() | ||
| 171 | .join("\n") | ||
| 172 | }, | ||
| 173 | false, | ||
| 174 | ); | ||
| 175 | |||
| 176 | ctx.send(poise::CreateReply::default().embed(embed)).await?; | ||
| 177 | Ok(()) | ||
| 178 | } | ||
| 179 | |||
| 180 | /// Display trigger command usage info | ||
| 181 | #[poise::command(slash_command)] | ||
| 182 | pub async fn help(ctx: Context<'_>) -> Result<()> { | ||
| 183 | let help = [ | ||
| 184 | "**Trigger Commands**", | ||
| 185 | "`/trigger create <name>` — Create new trigger group", | ||
| 186 | "`/trigger add <name> <trigger> <response>` — Add keywords/responses (separate with \\)", | ||
| 187 | "`/trigger remove <name> <trigger> <response>` — Remove keywords/responses", | ||
| 188 | "`/trigger delete <name>` — Delete entire group", | ||
| 189 | "`/trigger list <name>` — View group details", | ||
| 190 | ] | ||
| 191 | .join("\n"); | ||
| 192 | |||
| 193 | ctx.say(help).await?; | ||
| 194 | Ok(()) | ||
| 195 | } | ||
| 196 | |||
| 197 | pub fn commands() -> Vec<poise::Command<Data, Error>> { | ||
| 198 | vec![trigger()] | ||
| 199 | } | ||
