This commit is contained in:
lemonsh 2022-07-20 10:58:33 +02:00
parent c12509268a
commit cbbdcb145c
7 changed files with 67 additions and 22 deletions

View file

@ -2,7 +2,9 @@ use crate::bot::{Command, Context};
use async_trait::async_trait; use async_trait::async_trait;
const HELP: &str = concat!( const HELP: &str = concat!(
"=- \x1d\x02Überbot\x0f ", env!("CARGO_PKG_VERSION"), " -=\r\n", "=- \x1d\x02Überbot\x0f ",
env!("CARGO_PKG_VERSION"),
" -=\r\n",
" * waifu <category> * grab [count] <user>\r\n", " * waifu <category> * grab [count] <user>\r\n",
" * owo/mock/leet [user] * quot <user>\r\n", " * owo/mock/leet [user] * quot <user>\r\n",
" * ev <math expression> * qsearch <query>\r\n", " * ev <math expression> * qsearch <query>\r\n",

View file

@ -7,7 +7,7 @@ pub struct Grab;
pub struct Quot; pub struct Quot;
pub struct Search { pub struct Search {
limit: usize limit: usize,
} }
impl Search { impl Search {
@ -17,7 +17,7 @@ impl Search {
} }
pub struct SearchNext { pub struct SearchNext {
limit: usize limit: usize,
} }
impl SearchNext { impl SearchNext {
@ -83,7 +83,10 @@ impl Command for Search {
} else { } else {
return Ok("Invalid usage.".into()); return Ok("Invalid usage.".into());
}; };
let results = msg.db.search_quotes(msg.author.into(), query.into(), self.limit).await?; let results = msg
.db
.search_quotes(msg.author.into(), query.into(), self.limit)
.await?;
if results.is_empty() { if results.is_empty() {
return Ok("No results.".into()); return Ok("No results.".into());
} }
@ -104,7 +107,7 @@ impl Command for SearchNext {
let results = if let Some(o) = msg.db.advance_search(msg.author.into(), self.limit).await? { let results = if let Some(o) = msg.db.advance_search(msg.author.into(), self.limit).await? {
o o
} else { } else {
return Ok("You need to initiate a search first using 'qsearch'.".into()) return Ok("You need to initiate a search first using 'qsearch'.".into());
}; };
if results.is_empty() { if results.is_empty() {
return Ok("No results.".into()); return Ok("No results.".into());

View file

@ -47,7 +47,15 @@ async fn resolve_spotify(
resource_type: &str, resource_type: &str,
resource_id: &str, resource_id: &str,
) -> anyhow::Result<String> { ) -> anyhow::Result<String> {
if spotify.token.lock().await.unwrap().as_ref().unwrap().is_expired() { if spotify
.token
.lock()
.await
.unwrap()
.as_ref()
.unwrap()
.is_expired()
{
spotify.request_token().await?; spotify.request_token().await?;
} }
tracing::debug!( tracing::debug!(

View file

@ -5,7 +5,7 @@ pub struct UberConfig {
pub log_level: Option<String>, pub log_level: Option<String>,
pub irc: IrcConfig, pub irc: IrcConfig,
pub spotify: Option<SpotifyConfig>, pub spotify: Option<SpotifyConfig>,
pub bot: BotConfig pub bot: BotConfig,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -30,5 +30,5 @@ pub struct IrcConfig {
pub struct BotConfig { pub struct BotConfig {
pub db_path: Option<String>, pub db_path: Option<String>,
pub history_depth: usize, pub history_depth: usize,
pub search_limit: Option<usize> pub search_limit: Option<usize>,
} }

View file

@ -1,6 +1,6 @@
use std::collections::HashMap;
use rusqlite::{params, OptionalExtension, Params}; use rusqlite::{params, OptionalExtension, Params};
use serde::Serialize; use serde::Serialize;
use std::collections::HashMap;
use tokio::sync::{ use tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
oneshot, oneshot,
@ -14,8 +14,17 @@ enum Task {
oneshot::Sender<rusqlite::Result<Option<Quote>>>, oneshot::Sender<rusqlite::Result<Option<Quote>>>,
Option<String>, Option<String>,
), ),
StartSearch(oneshot::Sender<rusqlite::Result<Vec<Quote>>>, String, String, usize), StartSearch(
NextSearch(oneshot::Sender<rusqlite::Result<Option<Vec<Quote>>>>, String, usize) oneshot::Sender<rusqlite::Result<Vec<Quote>>>,
String,
String,
usize,
),
NextSearch(
oneshot::Sender<rusqlite::Result<Option<Vec<Quote>>>>,
String,
usize,
),
} }
pub struct DbExecutor { pub struct DbExecutor {
@ -66,27 +75,43 @@ impl DbExecutor {
tx.send(result).unwrap(); tx.send(result).unwrap();
} }
Task::StartSearch(tx, user, query, limit) => { Task::StartSearch(tx, user, query, limit) => {
tx.send(self.start_search(&mut searches, user, query, limit)).unwrap(); tx.send(self.start_search(&mut searches, user, query, limit))
.unwrap();
} }
Task::NextSearch(tx, user, limit) => { Task::NextSearch(tx, user, limit) => {
tx.send(self.next_search(&mut searches, &user, limit)).unwrap(); tx.send(self.next_search(&mut searches, &user, limit))
.unwrap();
} }
} }
tracing::debug!("task took {}ms", Instant::now().duration_since(before).as_secs_f64()/1000.0) tracing::debug!(
"task took {}ms",
Instant::now().duration_since(before).as_secs_f64() / 1000.0
)
} }
} }
fn start_search(&self, searches: &mut HashMap<String, (String, i64)>, user: String, query: String, limit: usize) -> rusqlite::Result<Vec<Quote>> { fn start_search(
&self,
searches: &mut HashMap<String, (String, i64)>,
user: String,
query: String,
limit: usize,
) -> rusqlite::Result<Vec<Quote>> {
let (quotes, oid) = self.yield_quotes_oid("select oid,quote,username from quotes where quote like '%'||?1||'%' order by oid asc limit ?", params![query, limit])?; let (quotes, oid) = self.yield_quotes_oid("select oid,quote,username from quotes where quote like '%'||?1||'%' order by oid asc limit ?", params![query, limit])?;
searches.insert(user, (query, oid)); searches.insert(user, (query, oid));
Ok(quotes) Ok(quotes)
} }
fn next_search(&self, searches: &mut HashMap<String, (String, i64)>, user: &str, limit: usize) -> rusqlite::Result<Option<Vec<Quote>>> { fn next_search(
&self,
searches: &mut HashMap<String, (String, i64)>,
user: &str,
limit: usize,
) -> rusqlite::Result<Option<Vec<Quote>>> {
let (query, old_oid) = if let Some(o) = searches.get_mut(user) { let (query, old_oid) = if let Some(o) = searches.get_mut(user) {
o o
} else { } else {
return Ok(None) return Ok(None);
}; };
let (quotes, new_oid) = self.yield_quotes_oid("select oid,quote,username from quotes where oid > ? and quote like '%'||?||'%' order by oid asc limit ?", params![*old_oid, &*query, limit])?; let (quotes, new_oid) = self.yield_quotes_oid("select oid,quote,username from quotes where oid > ? and quote like '%'||?||'%' order by oid asc limit ?", params![*old_oid, &*query, limit])?;
if new_oid != -1 { if new_oid != -1 {
@ -95,7 +120,11 @@ impl DbExecutor {
Ok(Some(quotes)) Ok(Some(quotes))
} }
fn yield_quotes_oid<P: Params>(&self, sql: &str, params: P) -> rusqlite::Result<(Vec<Quote>, i64)> { fn yield_quotes_oid<P: Params>(
&self,
sql: &str,
params: P,
) -> rusqlite::Result<(Vec<Quote>, i64)> {
let mut lastoid = -1i64; let mut lastoid = -1i64;
let quotes = self.db.prepare(sql).and_then(|mut v| { let quotes = self.db.prepare(sql).and_then(|mut v| {
v.query(params).and_then(|mut v| { v.query(params).and_then(|mut v| {

View file

@ -16,7 +16,9 @@ impl MessageHistory {
pub async fn last_msg(&self, user: &str) -> Option<String> { pub async fn last_msg(&self, user: &str) -> Option<String> {
let map = self.map.read().await; let map = self.map.read().await;
map.get(user).and_then(|d| d.get(0)).map(ToString::to_string) map.get(user)
.and_then(|d| d.get(0))
.map(ToString::to_string)
} }
pub async fn last_msgs(&self, user: &str, count: usize) -> Option<Vec<String>> { pub async fn last_msgs(&self, user: &str, count: usize) -> Option<Vec<String>> {

View file

@ -1,10 +1,10 @@
#![allow(clippy::module_name_repetitions)] #![allow(clippy::module_name_repetitions)]
use fancy_regex::Regex; use fancy_regex::Regex;
use std::{env, fs};
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use std::thread; use std::thread;
use std::{env, fs};
use crate::bot::Bot; use crate::bot::Bot;
use crate::commands::eval::Eval; use crate::commands::eval::Eval;
@ -72,7 +72,8 @@ async fn main() -> anyhow::Result<()> {
}) })
.init(); .init();
let (db_exec, db_conn) = DbExecutor::create(cfg.bot.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 exec_thread = thread::spawn(move || db_exec.run());
let uber_ver = concat!("Überbot ", env!("CARGO_PKG_VERSION")); let uber_ver = concat!("Überbot ", env!("CARGO_PKG_VERSION"));