145 lines
3.9 KiB
Rust
145 lines
3.9 KiB
Rust
use base64::{engine::general_purpose, Engine as _};
|
|
use eyre::Result;
|
|
use std::sync::mpsc::{self, Receiver, Sender};
|
|
|
|
#[derive(Debug)]
|
|
pub struct IrcParseError;
|
|
|
|
impl std::fmt::Display for IrcParseError {
|
|
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for IrcParseError {}
|
|
|
|
static MAX_LENGTH: usize = 300;
|
|
|
|
#[macro_export]
|
|
macro_rules! unwrap_or_return_result {
|
|
($e:expr) => {
|
|
match $e {
|
|
Ok(val) => val,
|
|
Err(_) => return Ok(()),
|
|
}
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! unwrap_or_return_option {
|
|
($e:expr) => {
|
|
match $e {
|
|
Some(val) => val,
|
|
None => return Ok(()),
|
|
}
|
|
};
|
|
}
|
|
|
|
pub struct State {
|
|
pub nicks_without_encryption: Vec<String>,
|
|
}
|
|
|
|
impl State {
|
|
pub fn new() -> Self {
|
|
State {
|
|
nicks_without_encryption: vec![
|
|
"nickserv".to_string(),
|
|
"chanserv".to_string(),
|
|
"hostserv".to_string(),
|
|
],
|
|
}
|
|
}
|
|
}
|
|
|
|
fn forward(
|
|
message: String,
|
|
stream: &Sender<String>,
|
|
server_local: &str,
|
|
server_forward: &str,
|
|
) -> Result<(), mpsc::SendError<String>> {
|
|
match ircparser::parse(&message) {
|
|
Ok(val) => match val[0].command.as_str() {
|
|
"PRIVMSG" => stream.send(message),
|
|
_ => stream.send(message.replace(server_local, server_forward)),
|
|
},
|
|
Err(_) => stream.send(message.replace(server_local, server_forward)),
|
|
}
|
|
}
|
|
|
|
pub fn bytes_to_privmsg_base64(message: &Vec<u8>, reciever: &str) -> String {
|
|
let message_length = MAX_LENGTH - format!("PRIVMSG {reciever} :\r\n").len();
|
|
let encoded = general_purpose::STANDARD.encode(message);
|
|
|
|
let mut command = String::new();
|
|
for line in encoded
|
|
.chars()
|
|
.collect::<Vec<char>>()
|
|
.chunks(message_length)
|
|
.map(|c| c.iter().collect::<String>())
|
|
{
|
|
dbg!(&line);
|
|
command.push_str(&format!("PRIVMSG {reciever} :{line}\r\n"));
|
|
}
|
|
|
|
println!("{}", encoded);
|
|
println!("{}", command);
|
|
command
|
|
}
|
|
|
|
pub fn send_key(sender: &Sender<String>, reciever: &str, key: &Vec<u8>) -> Result<()> {
|
|
sender.send(format!("PRIVMSG {reciever} :START_KEY\r\n"))?;
|
|
sender.send(bytes_to_privmsg_base64(key, reciever))?;
|
|
sender.send(format!("PRIVMSG {reciever} :END_KEY\r\n"))?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn get_nick(userstring: &str) -> Option<String> {
|
|
let userstring = userstring.chars().collect::<Vec<char>>();
|
|
let start_pos = userstring.iter().position(|&x| x == ':')? + 1;
|
|
let end_pos = userstring.iter().position(|&x| x == '!')?;
|
|
Some(userstring[start_pos..end_pos].iter().collect::<String>())
|
|
}
|
|
|
|
pub fn recieve_message_base64(
|
|
writer_channel_rx: &Receiver<String>,
|
|
forward_stream: &Sender<String>,
|
|
server_local: &str,
|
|
server_forward: &str,
|
|
sender: &str,
|
|
end: &str,
|
|
) -> Result<Vec<u8>> {
|
|
let mut message: Vec<String> = Vec::new();
|
|
|
|
while !message.contains(&end.to_string()) {
|
|
let recieved_raw = writer_channel_rx.recv()?;
|
|
|
|
let parse_result = ircparser::parse(&recieved_raw);
|
|
|
|
let recieved = match parse_result {
|
|
Ok(mut val) => val.pop_back().unwrap(),
|
|
Err(_) => return Err(IrcParseError.into()),
|
|
};
|
|
|
|
let begin_source_reciever = format!(":{sender}!");
|
|
if recieved.command != "PRIVMSG"
|
|
|| !recieved
|
|
.source
|
|
.clone()
|
|
.unwrap_or("".to_string())
|
|
.starts_with(&begin_source_reciever)
|
|
|| recieved.params[0].starts_with('#')
|
|
{
|
|
forward(recieved_raw, forward_stream, server_local, server_forward)?;
|
|
continue;
|
|
}
|
|
|
|
message.push(recieved.params[1].clone());
|
|
}
|
|
message.pop();
|
|
|
|
let foreign_key = dbg!(message.concat());
|
|
let foreign_key = general_purpose::STANDARD.decode(foreign_key)?;
|
|
Ok(foreign_key)
|
|
}
|