diff --git a/irc-stream b/irc-stream
index bf53e62..ef1e849 160000
--- a/irc-stream
+++ b/irc-stream
@@ -1 +1 @@
-Subproject commit bf53e62f1713dfe83198f75992cc0e889de398ff
+Subproject commit ef1e849d0ea7e6472a3fad86ea859a00597d27ea
diff --git a/src/connect.rs b/src/connect.rs
new file mode 100644
index 0000000..9d8f12c
--- /dev/null
+++ b/src/connect.rs
@@ -0,0 +1,64 @@
+/* Copyright 2021 Daniel Mowitz
+ * This file is part of Mention2Mail.
+ *
+ * Mention2Mail is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mention2Mail is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Mention2Mail. If not, see .
+ */
+
+use std::{
+ format,
+ net::TcpStream,
+};
+use irc_stream::{IrcStream, IrcRead, IrcWrite};
+use toml::value::Value;
+use native_tls::{TlsConnector,TlsStream};
+
+// Weird workaround for multitrait dyn pointer
+// https://github.com/rust-lang/rfcs/issues/2035
+// would be a charm...
+pub trait IrcReadWrite: IrcRead + IrcWrite {}
+impl IrcReadWrite for T {}
+
+fn get_tcp_stream (config: &Value)
+ -> Result> {
+ let address = format!("{}:{}",
+ config.get("server").unwrap().as_str()
+ .ok_or("Could not get server adress from config")?,
+ config.get("port").unwrap().as_str()
+ .ok_or("Could not get port from config")?
+ );
+ println!("Connectiing to: {}", address);
+ Ok(TcpStream::connect(address)?)
+}
+
+fn get_tls_stream (config: &Value)
+ -> Result, Box> {
+ let connector = TlsConnector::new().unwrap();
+ let stream = get_tcp_stream(config)?;
+ Ok(connector.connect(config["server"]
+ .as_str()
+ .ok_or("Could not get server adress from config")?,
+ stream)?
+ )
+}
+
+pub fn connect_irc (config: &Value)
+ -> Result, Box> {
+
+ if *config["tls"].as_bool().get_or_insert(true) == true {
+ return Ok(Box::new(IrcStream::new(get_tls_stream(&config)?)))
+ } else {
+ return Ok(Box::new(IrcStream::new(get_tcp_stream(&config)?)))
+ }
+}
+
diff --git a/src/main.rs b/src/main.rs
index a913402..ec283bc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -15,12 +15,13 @@
* along with Mention2Mail. If not, see .
*/
+pub mod connect;
+
use std::{
format,
env::args,
path::Path,
io::Read,
- net::TcpStream,
collections::VecDeque,
};
use irc_proto::command::{
@@ -28,9 +29,11 @@ use irc_proto::command::{
Command,
};
use irc_proto::message::Message;
-use irc_stream::{IrcStream, IrcRead, IrcWrite};
+use irc_stream::{
+ IrcRead,
+ IrcWrite,
+};
use toml::value::Value;
-use native_tls::{TlsConnector,TlsStream};
trait IrcReadWrite: IrcRead + IrcWrite {}
impl IrcReadWrite for T {}
@@ -65,29 +68,6 @@ fn get_config>(config_path: P)
Ok(Value::from(config))
}
-fn get_tcp_stream (config: &Value)
- -> Result> {
- let address = format!("{}:{}",
- config.get("server").unwrap().as_str()
- .ok_or("Could not get server adress from config")?,
- config.get("port").unwrap().as_str()
- .ok_or("Could not get port from config")?
- );
- println!("Connectiing to: {}", address);
- Ok(TcpStream::connect(address)?)
-}
-
-fn get_tls_stream (config: &Value)
- -> Result, Box> {
- let connector = TlsConnector::new().unwrap();
- let stream = get_tcp_stream(config)?;
- Ok(connector.connect(config["server"]
- .as_str()
- .ok_or("Could not get server adress from config")?,
- stream)?
- )
-}
-
fn get_irc_identify_messages (config: &Value)
-> Result, Box> {
let mut queue = VecDeque::new();
@@ -135,30 +115,93 @@ fn get_irc_identify_messages (config: &Value)
Ok(queue)
}
+fn get_irc_join_messages(config: &Value, queue: VecDeque)
+ -> Result, Box> {
+ let mut queue = queue;
+
+ match config.get("channels") {
+ Some(c) => {
+ for channel in c.as_array().ok_or("Could not parse channels.")? {
+ queue.push_back(Message::from(
+ Command::JOIN(
+ String::from(channel.as_str().ok_or("Could not parse one of the channels")?),
+ None,
+ None
+ )
+ ))
+ }
+ },
+ None => ()
+ }
+
+ Ok(queue)
+}
+
+fn handle_message(message: Message) -> Option {
+ let sender = match message.clone().source_nickname() {
+ Some(s) => String::from(s),
+ None => String::from("anonymous")
+ };
+ match message.clone().command {
+ Command::PING(ref data, _) => {
+ return Some(Message::from(
+ Command::PONG(data.to_owned(), None)
+ ));
+ },
+ Command::PRIVMSG(ref rec, ref msg) => println!(
+ "{} -> {}: {}",
+ rec,
+ msg,
+ sender
+ ),
+ _ => println!("{}", message.clone().to_string())
+ }
+ return None
+}
+
fn main() {
let config_path = args().nth(1)
.expect("no config given");
let config = get_config(config_path).expect("Could not get config");
- // Weird workaround for multitrait dyn pointer
- // https://github.com/rust-lang/rfcs/issues/2035
- // would be a charm...
-
- let mut stream: Box;
-
- if config["tls"].as_bool().unwrap() == true {
- stream = Box::new(IrcStream::new(get_tls_stream(&config).unwrap()));
- } else {
- stream = Box::new(IrcStream::new(get_tcp_stream(&config).unwrap()));
- }
+ let mut stream = connect::connect_irc(&config).unwrap();
let mut message_queue = get_irc_identify_messages(&config).unwrap();
-
+
while let Some(message) = message_queue.pop_front() {
stream.write(message).unwrap();
}
- stream.flush().unwrap();
+ message_queue = get_irc_join_messages(&config, message_queue).unwrap();
+
+ // Wait for first ping and join channels after sending pong.
+ // TODO this approach is not very DRY!
+ loop {
+ let message = match stream.read() {
+ Ok(m) => m,
+ Err(e) => Message::from(
+ Command::PRIVMSG(
+ String::from("Error"),
+ format!("{}", e)
+ )
+ )
+ };
+ match message.command {
+ Command::PING(ref data, _) => {
+ stream.write(Message::from(
+ Command::PONG(data.to_owned(), None)
+ )).unwrap();
+ while let Some(message) = message_queue.pop_front() {
+ stream.write(message).unwrap();
+ }
+ break;
+ }
+ _ => match handle_message(message) {
+ Some(m) => stream.write(m).unwrap(),
+ None => ()
+ }
+ }
+ }
loop {
let message = match stream.read() {
@@ -170,23 +213,9 @@ fn main() {
)
)
};
- let sender = match message.clone().source_nickname() {
- Some(s) => String::from(s),
- None => String::from("anonymous")
- };
- match message.clone().command {
- Command::PING(ref data, _) => {
- stream.write(Message::from(
- Command::PONG(data.to_owned(), None)
- )).unwrap();
- },
- Command::PRIVMSG(ref rec, ref msg) => println!(
- "{} -> {}: {}",
- rec,
- msg,
- sender
- ),
- _ => println!("Other message: {}", message.clone().to_string())
+ match handle_message(message) {
+ Some(m) => stream.write(m).unwrap(),
+ None => ()
}
}
}