Implement quotes
This commit is contained in:
parent
3eaaeb1244
commit
25a7635408
47
src/bot.rs
47
src/bot.rs
|
@ -1,11 +1,12 @@
|
||||||
|
use crate::history::MessageHistory;
|
||||||
use crate::ExecutorConnection;
|
use crate::ExecutorConnection;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use fancy_regex::{Captures, Regex};
|
use fancy_regex::{Captures, Regex};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tokio::sync::{Mutex, RwLock};
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
fn dissect<'a>(prefix: &str, str: &'a str) -> Option<(&'a str, Option<&'a str>)> {
|
fn dissect<'a>(prefix: &str, str: &'a str) -> Option<(&'a str, Option<&'a str>)> {
|
||||||
let str = str.strip_prefix(prefix)?;
|
let str = str.trim().strip_prefix(prefix)?;
|
||||||
if let Some(o) = str.find(' ') {
|
if let Some(o) = str.find(' ') {
|
||||||
Some((&str[..o], Some(&str[o + 1..])))
|
Some((&str[..o], Some(&str[o + 1..])))
|
||||||
} else {
|
} else {
|
||||||
|
@ -15,7 +16,11 @@ fn dissect<'a>(prefix: &str, str: &'a str) -> Option<(&'a str, Option<&'a str>)>
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Trigger {
|
pub trait Trigger {
|
||||||
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>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -24,15 +29,15 @@ pub trait Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
pub last_msg: &'a RwLock<HashMap<String, String>>,
|
pub history: &'a MessageHistory,
|
||||||
pub author: &'a str,
|
pub author: &'a str,
|
||||||
// in case of triggers, this is always Some(...)
|
// in case of triggers, this is always Some(...)
|
||||||
pub content: Option<&'a str>,
|
pub content: Option<&'a str>,
|
||||||
pub db: &'a ExecutorConnection
|
pub db: &'a ExecutorConnection,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Bot<SF: Fn(String, String) -> anyhow::Result<()>> {
|
pub struct Bot<SF: Fn(String, String) -> anyhow::Result<()>> {
|
||||||
last_msg: RwLock<HashMap<String, String>>,
|
history: MessageHistory,
|
||||||
prefix: String,
|
prefix: String,
|
||||||
db: ExecutorConnection,
|
db: ExecutorConnection,
|
||||||
commands: HashMap<String, Box<Mutex<dyn Command + Send>>>,
|
commands: HashMap<String, Box<Mutex<dyn Command + Send>>>,
|
||||||
|
@ -41,9 +46,9 @@ pub struct Bot<SF: Fn(String, String) -> anyhow::Result<()>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SF: Fn(String, String) -> anyhow::Result<()>> Bot<SF> {
|
impl<SF: Fn(String, String) -> anyhow::Result<()>> Bot<SF> {
|
||||||
pub fn new(prefix: String, db: ExecutorConnection, sendmsg: SF) -> Self {
|
pub fn new(prefix: String, db: ExecutorConnection, hdepth: usize, sendmsg: SF) -> Self {
|
||||||
Bot {
|
Bot {
|
||||||
last_msg: RwLock::new(HashMap::new()),
|
history: MessageHistory::new(hdepth),
|
||||||
commands: HashMap::new(),
|
commands: HashMap::new(),
|
||||||
triggers: Vec::new(),
|
triggers: Vec::new(),
|
||||||
prefix,
|
prefix,
|
||||||
|
@ -69,38 +74,36 @@ impl<SF: Fn(String, String) -> anyhow::Result<()>> Bot<SF> {
|
||||||
if let Some((command, remainder)) = dissect(&self.prefix, content) {
|
if let Some((command, remainder)) = dissect(&self.prefix, content) {
|
||||||
if let Some(handler) = self.commands.get(command) {
|
if let Some(handler) = self.commands.get(command) {
|
||||||
let msg = Context {
|
let msg = Context {
|
||||||
last_msg: &self.last_msg,
|
|
||||||
author,
|
author,
|
||||||
content: remainder,
|
content: remainder,
|
||||||
db: &self.db
|
db: &self.db,
|
||||||
|
history: &self.history,
|
||||||
};
|
};
|
||||||
return (self.sendmsg)(origin.into(), handler.lock().await.execute(msg).await?)
|
return (self.sendmsg)(origin.into(), handler.lock().await.execute(msg).await?);
|
||||||
}
|
}
|
||||||
return (self.sendmsg)(origin.into(), "Unknown command.".into())
|
return (self.sendmsg)(origin.into(), "Unknown command.".into());
|
||||||
} else {
|
} else {
|
||||||
for trigger in &self.triggers {
|
for trigger in &self.triggers {
|
||||||
let captures = trigger.0.captures(content)?;
|
let captures = trigger.0.captures(content)?;
|
||||||
if let Some(captures) = captures {
|
if let Some(captures) = captures {
|
||||||
let msg = Context {
|
let msg = Context {
|
||||||
last_msg: &self.last_msg,
|
|
||||||
author,
|
author,
|
||||||
content: Some(content),
|
content: Some(content),
|
||||||
db: &self.db
|
db: &self.db,
|
||||||
|
history: &self.history,
|
||||||
};
|
};
|
||||||
return (self.sendmsg)(origin.into(), trigger.1.lock().await.execute(msg, captures).await?)
|
return (self.sendmsg)(
|
||||||
|
origin.into(),
|
||||||
|
trigger.1.lock().await.execute(msg, captures).await?,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.last_msg.write().await.insert(author.to_string(), content.to_string());
|
self.history.add_message(author, content).await;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_message(
|
pub async fn handle_message(&self, origin: &str, author: &str, content: &str) {
|
||||||
&self,
|
|
||||||
origin: &str,
|
|
||||||
author: &str,
|
|
||||||
content: &str,
|
|
||||||
) {
|
|
||||||
if let Err(e) = self.handle_message_inner(origin, author, content).await {
|
if let Err(e) = self.handle_message_inner(origin, author, content).await {
|
||||||
let _ = (self.sendmsg)(origin.into(), format!("Error: {}", e));
|
let _ = (self.sendmsg)(origin.into(), format!("Error: {}", e));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use crate::bot::{Command, Context};
|
use crate::bot::{Command, Context};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Eval {
|
pub struct Eval {
|
||||||
last_eval: HashMap<String, f64>
|
last_eval: HashMap<String, f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::bot::{Context, Command};
|
use crate::bot::{Command, Context};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
const HELP: &str = concat!(
|
const HELP: &str = concat!(
|
||||||
|
|
|
@ -113,11 +113,11 @@ enum LeekCommand {
|
||||||
|
|
||||||
async fn execute_leek(cmd: LeekCommand, msg: &Context<'_>) -> anyhow::Result<String> {
|
async fn execute_leek(cmd: LeekCommand, msg: &Context<'_>) -> anyhow::Result<String> {
|
||||||
let nick = msg.content.unwrap_or(msg.author);
|
let nick = msg.content.unwrap_or(msg.author);
|
||||||
match msg.last_msg.read().await.get(nick) {
|
match msg.history.last_msg(nick).await {
|
||||||
Some(msg) => Ok(match cmd {
|
Some(msg) => Ok(match cmd {
|
||||||
LeekCommand::Owo => owoify(msg)?,
|
LeekCommand::Owo => owoify(&msg)?,
|
||||||
LeekCommand::Leet => leetify(msg),
|
LeekCommand::Leet => leetify(&msg),
|
||||||
LeekCommand::Mock => mock(msg),
|
LeekCommand::Mock => mock(&msg),
|
||||||
}
|
}
|
||||||
.to_string()),
|
.to_string()),
|
||||||
None => Ok("No previous messages found.".into()),
|
None => Ok("No previous messages found.".into()),
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
pub mod debug;
|
pub mod debug;
|
||||||
|
|
||||||
|
pub mod eval;
|
||||||
pub mod help;
|
pub mod help;
|
||||||
pub mod leek;
|
pub mod leek;
|
||||||
pub mod waifu;
|
pub mod quotes;
|
||||||
pub mod sed;
|
pub mod sed;
|
||||||
pub mod eval;
|
|
||||||
pub mod spotify;
|
pub mod spotify;
|
||||||
pub mod title;
|
pub mod title;
|
||||||
|
pub mod waifu;
|
||||||
|
|
58
src/commands/quotes.rs
Normal file
58
src/commands/quotes.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use crate::bot::{Command, Context};
|
||||||
|
use crate::database::Quote;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
pub struct Grab;
|
||||||
|
pub struct Quot;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Command for Grab {
|
||||||
|
async fn execute(&mut self, msg: Context<'_>) -> anyhow::Result<String> {
|
||||||
|
let content = if let Some(c) = msg.content {
|
||||||
|
c
|
||||||
|
} else {
|
||||||
|
return Ok("Invalid usage.".into());
|
||||||
|
};
|
||||||
|
let mut split = content.splitn(2, ' ');
|
||||||
|
let split = (split.next().unwrap(), split.next());
|
||||||
|
let (author, count) = if let Some(author) = split.1 {
|
||||||
|
(author, split.0.parse::<usize>()?)
|
||||||
|
} else {
|
||||||
|
(split.0, 1)
|
||||||
|
};
|
||||||
|
if count == 0 {
|
||||||
|
return Ok("So are you going to grab anything?".into());
|
||||||
|
}
|
||||||
|
if author == msg.author {
|
||||||
|
return Ok("You can't grab yourself.".into());
|
||||||
|
}
|
||||||
|
let message = msg
|
||||||
|
.history
|
||||||
|
.last_msgs(author, count)
|
||||||
|
.await
|
||||||
|
.map(|v| v.join(" | "));
|
||||||
|
if let Some(message) = message {
|
||||||
|
msg.db
|
||||||
|
.add_quote(Quote {
|
||||||
|
author: author.into(),
|
||||||
|
quote: message,
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
Ok("Quote added ({} messages).".into())
|
||||||
|
} else {
|
||||||
|
Ok("No previous messages to grab.".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Command for Quot {
|
||||||
|
async fn execute(&mut self, msg: Context<'_>) -> anyhow::Result<String> {
|
||||||
|
let author = msg.content.map(ToString::to_string);
|
||||||
|
if let Some(q) = msg.db.get_quote(author).await? {
|
||||||
|
Ok(format!("\"{}\" ~{}", q.quote, q.author))
|
||||||
|
} else {
|
||||||
|
Ok("No quotes found from this user.".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,16 @@
|
||||||
|
use crate::bot::{Context, Trigger};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use fancy_regex::Captures;
|
use fancy_regex::Captures;
|
||||||
use crate::bot::{Context, Trigger};
|
|
||||||
|
|
||||||
pub struct Sed;
|
pub struct Sed;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Trigger for Sed {
|
impl Trigger for Sed {
|
||||||
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 foreign_author;
|
let foreign_author;
|
||||||
let author = if let Some(author) = captures.name("u").map(|m| m.as_str()) {
|
let author = if let Some(author) = captures.name("u").map(|m| m.as_str()) {
|
||||||
foreign_author = true;
|
foreign_author = true;
|
||||||
|
@ -15,8 +19,7 @@ impl Trigger for Sed {
|
||||||
foreign_author = false;
|
foreign_author = false;
|
||||||
msg.author
|
msg.author
|
||||||
};
|
};
|
||||||
let lastmsg = msg.last_msg.read().await;
|
let message = if let Some(msg) = msg.history.last_msg(author).await {
|
||||||
let message = if let Some(msg) = lastmsg.get(author) {
|
|
||||||
msg
|
msg
|
||||||
} else {
|
} else {
|
||||||
return Ok("No previous messages found.".into());
|
return Ok("No previous messages found.".into());
|
||||||
|
@ -25,11 +28,15 @@ impl Trigger for Sed {
|
||||||
// TODO: karx plz add flags
|
// TODO: karx plz add flags
|
||||||
//let flags = matches.name("f").map(|m| m.as_str());
|
//let flags = matches.name("f").map(|m| m.as_str());
|
||||||
let result = message.replace(find.as_str(), replace.as_str());
|
let result = message.replace(find.as_str(), replace.as_str());
|
||||||
drop(lastmsg);
|
|
||||||
if foreign_author {
|
if foreign_author {
|
||||||
Ok(format!("(edited by {}) <{}> {}", msg.author, author, result))
|
Ok(format!(
|
||||||
|
"(edited by {}) <{}> {}",
|
||||||
|
msg.author, author, result
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
msg.last_msg.write().await.insert(author.into(), result.to_string());
|
msg.history
|
||||||
|
.edit_message(author, 0, result.to_string())
|
||||||
|
.await;
|
||||||
Ok(format!("<{}> {}", author, result))
|
Ok(format!("<{}> {}", author, result))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,24 +1,19 @@
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use anyhow::anyhow;
|
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
pub struct MessageHistory {
|
pub struct MessageHistory {
|
||||||
map: RwLock<HashMap<String, VecDeque<String>>>,
|
map: RwLock<HashMap<String, VecDeque<String>>>,
|
||||||
maxlen: usize
|
maxlen: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageHistory {
|
impl MessageHistory {
|
||||||
pub fn new(maxlen: usize) -> MessageHistory {
|
pub fn new(maxlen: usize) -> MessageHistory {
|
||||||
MessageHistory {
|
MessageHistory {
|
||||||
map: RwLock::new(HashMap::new()),
|
map: RwLock::new(HashMap::new()),
|
||||||
maxlen
|
maxlen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_len(&self) -> usize {
|
|
||||||
self.maxlen
|
|
||||||
}
|
|
||||||
|
|
||||||
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(|s| s.to_string())
|
map.get(user).and_then(|d| d.get(0)).map(|s| s.to_string())
|
||||||
|
@ -27,18 +22,39 @@ impl MessageHistory {
|
||||||
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>> {
|
||||||
let map = self.map.read().await;
|
let map = self.map.read().await;
|
||||||
if let Some(deque) = map.get(user) {
|
if let Some(deque) = map.get(user) {
|
||||||
let count = if deque.len() < count { deque.len() } else {count};
|
let count = if deque.len() < count {
|
||||||
Some(deque.range(..count).rev().map(ToString::to_string).collect())
|
deque.len()
|
||||||
|
} else {
|
||||||
|
count
|
||||||
|
};
|
||||||
|
Some(
|
||||||
|
deque
|
||||||
|
.range(..count)
|
||||||
|
.rev()
|
||||||
|
.map(ToString::to_string)
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn edit_message(&self, user: &str, pos: usize, edited: String) -> bool {
|
||||||
|
let mut map = self.map.write().await;
|
||||||
|
if let Some(deque) = map.get_mut(user) {
|
||||||
|
if let Some(old) = deque.get_mut(pos) {
|
||||||
|
*old = edited;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn add_message(&self, user: &str, message: &str) {
|
pub async fn add_message(&self, user: &str, message: &str) {
|
||||||
let mut map = self.map.write().await;
|
let mut map = self.map.write().await;
|
||||||
if let Some(deque) = map.get_mut(user) {
|
if let Some(deque) = map.get_mut(user) {
|
||||||
if deque.len() == self.maxlen {
|
if deque.len() == self.maxlen {
|
||||||
deque.remove(deque.len()-1);
|
deque.remove(deque.len() - 1);
|
||||||
}
|
}
|
||||||
deque.push_front(message.to_string());
|
deque.push_front(message.to_string());
|
||||||
} else {
|
} else {
|
||||||
|
@ -47,4 +63,4 @@ impl MessageHistory {
|
||||||
map.insert(user.to_string(), deque);
|
map.insert(user.to_string(), deque);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
27
src/main.rs
27
src/main.rs
|
@ -1,11 +1,18 @@
|
||||||
|
use fancy_regex::Regex;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use fancy_regex::Regex;
|
|
||||||
|
|
||||||
use crate::bot::Bot;
|
use crate::bot::Bot;
|
||||||
|
use crate::commands::eval::Eval;
|
||||||
|
use crate::commands::help::Help;
|
||||||
|
use crate::commands::leek::Owo;
|
||||||
|
use crate::commands::quotes::{Grab, Quot};
|
||||||
|
use crate::commands::sed::Sed;
|
||||||
|
use crate::commands::spotify::Spotify;
|
||||||
|
use crate::commands::title::Title;
|
||||||
use crate::commands::waifu::Waifu;
|
use crate::commands::waifu::Waifu;
|
||||||
use futures_util::stream::StreamExt;
|
use futures_util::stream::StreamExt;
|
||||||
use irc::client::prelude::Config;
|
use irc::client::prelude::Config;
|
||||||
|
@ -16,12 +23,6 @@ use tokio::select;
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
use tokio::sync::mpsc::unbounded_channel;
|
use tokio::sync::mpsc::unbounded_channel;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
use crate::commands::eval::Eval;
|
|
||||||
use crate::commands::help::Help;
|
|
||||||
use crate::commands::leek::Owo;
|
|
||||||
use crate::commands::sed::Sed;
|
|
||||||
use crate::commands::spotify::Spotify;
|
|
||||||
use crate::commands::title::Title;
|
|
||||||
|
|
||||||
use crate::config::UberConfig;
|
use crate::config::UberConfig;
|
||||||
use crate::database::{DbExecutor, ExecutorConnection};
|
use crate::database::{DbExecutor, ExecutorConnection};
|
||||||
|
@ -30,6 +31,7 @@ mod bot;
|
||||||
mod commands;
|
mod commands;
|
||||||
mod config;
|
mod config;
|
||||||
mod database;
|
mod database;
|
||||||
|
mod history;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
async fn terminate_signal() {
|
async fn terminate_signal() {
|
||||||
|
@ -89,7 +91,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
let (ctx, _) = broadcast::channel(1);
|
let (ctx, _) = broadcast::channel(1);
|
||||||
let (etx, mut erx) = unbounded_channel();
|
let (etx, mut erx) = unbounded_channel();
|
||||||
|
|
||||||
let mut bot = Bot::new(cfg.irc.prefix, db_conn, {
|
let mut bot = Bot::new(cfg.irc.prefix, db_conn, 3, {
|
||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
move |target, msg| Ok(client.send_privmsg(target, msg)?)
|
move |target, msg| Ok(client.send_privmsg(target, msg)?)
|
||||||
});
|
});
|
||||||
|
@ -98,7 +100,12 @@ async fn main() -> anyhow::Result<()> {
|
||||||
bot.add_command("waifu".into(), Waifu::default());
|
bot.add_command("waifu".into(), Waifu::default());
|
||||||
bot.add_command("owo".into(), Owo);
|
bot.add_command("owo".into(), Owo);
|
||||||
bot.add_command("ev".into(), Eval::default());
|
bot.add_command("ev".into(), Eval::default());
|
||||||
bot.add_trigger(Regex::new(r"^(?:(?<u>\S+):\s+)?s/(?<r>[^/]*)/(?<w>[^/]*)(?:/(?<f>[a-z]*))?\s*")?, Sed);
|
bot.add_command("grab".into(), Grab);
|
||||||
|
bot.add_command("quot".into(), Quot);
|
||||||
|
bot.add_trigger(
|
||||||
|
Regex::new(r"^(?:(?<u>\S+):\s+)?s/(?<r>[^/]*)/(?<w>[^/]*)(?:/(?<f>[a-z]*))?\s*")?,
|
||||||
|
Sed,
|
||||||
|
);
|
||||||
if let Some(spotcfg) = cfg.spotify {
|
if let Some(spotcfg) = cfg.spotify {
|
||||||
let creds = Credentials::new(&spotcfg.client_id, &spotcfg.client_secret);
|
let creds = Credentials::new(&spotcfg.client_id, &spotcfg.client_secret);
|
||||||
let spotify = Spotify::new(creds).await?;
|
let spotify = Spotify::new(creds).await?;
|
||||||
|
@ -150,7 +157,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
async fn message_loop<SF: Fn(String, String) -> anyhow::Result<()>>(
|
async fn message_loop<SF: Fn(String, String) -> anyhow::Result<()>>(
|
||||||
mut stream: ClientStream,
|
mut stream: ClientStream,
|
||||||
bot: Bot<SF>
|
bot: Bot<SF>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
while let Some(message) = stream.next().await.transpose()? {
|
while let Some(message) = stream.next().await.transpose()? {
|
||||||
if let Command::PRIVMSG(ref origin, content) = message.command {
|
if let Command::PRIVMSG(ref origin, content) = message.command {
|
||||||
|
|
Loading…
Reference in a new issue