From 9c63ab103dc87ac5de8d0efd109edf7eff05df82 Mon Sep 17 00:00:00 2001 From: lemonsh Date: Sun, 17 Jul 2022 20:54:32 +0200 Subject: [PATCH] Implement quote search + make history depth configurable --- sample_uberbot.toml | 11 +++++++++-- src/commands/quotes.rs | 31 +++++++++++++++++++++++++++++++ src/config.rs | 9 ++++++++- src/database.rs | 9 +++++---- src/main.rs | 7 ++++--- 5 files changed, 57 insertions(+), 10 deletions(-) diff --git a/sample_uberbot.toml b/sample_uberbot.toml index 52bbdde..011cce9 100644 --- a/sample_uberbot.toml +++ b/sample_uberbot.toml @@ -3,10 +3,17 @@ host = "karx.xyz" port = 6697 tls = true username = "uberbot" +nickname = "amazingbot" # optional, default: same as username channels = ["#main", "#no-normies"] -mode = "+B" +mode = "+B" # optional, default: none prefix = "u!" -[spotify] +[bot] +db_path = "database.db3" # optional, default: uberbot.db3 +history_depth = 5 +search_limit = 5 # optional, default: 3 + +[spotify] # optional, spotify module disabled if missing spotify_client_id = "" spotify_client_secret = "" + diff --git a/src/commands/quotes.rs b/src/commands/quotes.rs index 05e36d9..f85c7ac 100644 --- a/src/commands/quotes.rs +++ b/src/commands/quotes.rs @@ -1,10 +1,21 @@ use crate::bot::{Command, Context}; use crate::database::Quote; use async_trait::async_trait; +use std::fmt::Write; pub struct Grab; pub struct Quot; +pub struct Search { + limit: usize +} + +impl Search { + pub fn new(limit: usize) -> Self { + Self { limit } + } +} + #[async_trait] impl Command for Grab { async fn execute(&mut self, msg: Context<'_>) -> anyhow::Result { @@ -53,3 +64,23 @@ impl Command for Quot { } } } + +#[async_trait] +impl Command for Search { + async fn execute(&mut self, msg: Context<'_>) -> anyhow::Result { + let query = if let Some(c) = msg.content { + c + } else { + return Ok("Invalid usage.".into()); + }; + let results = msg.db.search_quotes(query.into(), self.limit).await?; + if results.is_empty() { + return Ok("No results.".into()); + } + let mut buf = format!("{}/{} results:\r\n", results.len(), self.limit); + for q in results { + write!(buf, "\"{}\" ~{}\r\n", q.quote, q.author)?; + } + Ok(buf) + } +} \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index f1db7d5..6eb9ca3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,7 +4,7 @@ use serde::Deserialize; pub struct UberConfig { pub irc: IrcConfig, pub spotify: Option, - pub db_path: Option, + pub bot: BotConfig } #[derive(Deserialize)] @@ -24,3 +24,10 @@ pub struct IrcConfig { pub username: String, pub prefix: String, } + +#[derive(Deserialize)] +pub struct BotConfig { + pub db_path: Option, + pub history_depth: usize, + pub search_limit: Option +} \ No newline at end of file diff --git a/src/database.rs b/src/database.rs index 61cf51d..86b52bc 100644 --- a/src/database.rs +++ b/src/database.rs @@ -12,7 +12,7 @@ enum Task { oneshot::Sender>>, Option, ), - SearchQuotes(oneshot::Sender>>, String), + SearchQuotes(oneshot::Sender>>, String, usize), } pub struct DbExecutor { @@ -59,8 +59,8 @@ impl DbExecutor { }.optional(); tx.send(result).unwrap(); } - Task::SearchQuotes(tx, query) => { - tx.send(self.yield_quotes("select quote,username from quotes where quote like '%'||?1||'%' order by quote asc limit 5", params![query])).unwrap(); + Task::SearchQuotes(tx, query, limit) => { + tx.send(self.yield_quotes("select quote,username from quotes where quote like '%'||?1||'%' order by quote asc limit ?", params![query, limit])).unwrap(); } } } @@ -129,6 +129,7 @@ impl ExecutorConnection { search_quotes, Task::SearchQuotes, rusqlite::Result>, - query: String + query: String, + limit: usize ); } diff --git a/src/main.rs b/src/main.rs index 1f19995..93f5dbb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ use crate::bot::Bot; use crate::commands::eval::Eval; use crate::commands::help::Help; use crate::commands::leek::{Leet, Mock, Owo}; -use crate::commands::quotes::{Grab, Quot}; +use crate::commands::quotes::{Grab, Quot, Search}; use crate::commands::sed::Sed; use crate::commands::spotify::Spotify; use crate::commands::title::Title; @@ -68,7 +68,7 @@ async fn main() -> anyhow::Result<()> { let cfg: UberConfig = toml::from_str(&client_conf)?; - let (db_exec, db_conn) = DbExecutor::create(cfg.db_path.as_deref().unwrap_or("uberbot.db3"))?; + let (db_exec, db_conn) = DbExecutor::create(cfg.bot.db_path.as_deref().unwrap_or("uberbot.db3"))?; let exec_thread = thread::spawn(move || db_exec.run()); let uber_ver = concat!("Überbot ", env!("CARGO_PKG_VERSION")); @@ -93,7 +93,7 @@ async fn main() -> anyhow::Result<()> { let (ctx, _) = broadcast::channel(1); let (etx, mut erx) = unbounded_channel(); - let mut bot = Bot::new(cfg.irc.prefix, db_conn, 3, { + let mut bot = Bot::new(cfg.irc.prefix, db_conn, cfg.bot.history_depth, { let client = client.clone(); move |target, msg| Ok(client.send_privmsg(target, msg)?) }); @@ -106,6 +106,7 @@ async fn main() -> anyhow::Result<()> { bot.add_command("ev".into(), Eval::default()); bot.add_command("grab".into(), Grab); bot.add_command("quot".into(), Quot); + bot.add_command("qsearch".into(), Search::new(cfg.bot.search_limit.unwrap_or(3))); bot.add_trigger( Regex::new(r"^(?:(?\S+):\s+)?s/(?[^/]*)/(?[^/]*)(?:/(?[a-z]*))?\s*")?, Sed,