mirror of
https://github.com/MeexReay/bRAC.git
synced 2025-05-06 13:38:04 +03:00
advertisement, update_time, colored_usernames refactor, /clear command
This commit is contained in:
parent
8c3517a8ac
commit
ebf740aed5
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -16,6 +16,7 @@ name = "bRAC"
|
|||||||
version = "1.99.2"
|
version = "1.99.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"colored",
|
"colored",
|
||||||
|
"lazy_static",
|
||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"termion",
|
"termion",
|
||||||
@ -60,6 +61,12 @@ dependencies = [
|
|||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.169"
|
version = "0.2.169"
|
||||||
|
@ -7,4 +7,5 @@ edition = "2021"
|
|||||||
rand = "0.9.0"
|
rand = "0.9.0"
|
||||||
termion = "4.0.3"
|
termion = "4.0.3"
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
colored = "3.0.0"
|
colored = "3.0.0"
|
||||||
|
lazy_static = "1.5.0"
|
16
README.md
16
README.md
@ -26,27 +26,27 @@ cargo run # run
|
|||||||
|
|
||||||
#### bRAC
|
#### bRAC
|
||||||
|
|
||||||
regex - `\[(.*?)\] \uB9AC\u3E70<(.*?)> (.*)` \
|
regex - `\uB9AC\u3E70<(.*?)> (.*)` \
|
||||||
color - green \
|
color - green \
|
||||||
example - `[date] 리㹰<nick> text`
|
example - `리㹰<nick> text`
|
||||||
|
|
||||||
#### CRAB
|
#### CRAB
|
||||||
|
|
||||||
regex - `\[(.*?)\] \u2550\u2550\u2550<(.*?)> (.*)` \
|
regex - `\u2550\u2550\u2550<(.*?)> (.*)` \
|
||||||
color - light red \
|
color - light red \
|
||||||
example - `[date] ═══<nick> text`
|
example - `═══<nick> text`
|
||||||
|
|
||||||
#### Mefedroniy
|
#### Mefedroniy
|
||||||
|
|
||||||
regex - `\[(.*?)\] (.*?): (.*)` \
|
regex - `(.*?): (.*)` \
|
||||||
color - light magenta \
|
color - light magenta \
|
||||||
example - `[date] nick: text`
|
example - `nick: text`
|
||||||
|
|
||||||
#### clRAC
|
#### clRAC
|
||||||
|
|
||||||
regex - `\[(.*?)\] <(.*?)> (.*)` \
|
regex - `<(.*?)> (.*)` \
|
||||||
color - cyan \
|
color - cyan \
|
||||||
example - `[date] <nick> text`
|
example - `<nick> text`
|
||||||
|
|
||||||
## see also
|
## see also
|
||||||
|
|
||||||
|
4
config.yml
Normal file
4
config.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
host: meex.lol:11234
|
||||||
|
name: null
|
||||||
|
magic_key: "\uB9AC\u3E70"
|
||||||
|
ad: "\r\x1B[1A use bRAC client! https://github.com/MeexReay/bRAC \x1B[1B"
|
137
src/main.rs
137
src/main.rs
@ -1,29 +1,46 @@
|
|||||||
use std::{
|
use std::{
|
||||||
error::Error, io::{stdin, stdout, BufRead, Read, Write}, net::TcpStream, sync::{Arc, RwLock}, thread
|
collections::HashMap, error::Error, io::{stdin, stdout, BufRead, Read, Write}, net::TcpStream, sync::{Arc, RwLock}, thread, time::Duration
|
||||||
};
|
};
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::{Color, Colorize};
|
||||||
use rand::random;
|
use rand::random;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use termion::{event::Key, input::TermRead, raw::IntoRawMode};
|
use termion::{event::Key, input::TermRead, raw::IntoRawMode};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
|
||||||
const MAX_MESSAGES: usize = 100;
|
const MAX_MESSAGES: usize = 100;
|
||||||
const DEFAULT_HOST: &str = "meex.lol:11234";
|
const DEFAULT_HOST: &str = "meex.lol:11234";
|
||||||
const MAGIC_KEY: &str = "\u{B9AC}\u{3E70}";
|
const MAGIC_KEY: &str = "\u{B9AC}\u{3E70}";
|
||||||
|
// const ADVERTISEMENT: &str = "\r\x1B[1A use bRAC client! https://github.com/MeexReay/bRAC \x1B[1B";
|
||||||
|
const ADVERTISEMENT: &str = "";
|
||||||
|
const UPDATE_TIME: u64 = 50;
|
||||||
|
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref DATE_REGEX: Regex = Regex::new(r"\[(.*?)\] (.*)").unwrap();
|
||||||
|
static ref COLORED_USERNAMES: Vec<(Regex, Color)> = vec![
|
||||||
|
(Regex::new(&format!(r"{}<(.*?)> (.*)", MAGIC_KEY)).unwrap(), Color::Green),
|
||||||
|
(Regex::new(r"\u{2550}\u{2550}\u{2550}<(.*?)> (.*)").unwrap(), Color::BrightRed),
|
||||||
|
(Regex::new(r"(.*?): (.*)").unwrap(), Color::Magenta),
|
||||||
|
(Regex::new(r"<(.*?)> (.*)").unwrap(), Color::Cyan),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn send_message(host: &str, message: &str) -> Result<(), Box<dyn Error>> {
|
fn send_message(host: &str, message: &str) -> Result<(), Box<dyn Error>> {
|
||||||
let mut stream = TcpStream::connect(host)?;
|
let mut stream = TcpStream::connect(host)?;
|
||||||
stream.write_all(&[0x01])?;
|
stream.write_all(&[0x01])?;
|
||||||
let data = format!("\r\x07{}{}",
|
let data = format!("\r\x07{}{}{}",
|
||||||
message,
|
message,
|
||||||
if message.chars().count() < 39 {
|
if message.chars().count() < 39 {
|
||||||
" ".repeat(39-message.chars().count())
|
" ".repeat(39-message.chars().count())
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
},
|
||||||
|
ADVERTISEMENT
|
||||||
);
|
);
|
||||||
stream.write_all(data.as_bytes())?;
|
stream.write_all(data.as_bytes())?;
|
||||||
stream.write_all("\0".repeat(1023 - data.len()).as_bytes())?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +100,8 @@ fn recv_loop(host: &str, cache: Arc<RwLock<String>>, input: Arc<RwLock<String>>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*cache.write().unwrap() = data;
|
*cache.write().unwrap() = data;
|
||||||
print_console(&cache.read().unwrap(), &input.read().unwrap(), true)?;
|
print_console(&cache.read().unwrap(), &input.read().unwrap())?;
|
||||||
|
thread::sleep(Duration::from_millis(UPDATE_TIME));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -117,82 +135,71 @@ fn sanitize_text(input: &str) -> String {
|
|||||||
cleaned_text.into_owned()
|
cleaned_text.into_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_message(message: String) -> String {
|
/// nick content nick_color
|
||||||
|
fn find_username_color(message: &str) -> Option<(String, String, Color)> {
|
||||||
|
for (re, color) in COLORED_USERNAMES.iter() {
|
||||||
|
if let Some(captures) = re.captures(message) {
|
||||||
|
return Some((captures[1].to_string(), captures[2].to_string(), color.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_message(message: String) -> Option<String> {
|
||||||
|
let message = message.trim_end_matches(ADVERTISEMENT);
|
||||||
let message = Regex::new(r"\{[^}]*\}\ ").unwrap().replace(&message, "").to_string();
|
let message = Regex::new(r"\{[^}]*\}\ ").unwrap().replace(&message, "").to_string();
|
||||||
let message = sanitize_text(&message);
|
let message = sanitize_text(&message);
|
||||||
|
if message.starts_with(ADVERTISEMENT
|
||||||
|
.trim_start_matches("\r")
|
||||||
|
.trim_start_matches("\n")) {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(captures) = Regex::new(r"\[(.*?)\] <(.*?)> (.*)").unwrap().captures(&message) {
|
let date = DATE_REGEX.captures(&message)?;
|
||||||
let date = &captures[1];
|
let (date, message) = (date.get(1)?.as_str().to_string(), date.get(2)?.as_str().to_string());
|
||||||
let nick = &captures[2];
|
|
||||||
let content = &captures[3];
|
Some(if let Some(captures) = find_username_color(&message) {
|
||||||
|
let nick = captures.0;
|
||||||
|
let content = captures.1;
|
||||||
|
let color = captures.2;
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"{} {} {}",
|
"{} {} {}",
|
||||||
format!("[{}]", date).white().dimmed(),
|
format!("[{}]", date).white().dimmed(),
|
||||||
format!("<{}>", nick).cyan().bold(),
|
format!("<{}>", nick).color(color).bold(),
|
||||||
content.white().blink()
|
|
||||||
)
|
|
||||||
} else if let Some(captures) = Regex::new(&format!(r"\[(.*?)\] {}<(.*?)> (.*)", MAGIC_KEY)).unwrap().captures(&message) {
|
|
||||||
let date = &captures[1];
|
|
||||||
let nick = &captures[2];
|
|
||||||
let content = &captures[3];
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"{} {} {}",
|
|
||||||
format!("[{}]", date).white().dimmed(),
|
|
||||||
format!("<{}>", nick).green().bold(),
|
|
||||||
content.white().blink()
|
|
||||||
)
|
|
||||||
} else if let Some(captures) = Regex::new(r"\[(.*?)\] (.*?): (.*)").unwrap().captures(&message) {
|
|
||||||
let date = &captures[1];
|
|
||||||
let nick = &captures[2];
|
|
||||||
let content = &captures[3];
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"{} {} {}",
|
|
||||||
format!("[{}]", date).white().dimmed(),
|
|
||||||
format!("<{}>", nick).magenta().bold(),
|
|
||||||
content.white().blink()
|
|
||||||
)
|
|
||||||
} else if let Some(captures) = Regex::new(r"\[(.*?)\] \u{2550}\u{2550}\u{2550}<(.*?)> (.*)").unwrap().captures(&message) {
|
|
||||||
let date = &captures[1];
|
|
||||||
let nick = &captures[2];
|
|
||||||
let content = &captures[3];
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"{} {} {}",
|
|
||||||
format!("[{}]", date).white().dimmed(),
|
|
||||||
format!("<{}>", nick).bright_red().bold(),
|
|
||||||
content.white().blink()
|
|
||||||
)
|
|
||||||
} else if let Some(captures) = Regex::new(r"\[(.*?)\] (.*)").unwrap().captures(&message) {
|
|
||||||
let date = &captures[1];
|
|
||||||
let content = &captures[2];
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"{} {}",
|
|
||||||
format!("[{}]", date).white().dimmed(),
|
|
||||||
content.white().blink()
|
content.white().blink()
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
message.to_string()
|
format!(
|
||||||
}
|
"{} {}",
|
||||||
|
format!("[{}]", date).white().dimmed(),
|
||||||
|
message.white().blink()
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_console(messages: &str, input: &str, sound: bool) -> Result<(), Box<dyn Error>> {
|
fn on_command(host: &str, command: &str) -> Result<(), Box<dyn Error>> {
|
||||||
|
if command == "/clear" {
|
||||||
|
send_message(host, &"\n".repeat(MAX_MESSAGES))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_console(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(MAX_MESSAGES);
|
||||||
messages.reverse();
|
messages.reverse();
|
||||||
let messages: Vec<String> = messages.into_iter().map(on_message).collect();
|
let messages: Vec<String> = messages.into_iter().filter_map(format_message).collect();
|
||||||
let mut out = stdout().into_raw_mode()?;
|
let mut out = stdout().into_raw_mode()?;
|
||||||
let text = format!(
|
let text = format!(
|
||||||
"{}{}\n{}> {}",
|
"{}{}\n> {}",
|
||||||
"\n".repeat(MAX_MESSAGES - messages.len()),
|
"\n".repeat(MAX_MESSAGES - messages.len()),
|
||||||
messages.join("\n"),
|
messages.join("\n"),
|
||||||
if sound { "\x07" } else { "" },
|
// if sound { "\x07" } else { "" },
|
||||||
input
|
input
|
||||||
);
|
);
|
||||||
for line in text.lines() {
|
for line in text.lines() {
|
||||||
@ -229,10 +236,14 @@ fn main() {
|
|||||||
Key::Char('\n') => {
|
Key::Char('\n') => {
|
||||||
let message = input.read().unwrap().clone();
|
let message = input.read().unwrap().clone();
|
||||||
if !message.is_empty() {
|
if !message.is_empty() {
|
||||||
send_message(&host, &format!("{}<{}> {}", MAGIC_KEY, name, message)).expect("Error sending message");
|
if message.starts_with("/") {
|
||||||
input.write().unwrap().clear();
|
on_command(&host, &message).expect("Error on command");
|
||||||
|
} else {
|
||||||
|
send_message(&host, &format!("{}<{}> {}", MAGIC_KEY, name, message)).expect("Error sending message");
|
||||||
|
input.write().unwrap().clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
print_console(&messages.read().unwrap(), &input.read().unwrap(), false).expect("Error printing console");
|
print_console(&messages.read().unwrap(), &input.read().unwrap()).expect("Error printing console");
|
||||||
}
|
}
|
||||||
Key::Backspace => {
|
Key::Backspace => {
|
||||||
input.write().unwrap().pop();
|
input.write().unwrap().pop();
|
||||||
|
Loading…
Reference in New Issue
Block a user