Rustfmt
This commit is contained in:
parent
25a7635408
commit
329f6d6dae
|
@ -1,14 +1,13 @@
|
||||||
use async_trait::async_trait;
|
|
||||||
use crate::bot::{Command, Context};
|
use crate::bot::{Command, Context};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
pub struct LastMsg;
|
pub struct LastMsg;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Command for LastMsg {
|
impl Command for LastMsg {
|
||||||
//noinspection RsNeedlessLifetimes
|
async fn execute(&mut self, msg: Context<'_>) -> anyhow::Result<String> {
|
||||||
async fn execute<'a>(&mut self, msg: Context<'a>) -> anyhow::Result<String> {
|
|
||||||
let nick = msg.content.unwrap_or(msg.author);
|
let nick = msg.content.unwrap_or(msg.author);
|
||||||
let lastmsg = msg.last_msg.read().await;
|
let lastmsg = msg.history.read().await;
|
||||||
Ok(format!("{}: {:?}", nick, lastmsg.get(nick)))
|
Ok(format!("{}: {:?}", nick, lastmsg.get(nick)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use rspotify::{ClientCredsSpotify, Credentials};
|
use crate::bot::{Context, Trigger};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use fancy_regex::Captures;
|
use fancy_regex::Captures;
|
||||||
use rspotify::clients::BaseClient;
|
use rspotify::clients::BaseClient;
|
||||||
use rspotify::model::{Id, PlayableItem};
|
use rspotify::model::{Id, PlayableItem};
|
||||||
use crate::bot::{Context, Trigger};
|
use rspotify::{ClientCredsSpotify, Credentials};
|
||||||
|
|
||||||
pub struct Spotify {
|
pub struct Spotify {
|
||||||
spotify: ClientCredsSpotify,
|
spotify: ClientCredsSpotify,
|
||||||
|
@ -13,22 +13,25 @@ impl Spotify {
|
||||||
pub async fn new(creds: Credentials) -> anyhow::Result<Self> {
|
pub async fn new(creds: Credentials) -> anyhow::Result<Self> {
|
||||||
let mut spotify = ClientCredsSpotify::new(creds);
|
let mut spotify = ClientCredsSpotify::new(creds);
|
||||||
spotify.request_token().await?;
|
spotify.request_token().await?;
|
||||||
Ok(Self {
|
Ok(Self { spotify })
|
||||||
spotify
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Trigger for Spotify {
|
impl Trigger for Spotify {
|
||||||
async fn execute<'a>(&mut self, msg: Context<'a>, captures: Captures<'a>) -> anyhow::Result<String> {
|
async fn execute<'a>(
|
||||||
|
&mut self,
|
||||||
|
msg: Context<'a>,
|
||||||
|
captures: Captures<'a>,
|
||||||
|
) -> anyhow::Result<String> {
|
||||||
let tp_group = captures.get(1).unwrap();
|
let tp_group = captures.get(1).unwrap();
|
||||||
let id_group = captures.get(2).unwrap();
|
let id_group = captures.get(2).unwrap();
|
||||||
resolve_spotify(
|
resolve_spotify(
|
||||||
&mut self.spotify,
|
&mut self.spotify,
|
||||||
&msg.content.unwrap()[tp_group.start()..tp_group.end()],
|
&msg.content.unwrap()[tp_group.start()..tp_group.end()],
|
||||||
&msg.content.unwrap()[id_group.start()..id_group.end()],
|
&msg.content.unwrap()[id_group.start()..id_group.end()],
|
||||||
).await
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,30 @@
|
||||||
|
use crate::bot::{Context, Trigger};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use fancy_regex::{Captures, Regex};
|
use fancy_regex::{Captures, Regex};
|
||||||
use reqwest::Client;
|
|
||||||
use htmlescape::decode_html;
|
use htmlescape::decode_html;
|
||||||
use crate::bot::{Context, Trigger};
|
use reqwest::Client;
|
||||||
|
|
||||||
pub struct Title {
|
pub struct Title {
|
||||||
http: Client,
|
http: Client,
|
||||||
title_regex: Regex
|
title_regex: Regex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Title {
|
impl Title {
|
||||||
pub fn new() -> anyhow::Result<Self> {
|
pub fn new() -> anyhow::Result<Self> {
|
||||||
Ok(Title {
|
Ok(Title {
|
||||||
http: Client::new(),
|
http: Client::new(),
|
||||||
title_regex: Regex::new(r"(?<=<title>)(.*)(?=</title>)")?
|
title_regex: Regex::new(r"(?<=<title>)(.*)(?=</title>)")?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Trigger for Title {
|
impl Trigger for Title {
|
||||||
async fn execute<'a>(&mut self, _msg: Context<'a>, captures: Captures<'a>) -> anyhow::Result<String> {
|
async fn execute<'a>(
|
||||||
|
&mut self,
|
||||||
|
_msg: Context<'a>,
|
||||||
|
captures: Captures<'a>,
|
||||||
|
) -> anyhow::Result<String> {
|
||||||
let url = captures.get(0).unwrap().as_str();
|
let url = captures.get(0).unwrap().as_str();
|
||||||
tracing::debug!("url: {}", url);
|
tracing::debug!("url: {}", url);
|
||||||
|
|
||||||
|
@ -33,18 +37,19 @@ impl Trigger for Title {
|
||||||
let body = response.text().await?;
|
let body = response.text().await?;
|
||||||
if let Some(tm) = self.title_regex.find(&body)? {
|
if let Some(tm) = self.title_regex.find(&body)? {
|
||||||
let title_match = &body[tm.start()..tm.end()];
|
let title_match = &body[tm.start()..tm.end()];
|
||||||
let result = decode_html(title_match).unwrap_or_else(|_| title_match.to_string());
|
let result =
|
||||||
|
decode_html(title_match).unwrap_or_else(|_| title_match.to_string());
|
||||||
Ok(format!("\x039[Title]\x0311 {}", result))
|
Ok(format!("\x039[Title]\x0311 {}", result))
|
||||||
} else {
|
} else {
|
||||||
Ok("\x039[Title]\x0311 No title".into())
|
Ok("\x039[Title]\x0311 No title".into())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let content_length = response.content_length().map(|l| (l/1024).to_string());
|
let content_length = response.content_length().map(|l| (l / 1024).to_string());
|
||||||
let size = content_length.as_deref().unwrap_or("unknown");
|
let size = content_length.as_deref().unwrap_or("unknown");
|
||||||
Ok(format!("\x039[Title]\x0311 File: {}; {}kb", mime, size))
|
Ok(format!("\x039[Title]\x0311 File: {}; {}kb", mime, size))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok("\x039[Title]\x0311 No Content-Type header".into())
|
Ok("\x039[Title]\x0311 No Content-Type header".into())
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
use crate::bot::{Context, Command};
|
use crate::bot::{Command, Context};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Waifu {
|
pub struct Waifu {
|
||||||
http: Client
|
http: Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Command for Waifu {
|
impl Command for Waifu {
|
||||||
async fn execute(&mut self, msg: Context<'_>) -> anyhow::Result<String> {
|
async fn execute(&mut self, msg: Context<'_>) -> anyhow::Result<String> {
|
||||||
let category = msg.content.unwrap_or("waifu");
|
let category = msg.content.unwrap_or("waifu");
|
||||||
let request = self.http.get(format!("https://api.waifu.pics/sfw/{}", category)).build()?;
|
let request = self
|
||||||
let response = self.http.execute(request)
|
.http
|
||||||
.await?
|
.get(format!("https://api.waifu.pics/sfw/{}", category))
|
||||||
.text()
|
.build()?;
|
||||||
.await?;
|
let response = self.http.execute(request).await?.text().await?;
|
||||||
let response = response.trim();
|
let response = response.trim();
|
||||||
let value: Value = serde_json::from_str(response)?;
|
let value: Value = serde_json::from_str(response)?;
|
||||||
let url = value["url"]
|
let url = value["url"]
|
||||||
|
|
|
@ -7,10 +7,12 @@ use tokio::sync::{
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Task {
|
enum Task {
|
||||||
AddQuote(oneshot::Sender<bool>, Quote),
|
AddQuote(oneshot::Sender<rusqlite::Result<()>>, Quote),
|
||||||
GetQuote(oneshot::Sender<Option<Quote>>, Option<String>),
|
GetQuote(
|
||||||
SearchQuotes(oneshot::Sender<Option<Vec<Quote>>>, String),
|
oneshot::Sender<rusqlite::Result<Option<Quote>>>,
|
||||||
RandomNQuotes(oneshot::Sender<Option<Vec<Quote>>>, u8),
|
Option<String>,
|
||||||
|
),
|
||||||
|
SearchQuotes(oneshot::Sender<rusqlite::Result<Vec<Quote>>>, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DbExecutor {
|
pub struct DbExecutor {
|
||||||
|
@ -40,45 +42,34 @@ impl DbExecutor {
|
||||||
while let Some(task) = self.rx.blocking_recv() {
|
while let Some(task) = self.rx.blocking_recv() {
|
||||||
match task {
|
match task {
|
||||||
Task::AddQuote(tx, quote) => {
|
Task::AddQuote(tx, quote) => {
|
||||||
if let Err(e) = self.db.execute(
|
let result = self
|
||||||
"insert into quotes(quote,username) values(?,?)",
|
.db
|
||||||
params![quote.quote, quote.author],
|
.execute(
|
||||||
) {
|
"insert into quotes(quote,username) values(?,?)",
|
||||||
tracing::error!("A database error has occurred: {}", e);
|
params![quote.quote, quote.author],
|
||||||
tx.send(false).unwrap();
|
)
|
||||||
} else {
|
.map(|_| ());
|
||||||
tx.send(true).unwrap();
|
tx.send(result).unwrap();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Task::GetQuote(tx, author) => {
|
Task::GetQuote(tx, author) => {
|
||||||
let quote = if let Some(ref author) = author {
|
let result = 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(Quote {quote:v.get(0)?, author: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 {
|
} else {
|
||||||
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)?}))
|
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| {
|
}.optional();
|
||||||
tracing::error!("A database error has occurred: {}", e);
|
tx.send(result).unwrap();
|
||||||
None
|
|
||||||
});
|
|
||||||
tx.send(quote).unwrap();
|
|
||||||
}
|
}
|
||||||
Task::SearchQuotes(tx, query) => {
|
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();
|
tx.send(self.yield_quotes("select quote,username from quotes where quote like '%'||?1||'%' order by quote asc limit 5", params![query])).unwrap();
|
||||||
}
|
}
|
||||||
Task::RandomNQuotes(tx, count) => {
|
|
||||||
tx.send(self.yield_quotes(
|
|
||||||
"select quote,username from quotes order by random() limit ?",
|
|
||||||
params![count],
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn yield_quotes<P: Params>(&self, sql: &str, params: P) -> Option<Vec<Quote>> {
|
fn yield_quotes<P: Params>(&self, sql: &str, params: P) -> rusqlite::Result<Vec<Quote>> {
|
||||||
match self.db.prepare(sql).and_then(|mut v| {
|
self.db.prepare(sql).and_then(|mut v| {
|
||||||
v.query(params).and_then(|mut v| {
|
v.query(params).and_then(|mut v| {
|
||||||
let mut quotes: Vec<Quote> = Vec::with_capacity(50);
|
let mut quotes: Vec<Quote> = Vec::new();
|
||||||
while let Some(row) = v.next()? {
|
while let Some(row) = v.next()? {
|
||||||
quotes.push(Quote {
|
quotes.push(Quote {
|
||||||
quote: row.get(0)?,
|
quote: row.get(0)?,
|
||||||
|
@ -87,13 +78,7 @@ impl DbExecutor {
|
||||||
}
|
}
|
||||||
Ok(quotes)
|
Ok(quotes)
|
||||||
})
|
})
|
||||||
}) {
|
})
|
||||||
Ok(o) => Some(o),
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!("A database error has occurred: {}", e);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,23 +113,22 @@ macro_rules! executor_wrapper {
|
||||||
|
|
||||||
impl ExecutorConnection {
|
impl ExecutorConnection {
|
||||||
// WARNING: these methods are NOT cancel-safe
|
// WARNING: these methods are NOT cancel-safe
|
||||||
executor_wrapper!(add_quote, Task::AddQuote, bool, quote: Quote);
|
executor_wrapper!(
|
||||||
|
add_quote,
|
||||||
|
Task::AddQuote,
|
||||||
|
rusqlite::Result<()>,
|
||||||
|
quote: Quote
|
||||||
|
);
|
||||||
executor_wrapper!(
|
executor_wrapper!(
|
||||||
get_quote,
|
get_quote,
|
||||||
Task::GetQuote,
|
Task::GetQuote,
|
||||||
Option<Quote>,
|
rusqlite::Result<Option<Quote>>,
|
||||||
author: Option<String>
|
author: Option<String>
|
||||||
);
|
);
|
||||||
executor_wrapper!(
|
executor_wrapper!(
|
||||||
search_quotes,
|
search_quotes,
|
||||||
Task::SearchQuotes,
|
Task::SearchQuotes,
|
||||||
Option<Vec<Quote>>,
|
rusqlite::Result<Vec<Quote>>,
|
||||||
query: String
|
query: String
|
||||||
);
|
);
|
||||||
executor_wrapper!(
|
|
||||||
random_n_quotes,
|
|
||||||
Task::RandomNQuotes,
|
|
||||||
Option<Vec<Quote>>,
|
|
||||||
count: u8
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue