From d191a339f8dc2e1be0e368ac756d801a8bd4aebf Mon Sep 17 00:00:00 2001 From: lemon-sh Date: Sun, 30 Jan 2022 18:26:09 +0100 Subject: [PATCH] Improve the web service --- src/database.rs | 83 +++++++++++++++++++++++++----------------- src/main.rs | 8 ++-- src/res/quote_tmpl.hbs | 2 +- src/web_service.rs | 15 +++++--- 4 files changed, 64 insertions(+), 44 deletions(-) diff --git a/src/database.rs b/src/database.rs index f118756..5fd42ba 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,4 +1,4 @@ -use rusqlite::{params, OptionalExtension}; +use rusqlite::{params, OptionalExtension, Params}; use serde::Serialize; use tokio::sync::{ mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, @@ -10,7 +10,7 @@ enum Task { AddQuote(oneshot::Sender, Quote), GetQuote(oneshot::Sender>, Option), Search(oneshot::Sender>>, String), - Random20(oneshot::Sender>>) + Random20(oneshot::Sender>>), } pub struct DbExecutor { @@ -63,35 +63,39 @@ impl DbExecutor { tx.send(quote).unwrap(); } Task::Search(tx, query) => { - tx.send(match self.db - .prepare("select quote,username from quotes where quote like '%'||?1||'%' order by quote asc limit 50") - .and_then(|mut v| v.query(params![query]) - .and_then(|mut v| { - let mut quotes: Vec = Vec::with_capacity(50); - while let Some(row) = v.next()? { - quotes.push(Quote { - quote: row.get(0)?, - author: row.get(1)?, - }); - } - Ok(quotes) - })) - { - Ok(o) => { - Some(o) - } - Err(e) => { - tracing::error!("A database error has occurred: {}", e); - None - } - }).unwrap(); + tx.send(self.yield_quotes("select quote,username from quotes where quote like '%'||?1||'%' order by quote asc limit 50", params![query])).unwrap(); } Task::Random20(tx) => { - tx.send(None).unwrap(); + tx.send(self.yield_quotes( + "select quote,username from quotes order by random() limit 20", + params![], + )) + .unwrap(); } } } } + + fn yield_quotes(&self, sql: &str, params: P) -> Option> { + match self.db.prepare(sql).and_then(|mut v| { + v.query(params).and_then(|mut v| { + let mut quotes: Vec = Vec::with_capacity(50); + while let Some(row) = v.next()? { + quotes.push(Quote { + quote: row.get(0)?, + author: row.get(1)?, + }); + } + Ok(quotes) + }) + }) { + Ok(o) => Some(o), + Err(e) => { + tracing::error!("A database error has occurred: {}", e); + None + } + } + } } pub struct ExecutorConnection { @@ -107,13 +111,20 @@ impl Clone for ExecutorConnection { } macro_rules! executor_wrapper { - ($name:ident, $task:expr, $ret:ty, $($arg:ident: $ty:ty),*) => { - pub async fn $name(&self, $($arg: $ty),*) -> $ret { - let (otx, orx) = oneshot::channel(); - self.tx.send($task(otx, $($arg),*)).unwrap(); - orx.await.unwrap() - } - } + ($name:ident, $task:expr, $ret:ty, $($arg:ident: $ty:ty),*) => { + pub async fn $name(&self, $($arg: $ty),*) -> $ret { + let (otx, orx) = oneshot::channel(); + self.tx.send($task(otx, $($arg),*)).unwrap(); + orx.await.unwrap() + } + }; + ($name:ident, $task:expr, $ret:ty) => { + pub async fn $name(&self) -> $ret { + let (otx, orx) = oneshot::channel(); + self.tx.send($task(otx)).unwrap(); + orx.await.unwrap() + } + }; } impl ExecutorConnection { @@ -125,5 +136,11 @@ impl ExecutorConnection { Option, author: Option ); - executor_wrapper!(search, Task::Search, Option>, query: String); + executor_wrapper!( + search, + Task::Search, + Option>, + query: String + ); + executor_wrapper!(random20, Task::Random20, Option>); } diff --git a/src/main.rs b/src/main.rs index 13f8023..a16d69a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -296,7 +296,7 @@ async fn handle_privmsg( if target == author { state .client - .send_privmsg(target, "You can't grab yourself")?; + .send_privmsg(origin, "You can't grab yourself")?; return Ok(()); } if let Some(prev_msg) = state.last_msgs.get(target) { @@ -308,16 +308,16 @@ async fn handle_privmsg( }) .await { - state.client.send_privmsg(target, "Quote added")?; + state.client.send_privmsg(origin, "Quote added")?; } else { state .client - .send_privmsg(target, "A database error has occurred")?; + .send_privmsg(origin, "A database error has occurred")?; } } else { state .client - .send_privmsg(target, "No previous messages to grab")?; + .send_privmsg(origin, "No previous messages to grab")?; } } else { state.client.send_privmsg(origin, "No nickname to grab")?; diff --git a/src/res/quote_tmpl.hbs b/src/res/quote_tmpl.hbs index 85d6be3..6c19baf 100644 --- a/src/res/quote_tmpl.hbs +++ b/src/res/quote_tmpl.hbs @@ -19,7 +19,7 @@
diff --git a/src/web_service.rs b/src/web_service.rs index 97df282..ab042e2 100644 --- a/src/web_service.rs +++ b/src/web_service.rs @@ -58,16 +58,19 @@ struct QuotesTemplate { #[derive(Deserialize)] struct QuotesQuery { - query: Option, + q: Option } async fn handle_get_quote(query: QuotesQuery, db: ExecutorConnection) -> impl Reply { - let template = if let Some(query) = query.query { - if let Some(quotes) = db.search(query.clone()).await { + let template = if let Some(q) = query.q { + if let Some(quotes) = db.search(q.clone()).await { let quotes_count = quotes.len(); QuotesTemplate { quotes: Some(quotes), - flash: Some(format!("Displaying {}/50 results for query \"{}\"", quotes_count, query)), + flash: Some(format!( + "Displaying {}/50 results for query \"{}\"", + quotes_count, q + )), } } else { QuotesTemplate { @@ -77,8 +80,8 @@ async fn handle_get_quote(query: QuotesQuery, db: ExecutorConnection) -> impl Re } } else { QuotesTemplate { - quotes: None, - flash: None, + quotes: db.random20().await, + flash: Some("Displaying up to 20 random quotes".into()), } }; match HANDLEBARS.render("quotes", &template) {