aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/agenda.rs58
-rw-r--r--src/discord.rs58
-rw-r--r--src/main.rs6
-rw-r--r--src/slack.rs30
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) => {