From 49d69cef5cf4e6238e3226f3f49ac8466a806034 Mon Sep 17 00:00:00 2001 From: lemon-sh Date: Thu, 27 Jan 2022 00:58:00 +0100 Subject: [PATCH] I GOT ZLINED --- Cargo.toml | 3 ++- src/database.rs | 25 ++++++++++++++-------- src/main.rs | 6 +++--- src/res/quote_tmpl.hbs | 46 +++++++++++++++++++++++++++++++++++++++++ src/res/quote_tmpl.html | 11 ---------- src/web_service.rs | 30 ++++++++++++++++++++++++++- 6 files changed, 96 insertions(+), 25 deletions(-) create mode 100644 src/res/quote_tmpl.hbs delete mode 100644 src/res/quote_tmpl.html diff --git a/Cargo.toml b/Cargo.toml index a8ef4b0..8b6e4e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ fancy-regex = "0.7" rspotify = { version = "0.11", default-features = false, features = ["client-reqwest", "reqwest-rustls-tls"] } htmlescape = "0.3" toml = "0.5" -serde = "1.0" +serde = { version = "1.0", features = ["derive"] } arrayvec = "0.7" rand = "0.8" meval = "0.2" @@ -27,6 +27,7 @@ rusqlite = { version = "0.26", features = ["bundled"] } warp = "0.3" futures-util = "0.3" irc = { version = "0.15", default-features = false } +handlebars = "4.2" [features] tls = ["irc/tls-rust"] diff --git a/src/database.rs b/src/database.rs index b85331e..bd8af2f 100644 --- a/src/database.rs +++ b/src/database.rs @@ -3,11 +3,12 @@ use tokio::sync::{ mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, oneshot, }; +use serde::Serialize; #[derive(Debug)] enum Task { - AddQuote(oneshot::Sender, String, String), - GetQuote(oneshot::Sender>, Option), + AddQuote(oneshot::Sender, Quote), + GetQuote(oneshot::Sender>, Option), // implement search WITH PAGINATION } @@ -16,6 +17,12 @@ pub struct DbExecutor { db: rusqlite::Connection, } +#[derive(Serialize, Debug)] +pub struct Quote { + pub author: String, + pub quote: String +} + impl DbExecutor { pub fn create(dbpath: &str) -> rusqlite::Result<(Self, ExecutorConnection)> { let (tx, rx) = unbounded_channel(); @@ -32,10 +39,10 @@ impl DbExecutor { pub fn run(mut self) { while let Some(task) = self.rx.blocking_recv() { match task { - Task::AddQuote(tx, quote, author) => { + Task::AddQuote(tx, quote) => { if let Err(e) = self.db.execute( "insert into quotes(quote,username) values(?,?)", - params![quote, author], + params![quote.quote, quote.author], ) { tracing::error!("A database error has occurred: {}", e); tx.send(false).unwrap(); @@ -45,9 +52,9 @@ impl DbExecutor { } Task::GetQuote(tx, author) => { let quote = if let Some(ref author) = author { - self.db.query_row("select quote,username from quotes where username=? order by random() limit 1", params![author], |v| Ok((v.get(0)?, v.get(1)?))) + self.db.query_row("select quote,username from quotes where username=? order by random() limit 1", params![author], |v| Ok(Quote {quote:v.get(0)?, author:v.get(1)?})) } else { - self.db.query_row("select quote,username from quotes order by random() limit 1", params![], |v| Ok((v.get(0)?, v.get(1)?))) + self.db.query_row("select quote,username from quotes order by random() limit 1", params![], |v| Ok(Quote {quote:v.get(0)?, author:v.get(1)?})) }.optional().unwrap_or_else(|e| { tracing::error!("A database error has occurred: {}", e); None @@ -72,12 +79,12 @@ impl Clone for ExecutorConnection { } impl ExecutorConnection { - pub async fn add_quote(&self, quote: String, author: String) -> bool { + pub async fn add_quote(&self, quote: Quote) -> bool { let (otx, orx) = oneshot::channel(); - self.tx.send(Task::AddQuote(otx, quote, author)).unwrap(); + self.tx.send(Task::AddQuote(otx, quote)).unwrap(); orx.await.unwrap() } - pub async fn get_quote(&self, author: Option) -> Option<(String, String)> { + pub async fn get_quote(&self, author: Option) -> Option { let (otx, orx) = oneshot::channel(); self.tx.send(Task::GetQuote(otx, author)).unwrap(); orx.await.unwrap() diff --git a/src/main.rs b/src/main.rs index 4433035..9aade81 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,7 @@ use tokio::sync::mpsc::{unbounded_channel}; use tracing_subscriber::EnvFilter; use crate::bots::{leek, misc, sed, title}; -use crate::database::{DbExecutor, ExecutorConnection}; +use crate::database::{DbExecutor, ExecutorConnection, Quote}; mod bots; mod database; @@ -299,7 +299,7 @@ async fn handle_privmsg( return Ok(()); } if let Some(prev_msg) = state.last_msgs.get(target) { - if state.db.add_quote(prev_msg.clone(), target.into()).await { + if state.db.add_quote(Quote{quote:prev_msg.clone(), author:target.into()}).await { state.client.send_privmsg(target, "Quote added")?; } else { state @@ -318,7 +318,7 @@ async fn handle_privmsg( "quot" => { if let Some(quote) = state.db.get_quote(remainder.map(ToString::to_string)).await { let mut resp = ArrayString::<512>::new(); - write!(resp, "\"{}\" ~{}", quote.0, quote.1)?; + write!(resp, "\"{}\" ~{}", quote.quote, quote.author)?; state.client.send_privmsg(origin, &resp)?; } else { state.client.send_privmsg(origin, "No quotes found")?; diff --git a/src/res/quote_tmpl.hbs b/src/res/quote_tmpl.hbs new file mode 100644 index 0000000..95b8636 --- /dev/null +++ b/src/res/quote_tmpl.hbs @@ -0,0 +1,46 @@ + + + + + + + + # überbot quotes + + +
+
+ + +
+ {{#if quotes}} + + + + + + + + + {{#each quotes}} + + + + + {{/each}} + +
AuthorQuote
{{author}}{{quote}}
+ {{/if}} +
+ + \ No newline at end of file diff --git a/src/res/quote_tmpl.html b/src/res/quote_tmpl.html deleted file mode 100644 index 2b3e585..0000000 --- a/src/res/quote_tmpl.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - # überbot quotes - - - - - \ No newline at end of file diff --git a/src/web_service.rs b/src/web_service.rs index 9e7bc04..0305659 100644 --- a/src/web_service.rs +++ b/src/web_service.rs @@ -4,8 +4,20 @@ use reqwest::StatusCode; use serde_json::Value::Null; use std::net::SocketAddr; use std::sync::Arc; +use handlebars::Handlebars; +use lazy_static::lazy_static; use tokio::sync::broadcast::Receiver; use warp::{reply, Filter, Reply}; +use serde::Serialize; +use crate::database::Quote; + +lazy_static! { + static ref HANDLEBARS: Handlebars<'static> = { + let mut reg = Handlebars::new(); + reg.register_template_string("quotes", include_str!("res/quote_tmpl.hbs")).unwrap(); + reg + }; +} pub async fn run( db: ExecutorConnection, @@ -33,8 +45,24 @@ pub async fn run( tracing::info!("Web service finished"); } +#[derive(Serialize)] +struct QuotesTemplate { + quotes: Option> +} + fn handle_get_quote(_: ExecutorConnection) -> impl Reply { - reply::html(include_str!("res/quote_tmpl.html")) + match HANDLEBARS.render("quotes", &QuotesTemplate{quotes: Some(vec![ + Quote{quote:"something".into(),author:"by someone".into()}, + Quote{quote:"something different".into(),author:"by someone else".into()}, + Quote{quote:"something even more different".into(),author:"by nobody".into()} + ])}) { + Ok(o) => reply::html(o).into_response(), + Err(e) => { + tracing::warn!("Error while rendering template: {}", e); + reply::with_status("Failed to render template", StatusCode::INTERNAL_SERVER_ERROR).into_response() + } + } + } #[allow(clippy::needless_pass_by_value)]