diff options
| author | Gustav Sörnäs <gustav@sornas.net> | 2020-11-13 00:59:32 +0100 |
|---|---|---|
| committer | Gustav Sörnäs <gustav@sornas.net> | 2020-11-13 01:00:00 +0100 |
| commit | 3b75792081e11cfeb334b45dfb41027532a8848e (patch) | |
| tree | b3c98ccd96a78726bd6f046139613eda44101a3c | |
| parent | 6129d0089aa32a2c9793b736a6ef0480704948cd (diff) | |
| download | kodapa-3b75792081e11cfeb334b45dfb41027532a8848e.tar.gz | |
basic commands and write agenda to file
| -rw-r--r-- | src/agenda.rs | 58 | ||||
| -rw-r--r-- | src/discord.rs | 58 | ||||
| -rw-r--r-- | src/main.rs | 6 | ||||
| -rw-r--r-- | src/slack.rs | 30 |
4 files changed, 106 insertions, 46 deletions
diff --git a/src/agenda.rs b/src/agenda.rs index 3cfcfb7..39b07a7 100644 --- a/src/agenda.rs +++ b/src/agenda.rs @@ -9,8 +9,8 @@ use std::{ #[derive(Debug, Deserialize, Serialize)] pub struct AgendaPoint { - pub title: String, - pub adder: String, + title: String, + adder: String, } impl fmt::Display for AgendaPoint { @@ -30,21 +30,49 @@ pub struct Agenda { points: Vec<AgendaPoint>, } -pub fn read_agenda() -> Agenda { - serde_json::from_str::<Agenda>( - &fs::read_to_string("agenda.json") - .expect("Can't read agenda.json")) - .expect("Error parsing agenda.json") +impl Agenda { + fn write(&self) { + fs::write(std::path::Path::new("agenda.json"), + serde_json::to_string_pretty(&self).expect("Can't serialize agenda")) + .expect("Can't write agenda.json"); + } +} + +pub enum ParseError { + NoSuchCommand, } -pub fn write_agenda(agenda: Agenda) { - fs::write(std::path::Path::new("agenda.json"), - serde_json::to_string_pretty(&agenda).expect("Can't serialize agenda")) - .expect("Can't write agenda.json"); +pub fn parse_message(message: &str, sender: &str) -> Result<Option<String>, ParseError> { + if message.starts_with("!add ") { + let mut agenda = read_agenda(); + agenda.points.push(AgendaPoint { + title: message[5..].to_string(), + adder: sender.to_string(), + }); + agenda.write(); + Ok(None) + } else if message.starts_with("!agenda") { + Ok(Some(read_agenda() + .points + .iter() + .map(|p| p.to_string()) + .collect::<Vec<_>>() + .join("\n"))) + } else if message.starts_with("!clear") { + Agenda { + points: Vec::new(), + }.write(); + Ok(None) + } else if message.starts_with("!help") { + Ok(Some("Available commands:\n !add\n !agenda\n !clear\n !help".to_string())) + } else { + Err(ParseError::NoSuchCommand) + } } -pub fn add_point(point: AgendaPoint) { - let mut agenda = read_agenda(); - agenda.points.push(point); - write_agenda(agenda); +fn read_agenda() -> Agenda { + serde_json::from_str::<Agenda>( + &fs::read_to_string("agenda.json") + .expect("Can't read agenda.json")) + .expect("Error parsing agenda.json") } diff --git a/src/discord.rs b/src/discord.rs index fe64b24..ea7ad03 100644 --- a/src/discord.rs +++ b/src/discord.rs @@ -1,4 +1,7 @@ -use crate::agenda::AgendaPoint; +use crate::agenda::{ + parse_message, + AgendaPoint +}; use discord::{ model::{ @@ -9,6 +12,10 @@ use discord::{ Error, }; use futures::join; +use std::sync::{ + Arc, + Mutex, +}; use tokio::{ sync::mpsc, task::{ @@ -27,16 +34,23 @@ pub async fn handle( println!("Setting up Discord"); let token = std::env::var("DISCORD_API_TOKEN").unwrap_or_else(|_| TOKEN.expect("Missing Discord token").to_string()); + let channel_id = ChannelId( + match std::env::var("DISCORD_CHANNEL") { + Ok(var) => var.parse().unwrap(), + Err(_) => CHANNEL.expect("Missing Discord channel"), + }); + let client = Discord::from_bot_token(&token); if let Ok(client) = client { let (connection, _) = client.connect().expect("Discord connect failed"); //TODO let our_id = client.get_current_user().unwrap().id; + let client = Arc::new(Mutex::new(client)); println!("Discord ready"); let (_, _) = join!( //TODO? - spawn_blocking(move || receive_events(our_id, connection, sender)), - spawn(receive_from_slack(receiver, client)) + spawn(receive_from_slack(receiver, Arc::clone(&client), channel_id)), + spawn_blocking(move || receive_events(our_id, connection, sender, client, channel_id)), ); } } @@ -44,17 +58,25 @@ pub async fn handle( fn receive_events( our_id: discord::model::UserId, mut connection: discord::Connection, - sender: mpsc::UnboundedSender<AgendaPoint> + sender: mpsc::UnboundedSender<AgendaPoint>, + client: Arc<Mutex<discord::Discord>>, + channel_id: ChannelId, ) { loop { match connection.recv_event() { Ok(Event::MessageCreate(message)) => { - if message.author.id != our_id { - sender.send(AgendaPoint{ - title: message.content, - adder: message.author.name, - }).unwrap(); + if let Ok(Some(s)) = parse_message(&message.content, &message.author.name) { + client.lock().unwrap().send_message(channel_id, + &s, + "", + false).unwrap(); } + //if message.author.id != our_id { + // sender.send(AgendaPoint{ + // title: message.content, + // adder: message.author.name, + // }).unwrap(); + //} } Ok(_) => {} Err(Error::Closed(code, body)) => { @@ -70,21 +92,15 @@ fn receive_events( async fn receive_from_slack( mut receiver: mpsc::UnboundedReceiver<AgendaPoint>, - client: discord::Discord, + client: Arc<Mutex<discord::Discord>>, + channel_id: ChannelId ) { while let Some(point) = receiver.recv().await { println!("Discord received '{}'", point); - client.send_message( - ChannelId( - match std::env::var("DISCORD_CHANNEL") { - Ok(var) => var.parse().unwrap(), - Err(_) => CHANNEL.expect("Missing Discord channel"), - } - ), - &point.to_add_message(), - "", - false - ).unwrap(); + client.lock().unwrap().send_message(channel_id, + &point.to_add_message(), + "", + false).unwrap(); } } diff --git a/src/main.rs b/src/main.rs index d3a24f3..b6edd38 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,10 @@ mod agenda; mod discord; mod slack; -use crate::agenda::AgendaPoint; - +use crate::agenda::{ + Agenda, + AgendaPoint, +}; use futures::join; use tokio::sync::mpsc; diff --git a/src/slack.rs b/src/slack.rs index b460925..c0d9bb8 100644 --- a/src/slack.rs +++ b/src/slack.rs @@ -1,4 +1,7 @@ -use crate::agenda::AgendaPoint; +use crate::agenda::{ + parse_message, + AgendaPoint +}; use futures::join; use slack::{ @@ -18,12 +21,20 @@ const CHANNEL: Option<&str> = None; struct Handler { sender: mpsc::UnboundedSender<AgendaPoint>, + slack_sender: slack::Sender, + slack_channel: String, } impl Handler { - fn new(sender: mpsc::UnboundedSender<AgendaPoint>) -> Self { + fn new( + sender: mpsc::UnboundedSender<AgendaPoint>, + slack_sender: slack::Sender, + slack_channel: String + ) -> Self { Self { - sender + sender, + slack_sender, + slack_channel, } } @@ -39,10 +50,12 @@ impl slack::EventHandler for Handler { Event::Message(msg) => { match *msg { Message::Standard(msg) => { - self.sender().send(AgendaPoint{ - title: msg.text.unwrap_or("??".to_string()), - adder: msg.user.unwrap_or("??".to_string()), - }).unwrap(); + if let Ok(Some(s)) = parse_message( + &msg.text.unwrap_or("".to_string()), + &msg.user.unwrap_or("??".to_string()), + ) { + self.slack_sender.send_message(self.slack_channel.as_str(), &s).unwrap(); + } } _ => {} } @@ -67,15 +80,16 @@ pub async fn handle( println!("Setting up Slack"); let token = std::env::var("SLACK_API_TOKEN").unwrap_or_else(|_| TOKEN.expect("Missing slack token").to_string()); + let token_clone = token.clone(); let client = spawn_blocking(move || { slack::RtmClient::login(&token).unwrap() }).await.unwrap(); + let mut handler = Handler::new(sender, client.sender().clone(), token_clone); let slack_sender = client.sender().clone(); let (_, _) = join!( spawn_blocking(move || { - let mut handler = Handler::new(sender); match client.run(&mut handler) { Ok(_) => {} Err(e) => { |
