diff --git a/src/chat.rs b/src/chat.rs index 0ee4d12..167adbd 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1,11 +1,13 @@ use std::{ - error::Error, io::{stdout, Write}, + error::Error, sync::{atomic::{AtomicUsize, Ordering}, Arc, RwLock}, time::{SystemTime, UNIX_EPOCH} }; use colored::{Color, Colorize}; +use crate::proto::{register_user, send_message_auth}; + use super::{ proto::{connect, read_messages, send_message, send_message_spoof_auth}, util::sanitize_text, @@ -18,23 +20,24 @@ use regex::Regex; lazy_static! { pub static ref DATE_REGEX: Regex = Regex::new(r"\[(.*?)\] (.*)").unwrap(); pub static ref IP_REGEX: Regex = Regex::new(r"\{(.*?)\} (.*)").unwrap(); + pub static ref COLORED_USERNAMES: Vec<(Regex, Color)> = vec![ - (Regex::new(r"\u{B9AC}\u{3E70}<(.*?)> (.*)").unwrap(), Color::Green), // bRAC - (Regex::new(r"\u{2550}\u{2550}\u{2550}<(.*?)> (.*)").unwrap(), Color::BrightRed), // CRAB - (Regex::new(r"\u{00B0}\u{0298}<(.*?)> (.*)").unwrap(), Color::Magenta), // Mefidroniy - (Regex::new(r"<(.*?)> (.*)").unwrap(), Color::Cyan), // clRAC + (Regex::new(r"\u{B9AC}\u{3E70}<(.*?)> (.*)").unwrap(), Color::Green), // bRAC + (Regex::new(r"\u{2550}\u{2550}\u{2550}<(.*?)> (.*)").unwrap(), Color::BrightRed), // CRAB + (Regex::new(r"\u{00B0}\u{0298}<(.*?)> (.*)").unwrap(), Color::Magenta), // Mefidroniy + (Regex::new(r"<(.*?)> (.*)").unwrap(), Color::Cyan), // clRAC ]; } #[cfg(not(feature = "pretty"))] pub mod minimal_tui; #[cfg(not(feature = "pretty"))] -pub use minimal_tui::run_main_loop; +pub use minimal_tui::{run_main_loop, update_console}; #[cfg(feature = "pretty")] pub mod pretty_tui; #[cfg(feature = "pretty")] -pub use pretty_tui::run_main_loop; +pub use pretty_tui::{run_main_loop, update_console}; pub struct ChatStorage { @@ -81,81 +84,98 @@ impl ChatStorage { } -const HELP_MESSAGE: &str = "Help message:\r -/help - show help message\r -/clear n - send empty message n times\r -/spam n text - send message with text n times\r -/ping - check server ping\r -\r -Press enter to close"; +const HELP_MESSAGE: &str = "Help message: +/help - show help message +/register password - register user +/login password - login user +/clear n - send empty message n times +/spam n text - send message with text n times +/ping - check server ping"; +pub fn add_message(ctx: Arc, message: &str) -> Result<(), Box> { + ctx.messages.append( + ctx.max_messages, + message.split("\n").map(|o| o.to_string()).collect::>() + ); + update_console(ctx) +} + pub fn on_command(ctx: Arc, command: &str) -> Result<(), Box> { let command = command.trim_start_matches("/"); let (command, args) = command.split_once(" ").unwrap_or((&command, "")); let args = args.split(" ").collect::>(); - let response = move || -> Option { - if command == "clear" { - let times = args.get(0)?.parse().ok()?; - for _ in 0..times { - send_message(&mut connect(&ctx.host, ctx.enable_ssl).ok()?, "\r").ok()?; - } - None - } else if command == "spam" { - let times = args.get(0)?.parse().ok()?; - let msg = args[1..].join(" "); - for _ in 0..times { - send_message(&mut connect(&ctx.host, ctx.enable_ssl).ok()?, &("\r".to_string()+&msg)).ok()?; - } - None - // send_message(&mut connect(&ctx.host, ctx.enable_ssl)?, - // &prepare_message(ctx.clone(), - // &format!("\r\x1B[1A{}{}", args.join(" "), " ".repeat(10)).repeat(ctx.max_messages) - // ))?; - } else if command == "help" { - Some(HELP_MESSAGE.to_string()) - } else if command == "ping" { - let mut before = ctx.messages.packet_size(); - let message = format!("Checking ping... {:X}", SystemTime::now().duration_since(UNIX_EPOCH).ok()?.as_millis()); + if command == "clear" { + let Some(times) = args.get(0) else { return Ok(()) }; + let times = times.parse()?; + for _ in 0..times { + send_message(&mut connect(&ctx.host, ctx.enable_ssl)?, "\r")?; + } + } else if command == "spam" { + let Some(times) = args.get(0) else { return Ok(()) }; + let times = times.parse()?; + let msg = args[1..].join(" "); + for _ in 0..times { + send_message(&mut connect(&ctx.host, ctx.enable_ssl)?, &("\r".to_string()+&msg))?; + } + } else if command == "help" { + add_message(ctx.clone(), HELP_MESSAGE)?; + } else if command == "register" { + let Some(pass) = args.get(0) else { + add_message(ctx.clone(), "please provide password as the first argument")?; + return Ok(()) + }; - send_message(&mut connect(&ctx.host, ctx.enable_ssl).ok()?, &message).ok()?; + match register_user(&mut connect(&ctx.host, ctx.enable_ssl)?, &ctx.name, pass) { + Ok(true) => { + add_message(ctx.clone(), "you was registered successfully bro")?; + *ctx.registered.write().unwrap() = Some(pass.to_string()); + }, + Ok(false) => add_message(ctx.clone(), "user with this account already exists bruh")?, + Err(e) => add_message(ctx.clone(), &format!("ERROR while registrationing: {}", e))? + }; + } else if command == "login" { + let Some(pass) = args.get(0) else { + add_message(ctx.clone(), "please provide password as the first argument")?; + return Ok(()) + }; - let start = SystemTime::now(); + add_message(ctx.clone(), "ye bro you was logged in")?; + *ctx.registered.write().unwrap() = Some(pass.to_string()); + } else if command == "ping" { + let mut before = ctx.messages.packet_size(); + let message = format!("Checking ping... {:X}", SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis()); - loop { - let data = read_messages( - &mut connect(&ctx.host, ctx.enable_ssl).ok()?, - ctx.max_messages, - before, - !ctx.enable_ssl, - ctx.enable_chunked - ).ok().flatten(); - - if let Some((data, size)) = data { - if let Some(last) = data.iter().rev().find(|o| o.contains(&message)) { - if last.contains(&message) { - break; - } else { - before = size; - } + send_message(&mut connect(&ctx.host, ctx.enable_ssl)?, &message)?; + + let start = SystemTime::now(); + + loop { + let data = read_messages( + &mut connect(&ctx.host, ctx.enable_ssl)?, + ctx.max_messages, + before, + !ctx.enable_ssl, + ctx.enable_chunked + ).ok().flatten(); + + if let Some((data, size)) = data { + if let Some(last) = data.iter().rev().find(|o| o.contains(&message)) { + if last.contains(&message) { + break; } else { before = size; } + } else { + before = size; } } - - send_message(&mut connect(&ctx.host, ctx.enable_ssl).ok()?, &format!("Ping = {}ms", start.elapsed().unwrap().as_millis())).ok()?; - - None - } else { - None } - }(); - if let Some(response) = response { - write!(stdout(), "{}", response)?; - stdout().flush()?; + add_message(ctx.clone(), &format!("Ping = {}ms", start.elapsed().unwrap().as_millis()))?; + } else { + add_message(ctx.clone(), "Unknown command bruh")?; } Ok(()) @@ -198,7 +218,9 @@ pub fn on_send_message(ctx: Arc, message: &str) -> Result<(), Box Option) -> Result<(), Box> { + let messages = ctx.messages.messages(); + + let mut out = stdout().lock(); + write!( + out, + "{}\n{}\n{} ", + "\n".repeat(ctx.max_messages - messages.len()), + messages + .into_iter() + .map(|o| o.white().blink().to_string()) + .collect::>() + .join("\n"), + ">".bright_yellow() + ); + out.flush(); + + Ok(()) +} + pub fn run_main_loop(ctx: Arc) { loop { match connect(&ctx.host, ctx.enable_ssl) { @@ -49,21 +70,7 @@ pub fn run_main_loop(ctx: Arc) { } } - let messages = ctx.messages.messages(); - - let mut out = stdout().lock(); - write!( - out, - "{}\n{}\n{} ", - "\n".repeat(ctx.max_messages - messages.len()), - messages - .into_iter() - .map(|o| o.white().blink().to_string()) - .collect::>() - .join("\n"), - ">".bright_yellow() - ); - out.flush(); + let _ = update_console(ctx.clone()); if let Some(message) = get_input("") { if let Err(e) = on_send_message(ctx.clone(), &message) { diff --git a/src/chat/pretty_tui.rs b/src/chat/pretty_tui.rs index 81f4fb1..60748d1 100644 --- a/src/chat/pretty_tui.rs +++ b/src/chat/pretty_tui.rs @@ -353,6 +353,10 @@ pub fn on_close() { execute!(stdout(), event::DisableMouseCapture).unwrap(); } +pub fn update_console(ctx: Arc) -> Result<(), Box> { + print_console(ctx.clone(), ctx.messages.messages(), &ctx.input.read().unwrap()) +} + pub fn run_main_loop(ctx: Arc) { enable_raw_mode().unwrap(); execute!(stdout(), event::EnableMouseCapture).unwrap(); diff --git a/src/config.rs b/src/config.rs index 52a4906..62bd733 100644 --- a/src/config.rs +++ b/src/config.rs @@ -213,6 +213,7 @@ pub struct Context { pub input: Arc>, pub host: String, pub name: String, + pub registered: Arc>>, pub disable_formatting: bool, pub disable_commands: bool, pub disable_hiding_ip: bool, @@ -234,6 +235,7 @@ impl Context { message_format: args.message_format.clone().unwrap_or(config.message_format.clone()), host: args.host.clone().unwrap_or(config.host.clone()), name: args.name.clone().or(config.name.clone()).unwrap_or_else(|| ask_string("Name", format!("Anon#{:X}", random::()))), + registered: Arc::new(RwLock::new(None)), disable_formatting: args.disable_formatting, disable_commands: args.disable_commands, disable_hiding_ip: args.disable_ip_hiding,