use crate::helpers::bytes_to_privmsg_base64;
use crate::{encryption, helpers, State};
use eyre::Result;
use pgp::{Deserializable, SignedPublicKey};
use std::collections::HashMap;
use std::sync::mpsc::{Receiver, Sender};
#[derive(Debug)]
struct InvalidCommand;
impl std::fmt::Display for InvalidCommand {
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Ok(())
}
}
impl std::error::Error for InvalidCommand {}
fn parse_bouncer_command(message: String, state: &mut State) -> Result<()> {
macro_rules! unwrap_option {
($t:expr) => {
match $t {
Some(val) => val,
None => return Err(InvalidCommand.into()),
}
};
}
let mut splitted = message.split(' ');
match unwrap_option!(splitted.next()) {
"ALLOW_UNENCRYPTED" => state
.nicks_without_encryption
.push(unwrap_option!(splitted.next()).to_string().to_lowercase()),
_ => return Err(InvalidCommand.into()),
};
Ok(())
}
pub fn handle_message_from_client(
recieved: &str,
public_key: &Vec<u8>,
server: &str,
keys: &mut HashMap<String, SignedPublicKey>,
writer_channel_tx: &Sender<String>,
writer_channel_rx: &Receiver<String>,
listener_channel_tx: &Sender<String>,
_listener_channel_rx: &Receiver<String>,
state: &mut State,
) -> Result<()> {
let mut recieved = recieved.to_string();
if recieved.split(' ').count() == 1 {
recieved += " ";
}
let parsed = ircparser::parse(&recieved);
let command = match parsed {
Ok(val) => val[0].clone(),
Err(_) => {
writer_channel_tx.send(recieved)?;
return Ok(());
}
};
if command.command == "PRIVMSG" && !command.params[0].starts_with('#') {
if command.params[0] == "BOUNCER" {
return parse_bouncer_command(command.params[1].clone(), state);
}
if state
.nicks_without_encryption
.contains(&command.params[0].to_lowercase())
{
writer_channel_tx.send(recieved)?;
return Ok(());
}
let other = &command.params[0];
if !keys.contains_key(other) {
helpers::send_key(writer_channel_tx, other, public_key)?;
let key = helpers::recieve_message_base64(
writer_channel_rx,
listener_channel_tx,
"127.0.0.1",
server,
other,
"END_KEY",
)?;
let key = SignedPublicKey::from_bytes(key.as_slice())?;
keys.insert(other.to_string(), key);
}
let foreign_key = keys.get(other).unwrap();
writer_channel_tx.send(format!("PRIVMSG {other} START_MESSAGE\r\n"))?;
writer_channel_tx.send(bytes_to_privmsg_base64(
&encryption::encrypt(foreign_key, &command.params[1])?,
other,
))?;
writer_channel_tx.send(format!("PRIVMSG {other} END_MESSAGE\r\n"))?;
} else {
writer_channel_tx.send(recieved.replace("127.0.0.1", server))?;
}
Ok(())
}