diff --git a/ßqa b/ßqa deleted file mode 100644 index 56be040..0000000 --- a/ßqa +++ /dev/null @@ -1,263 +0,0 @@ -/* 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::{ - collections::VecDeque, - collections::HashMap, - sync::mpsc::Sender, -}; -use irc_proto::command::{ - CapSubCommand, - Command, -}; -use toml::map::{ - Map, - Keys -}; -use irc_proto::message::Message; -use toml::value::Value; - -struct MessageRingBuf { - buf: [Option<[String; 3]>; SIZE], - ptr: usize, -} - -impl MessageRingBuf { - pub fn new() -> Self { - Self{ - buf: [None; SIZE], - ptr: 0 - } - } - - pub fn push(&mut self, val: [String; 3]) { - self.ptr = (self.ptr + 1) % SIZE; - self.buf[self.ptr] = Some(val); - } - - pub fn pop(&mut self) -> Option<[String; 3]> { - self.buf[self.ptr].take() - } - - pub fn get_queue(& self) -> [Option; SIZE] { - let mut queue = self.buf.clone(); - - for i in self.ptr .. SIZE { - queue[i - self.ptr] = self.buf[i]; - } - - for i in 0 .. self.ptr { - queue[SIZE - self.ptr + i] = self.buf[i]; - } - - return queue - } -} - -/// Constructs a VecDeque with the messages -/// required to identify with an IRC server. -/// Uses the credentials set in -`config.toml`. -fn get_irc_identify_messages (config: &Value) - -> Result, Box> { - let mut queue = VecDeque::new(); - - queue.push_back(Message::from( - Command::CAP( - None, - CapSubCommand::END, - None, - None - ))); - - match config.get("password") { - Some(p) => queue.push_back(Message::from( - Command::PASS( - String::from(p.as_str().ok_or("Could not parse password.")?) - ) - )), - None => () - } - - let nick: String; - match config.get("nickname") { - Some(n) => { - nick = String::from(n.as_str().ok_or("Could not parse nickname.")?); - queue.push_back(Message::from(Command::NICK(nick.clone()))); - }, - None => return Err("No nickname supplied!".into()), - } - - match config.get("username") { - Some(u) => queue.push_back(Message::from( - Command::USER( - String::from(u.as_str().ok_or("Could not parse username.")?), - "0".to_owned(), - String::from(u.as_str().ok_or("Could not parse username.")?) - ) - )), - None => queue.push_back(Message::from( - // nick.clone() is only used once because the value - // can be moved the second time - Command::USER(nick.clone(), "0".to_owned(), nick) - )) - } - Ok(queue) -} - -/// Appends a given VecDeque to include the messages -/// used to join the channels defined in `config.toml`. -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, nick: &String, - client_names: Keys, contexts: HashMap>) - -> (Option, Option<[String; 4]>) { - 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) - )), - None - ); - }, - Command::PRIVMSG(ref rec, ref msg) => { - // Send bot info on receiving a private message. - if rec.as_str() == nick.as_str() { - return ( - Some(Message::from( - Command::PRIVMSG( - sender.clone(), - super::texts::get_bot_info(), - ) - ) - ), - None - ) - } else { - match contexts.get_mut(sender.clone()) { - Some(ref buf) => buf.push( - for c_name in client_names { - if msg.contains(c_name) { - return (None, Some([c_name.clone(), - rec.clone(), - sender.clone(), - msg.clone() - ])) - } - } - } - }, - _ => println!("{}", message.clone().to_string()) - } - return (None, None) -} - -pub fn handle_server(config: Value, tx: Sender<[String; 5]>) - -> Result<(), Box> { - let server_name = config.get("server").unwrap().as_str() - .ok_or("Could not get server adress from config")?; - let nick = config.get("nickname").unwrap().as_str() - .ok_or("Could not get nickname from config")?.to_owned(); - - let clients; - match config.get("clients").unwrap().as_table() { - Some(t) => clients = t.clone(), - None => clients = Map::new(), - } - - let mut chat_context = HashMap::new(); - - let mut stream = super::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(); - } - - message_queue = get_irc_join_messages(&config, message_queue).unwrap(); - - // Wait for first ping and join channels after sending pong. - loop { - let message = stream.read()?; - 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; - } - _ => () - } - } - - // Handle all incoming messages after joining the channels. - loop { - let message = stream.read()?; - let (answer, data) = handle_message(message, &nick, clients.keys()); - match answer { - Some(a) => stream.write(a).unwrap(), - None => () - } - match data { - Some(d) => match clients.get(&d[0]) { - Some(addr) => { - // There must be a better way to do this… - let out = [ - addr.as_str() - .ok_or("Could not parse email address.")? - .to_owned(), - server_name.to_owned(), - d[1].clone(), - d[2].clone(), - d[3].clone(), - ]; - tx.send(out)? - }, - None => (), - }, - None => (), - } - } -} -