This commit is contained in:
MeexReay 2025-02-10 13:04:37 +03:00
parent f23963c8b8
commit 46b4b84ed4
8 changed files with 314 additions and 59 deletions

183
Cargo.lock generated
View File

@ -11,6 +11,12 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "anyhow"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.4.0" version = "1.4.0"
@ -23,9 +29,12 @@ version = "0.1.0+1.99.2"
dependencies = [ dependencies = [
"colored", "colored",
"crossterm", "crossterm",
"homedir",
"lazy_static", "lazy_static",
"rand", "rand",
"regex", "regex",
"serde",
"serde_yml",
] ]
[[package]] [[package]]
@ -46,6 +55,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]] [[package]]
name = "colored" name = "colored"
version = "3.0.0" version = "3.0.0"
@ -80,6 +95,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.3.10" version = "0.3.10"
@ -102,6 +123,40 @@ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]]
name = "hashbrown"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
[[package]]
name = "homedir"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bdbbd5bc8c5749697ccaa352fa45aff8730cf21c68029c0eef1ffed7c3d6ba2"
dependencies = [
"cfg-if",
"nix",
"widestring",
"windows",
]
[[package]]
name = "indexmap"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@ -114,6 +169,16 @@ version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libyml"
version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980"
dependencies = [
"anyhow",
"version_check",
]
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.15" version = "0.4.15"
@ -154,6 +219,18 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "nix"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags",
"cfg-if",
"cfg_aliases",
"libc",
]
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.3" version = "0.12.3"
@ -286,12 +363,53 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "ryu"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_yml"
version = "0.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd"
dependencies = [
"indexmap",
"itoa",
"libyml",
"memchr",
"ryu",
"serde",
"version_check",
]
[[package]] [[package]]
name = "signal-hook" name = "signal-hook"
version = "0.3.17" version = "0.3.17"
@ -345,6 +463,12 @@ version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"
@ -360,6 +484,12 @@ dependencies = [
"wit-bindgen-rt", "wit-bindgen-rt",
] ]
[[package]]
name = "widestring"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -382,6 +512,59 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
dependencies = [
"windows-core",
"windows-targets",
]
[[package]]
name = "windows-core"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-targets",
]
[[package]]
name = "windows-implement"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-result"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
dependencies = [
"windows-targets",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.52.0"

View File

@ -9,3 +9,6 @@ regex = "1.11.1"
colored = "3.0.0" colored = "3.0.0"
lazy_static = "1.5.0" lazy_static = "1.5.0"
crossterm = "0.28.1" crossterm = "0.28.1"
serde = { version = "1.0.217", features = ["serde_derive"] }
serde_yml = "0.0.12"
homedir = "0.3.4"

View File

@ -3,7 +3,7 @@ better RAC client
## features ## features
- cheat commands - cheat commands (type /help)
- no ip and date visible - no ip and date visible
- uses TOR proxy server by default - uses TOR proxy server by default
- plays sound when users receive your messages - plays sound when users receive your messages
@ -32,7 +32,8 @@ cargo run # run (builds and runs bRAC itself)
## commands ## commands
`/clear` - clear chat \ `/clear` - clear chat \
`/spam *args` - spam with text `/spam *args` - spam with text \
`/help` - show help message
## colored usernames ## colored usernames

View File

@ -1,5 +0,0 @@
host: meex.lol:11234 # reverse proxy through tor
name: null # username (null - ask every time)
magic_key: "\uB9AC\u3E70" # default bRAC marker
ad_enabled: false # enable sending ad of bRAC above your message
update_time: 50 # update messages interval

69
src/config.rs Normal file
View File

@ -0,0 +1,69 @@
use std::{fs, path::{Path, PathBuf}};
use homedir::my_home;
use serde_yml;
use super::get_input;
const MESSAGE_FORMAT: &str = "\u{B9AC}\u{3E70}<{name}> {text}";
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Config {
pub host: String,
pub name: Option<String>,
pub message_format: String,
pub update_time: usize,
pub max_messages: usize
}
pub fn load_config(path: PathBuf) -> Config {
println!("Config path: {}", path.to_string_lossy());
println!("Loading config...");
let config = if !fs::exists(&path).unwrap_or_default() {
let host = get_input("Host (default: meex.lol:11234) > ").unwrap_or("meex.lol:11234".to_string());
let name = get_input("Name (default: ask every time) > ");
let update_time = get_input("Update Interval (default: 50) > ").map(|o| o.parse().ok()).flatten().unwrap_or(50);
let max_messages = get_input("Max Messages (default: 100) > ").map(|o| o.parse().ok()).flatten().unwrap_or(100);
let config = Config {
host,
name,
message_format: MESSAGE_FORMAT.to_string(),
update_time,
max_messages
};
fs::write(path, serde_yml::to_string(&config).expect("Config save error"));
config
} else {
let config = &fs::read_to_string(&path).expect("Config load error");
serde_yml::from_str(config).expect("Config load error")
};
println!("Config loaded successfully!");
config
}
pub fn get_config_path() -> PathBuf {
let config_path = Path::new("config.yml").to_path_buf();
#[cfg(target_os = "linux")]
let config_path = {
let home_dir = my_home().ok().flatten().expect("Config find path error");
home_dir.join(".config").join("bRAC").join("config.yml")
};
#[cfg(target_os = "macos")]
let config_path = {
let home_dir = my_home().ok().flatten().expect("Config find path error");
home_dir.join(".config").join("bRAC").join("config.yml")
};
#[cfg(target_os = "windows")]
let config_path = {
let appdata = env::var("APPDATA").expect("Config find path error");
Path::new(&appdata).join("bRAC").join("config.yml")
};
config_path
}

View File

@ -1,10 +1,9 @@
use std::{ use std::{
error::Error, error::Error, io::{stdin, stdout, BufRead, Write}, sync::{Arc, RwLock}, thread, time::{Duration, SystemTime, UNIX_EPOCH}
io::{stdin, stdout, BufRead, Write},
sync::{Arc, RwLock},
}; };
use colored::Color; use colored::Color;
use config::{get_config_path, load_config, Config};
use rac::{run_recv_loop, send_message}; use rac::{run_recv_loop, send_message};
use rand::random; use rand::random;
use regex::Regex; use regex::Regex;
@ -12,15 +11,11 @@ use lazy_static::lazy_static;
use term::run_main_loop; use term::run_main_loop;
const DEFAULT_HOST: &str = "meex.lol:11234";
const ADVERTISEMENT: &str = "\r\x1B[1A use bRAC client! https://github.com/MeexReay/bRAC \x1B[1B"; const ADVERTISEMENT: &str = "\r\x1B[1A use bRAC client! https://github.com/MeexReay/bRAC \x1B[1B";
const MAX_MESSAGES: usize = 100;
const MAGIC_KEY: &str = "\u{B9AC}\u{3E70}";
const ADVERTISEMENT_ENABLED: bool = false; const ADVERTISEMENT_ENABLED: bool = false;
const UPDATE_TIME: u64 = 50;
mod config;
mod term; mod term;
mod rac; mod rac;
@ -28,7 +23,7 @@ mod rac;
lazy_static! { lazy_static! {
static ref DATE_REGEX: Regex = Regex::new(r"\[(.*?)\] (.*)").unwrap(); static ref DATE_REGEX: Regex = Regex::new(r"\[(.*?)\] (.*)").unwrap();
static ref COLORED_USERNAMES: Vec<(Regex, Color)> = vec![ static ref COLORED_USERNAMES: Vec<(Regex, Color)> = vec![
(Regex::new(&format!(r"{}<(.*?)> (.*)", MAGIC_KEY)).unwrap(), Color::Green), (Regex::new(r"\u{B9AC}\u{3E70}<(.*?)> (.*)").unwrap(), Color::Green),
(Regex::new(r"\u{2550}\u{2550}\u{2550}<(.*?)> (.*)").unwrap(), Color::BrightRed), (Regex::new(r"\u{2550}\u{2550}\u{2550}<(.*?)> (.*)").unwrap(), Color::BrightRed),
(Regex::new(r"(.*?): (.*)").unwrap(), Color::Magenta), (Regex::new(r"(.*?): (.*)").unwrap(), Color::Magenta),
(Regex::new(r"<(.*?)> (.*)").unwrap(), Color::Cyan), (Regex::new(r"<(.*?)> (.*)").unwrap(), Color::Cyan),
@ -37,38 +32,32 @@ lazy_static! {
fn get_input(prompt: &str) -> Option<String> {
let mut out = stdout().lock();
out.write_all(prompt.as_bytes()).ok()?;
out.flush().ok()?;
let input = stdin().lock().lines().next()
.map(|o| o.ok())
.flatten()?;
fn get_input(prompt: &str, default: &str) -> String { if input.is_empty() {
let input = || -> Option<String> { None
let mut out = stdout().lock();
out.write_all(prompt.as_bytes()).ok()?;
out.flush().ok()?;
stdin().lock().lines().next()
.map(|o| o.ok())
.flatten()
}();
if let Some(input) = &input {
if input.is_empty() {
default
} else {
input
}
} else { } else {
default Some(input.to_string())
}.to_string() }
} }
fn on_command(host: &str, command: &str) -> Result<(), Box<dyn Error>> {
fn on_command(config: Arc<Config>, host: &str, command: &str) -> Result<(), Box<dyn Error>> {
let command = command.trim_start_matches("/"); let command = command.trim_start_matches("/");
let (command, args) = command.split_once(" ").unwrap_or((&command, "")); let (command, args) = command.split_once(" ").unwrap_or((&command, ""));
let args = args.split(" ").collect::<Vec<&str>>(); let args = args.split(" ").collect::<Vec<&str>>();
if command == "clear" { if command == "clear" {
send_message(host, &format!("\r\x1B[1A{}", " ".repeat(64)).repeat(MAX_MESSAGES))?; send_message(host, &format!("\r\x1B[1A{}", " ".repeat(64)).repeat(config.max_messages))?;
// *input.write().unwrap() = "/ заспамлено)))".to_string(); // *input.write().unwrap() = "/ заспамлено)))".to_string();
} else if command == "spam" { } else if command == "spam" {
send_message(host, &format!("\r\x1B[1A{}{}", args.join(" "), " ".repeat(10)).repeat(MAX_MESSAGES))?; send_message(host, &format!("\r\x1B[1A{}{}", args.join(" "), " ".repeat(10)).repeat(config.max_messages))?;
// *input.write().unwrap() = "/ заспамлено)))".to_string(); // *input.write().unwrap() = "/ заспамлено)))".to_string();
} else if command == "help" { } else if command == "help" {
write!(stdout(), "/clear - clear console; /spam *args - spam console with text; /help - show help message")?; write!(stdout(), "/clear - clear console; /spam *args - spam console with text; /help - show help message")?;
@ -79,13 +68,26 @@ fn on_command(host: &str, command: &str) -> Result<(), Box<dyn Error>> {
} }
fn main() { fn main() {
let host = get_input(&format!("Host (default: {}) > ", DEFAULT_HOST), DEFAULT_HOST); let start_time = SystemTime::now();
let anon_name = format!("Anon#{:X}", random::<u16>()); let config = load_config(get_config_path());
let name = get_input(&format!("Name (default: {}) > ", anon_name), &anon_name);
let name = match config.name.clone() {
Some(i) => i,
None => {
let anon_name = format!("Anon#{:X}", random::<u16>());
get_input(&format!("Name (default: {}) > ", anon_name)).unwrap_or(anon_name)
},
};
let messages = Arc::new(RwLock::new(String::new())); let messages = Arc::new(RwLock::new(String::new()));
let input = Arc::new(RwLock::new(String::new())); let input = Arc::new(RwLock::new(String::new()));
let config = Arc::new(config);
run_recv_loop(host.clone(), messages.clone(), input.clone()); let elapsed = start_time.elapsed().unwrap().as_millis();
run_main_loop(messages.clone(), input.clone(), host.clone(), name.clone()); if elapsed < 1500 {
thread::sleep(Duration::from_millis((1500 - elapsed) as u64));
}
run_recv_loop(config.clone(), config.host.clone(), messages.clone(), input.clone());
run_main_loop(config.clone(), messages.clone(), input.clone(), config.host.clone(), name.clone());
} }

View File

@ -1,6 +1,6 @@
use std::{error::Error, io::{Read, Write}, net::TcpStream, sync::{Arc, RwLock}, thread, time::Duration}; use std::{error::Error, io::{Read, Write}, net::TcpStream, sync::{Arc, RwLock}, thread, time::Duration};
use super::{ADVERTISEMENT, ADVERTISEMENT_ENABLED, term::print_console, UPDATE_TIME}; use crate::{config::Config, term::print_console, ADVERTISEMENT, ADVERTISEMENT_ENABLED};
pub fn send_message(host: &str, message: &str) -> Result<(), Box<dyn Error>> { pub fn send_message(host: &str, message: &str) -> Result<(), Box<dyn Error>> {
let mut stream = TcpStream::connect(host)?; let mut stream = TcpStream::connect(host)?;
@ -67,23 +67,23 @@ fn read_messages(host: &str) -> Result<String, Box<dyn Error>> {
Ok(packet_data) Ok(packet_data)
} }
fn recv_loop(host: &str, cache: Arc<RwLock<String>>, input: Arc<RwLock<String>>) -> Result<(), Box<dyn Error>> { fn recv_loop(config: Arc<Config>, host: &str, cache: Arc<RwLock<String>>, input: Arc<RwLock<String>>) -> Result<(), Box<dyn Error>> {
while let Ok(data) = read_messages(host) { while let Ok(data) = read_messages(host) {
if data == cache.read().unwrap().clone() { if data == cache.read().unwrap().clone() {
continue continue
} }
*cache.write().unwrap() = data; *cache.write().unwrap() = data;
print_console(&cache.read().unwrap(), &input.read().unwrap())?; print_console(config.clone(), &cache.read().unwrap(), &input.read().unwrap())?;
thread::sleep(Duration::from_millis(UPDATE_TIME)); thread::sleep(Duration::from_millis(config.update_time as u64));
} }
Ok(()) Ok(())
} }
pub fn run_recv_loop(host: String, messages: Arc<RwLock<String>>, input: Arc<RwLock<String>>) { pub fn run_recv_loop(config: Arc<Config>, host: String, messages: Arc<RwLock<String>>, input: Arc<RwLock<String>>) {
thread::spawn({ thread::spawn({
move || { move || {
let _ = recv_loop(&host, messages, input); let _ = recv_loop(config.clone(), &host, messages, input);
println!("Connection closed"); println!("Connection closed");
} }
}); });

View File

@ -1,22 +1,22 @@
use std::{error::Error, io::{stdout, Write}, sync::{Arc, RwLock}, thread, time::Duration}; use std::{error::Error, io::{stdout, Write}, sync::{Arc, RwLock}, time::Duration};
use colored::{Color, Colorize}; use colored::{Color, Colorize};
use crossterm::{cursor::MoveLeft, event::{self, Event, KeyCode}, terminal::{disable_raw_mode, enable_raw_mode}, ExecutableCommand}; use crossterm::{cursor::MoveLeft, event::{self, Event, KeyCode}, terminal::{disable_raw_mode, enable_raw_mode}, ExecutableCommand};
use regex::Regex; use regex::Regex;
use crate::{on_command, rac::send_message, ADVERTISEMENT, COLORED_USERNAMES, DATE_REGEX, MAGIC_KEY, MAX_MESSAGES}; use crate::{config::Config, on_command, rac::send_message, ADVERTISEMENT, COLORED_USERNAMES, DATE_REGEX};
pub fn print_console(messages: &str, input: &str) -> Result<(), Box<dyn Error>> { pub fn print_console(config: Arc<Config>, messages: &str, input: &str) -> Result<(), Box<dyn Error>> {
let mut messages = messages.split("\n") let mut messages = messages.split("\n")
.map(|o| o.to_string()) .map(|o| o.to_string())
.collect::<Vec<String>>(); .collect::<Vec<String>>();
messages.reverse(); messages.reverse();
messages.truncate(MAX_MESSAGES); messages.truncate(config.max_messages);
messages.reverse(); messages.reverse();
let messages: Vec<String> = messages.into_iter().filter_map(format_message).collect(); let messages: Vec<String> = messages.into_iter().filter_map(format_message).collect();
let text = format!( let text = format!(
"{}{}\n> {}", "{}{}\n> {}",
"\n".repeat(MAX_MESSAGES - messages.len()), "\n".repeat(config.max_messages - messages.len()),
messages.join("\n"), messages.join("\n"),
// if sound { "\x07" } else { "" }, // if sound { "\x07" } else { "" },
input input
@ -80,7 +80,7 @@ fn find_username_color(message: &str) -> Option<(String, String, Color)> {
None None
} }
fn poll_events(input: Arc<RwLock<String>>, messages: Arc<RwLock<String>>, host: String, name: String) { fn poll_events(config: Arc<Config>, input: Arc<RwLock<String>>, messages: Arc<RwLock<String>>, host: String, name: String) {
loop { loop {
if !event::poll(Duration::from_millis(50)).unwrap_or(false) { continue } if !event::poll(Duration::from_millis(50)).unwrap_or(false) { continue }
@ -107,12 +107,14 @@ fn poll_events(input: Arc<RwLock<String>>, messages: Arc<RwLock<String>>, host:
input.write().unwrap().clear(); input.write().unwrap().clear();
if message.starts_with("/") { if message.starts_with("/") {
on_command(&host, &message).expect("Error on command"); on_command(config.clone(), &host, &message).expect("Error on command");
} else { } else {
send_message(&host, &format!("{}<{}> {}", MAGIC_KEY, name, message)).expect("Error sending message"); let message = config.message_format.replace("{name}", &name).replace("{text}", &message);
send_message(&host, &message).expect("Error sending message");
} }
} else { } else {
print_console( print_console(
config.clone(),
&messages.read().unwrap(), &messages.read().unwrap(),
&input.read().unwrap() &input.read().unwrap()
).expect("Error printing console"); ).expect("Error printing console");
@ -147,7 +149,7 @@ fn poll_events(input: Arc<RwLock<String>>, messages: Arc<RwLock<String>>, host:
} }
} }
pub fn run_main_loop(messages: Arc<RwLock<String>>, input: Arc<RwLock<String>>, host: String, name: String) { pub fn run_main_loop(config: Arc<Config>, messages: Arc<RwLock<String>>, input: Arc<RwLock<String>>, host: String, name: String) {
enable_raw_mode().unwrap(); enable_raw_mode().unwrap();
// thread::spawn({ // thread::spawn({
@ -165,5 +167,5 @@ pub fn run_main_loop(messages: Arc<RwLock<String>>, input: Arc<RwLock<String>>,
// } // }
// }); // });
poll_events(input.clone(), messages.clone(), host, name); poll_events(config, input.clone(), messages.clone(), host, name);
} }