mirror of
https://github.com/MeexReay/bRAC.git
synced 2025-05-06 13:38:04 +03:00
configs
This commit is contained in:
parent
f23963c8b8
commit
46b4b84ed4
183
Cargo.lock
generated
183
Cargo.lock
generated
@ -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"
|
||||||
|
@ -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"
|
@ -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
|
||||||
|
|
||||||
|
@ -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
69
src/config.rs
Normal 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
|
||||||
|
}
|
72
src/main.rs
72
src/main.rs
@ -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());
|
||||||
}
|
}
|
||||||
|
12
src/rac.rs
12
src/rac.rs
@ -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");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
22
src/term.rs
22
src/term.rs
@ -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);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user