config refactor and some fixes like always

This commit is contained in:
MeexReay 2025-04-18 23:08:10 +03:00
parent 8dba6f2fd9
commit 592874680c
9 changed files with 239 additions and 301 deletions

60
Cargo.lock generated
View File

@ -101,6 +101,7 @@ dependencies = [
"rand",
"regex",
"serde",
"serde_default",
"serde_yml",
]
@ -252,6 +253,41 @@ version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "darling"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -284,6 +320,12 @@ dependencies = [
"rustc_version",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
@ -670,6 +712,12 @@ dependencies = [
"cc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indexmap"
version = "2.7.1"
@ -1057,6 +1105,18 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde_default"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "486b028b311aaaea83e0ba65a3e6e3cbef381e74e9d0bd6263faefd1fb503c1d"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_derive"
version = "1.0.219"

View File

@ -14,3 +14,4 @@ clap = { version = "4.5.36", features = ["derive"] }
serde = { version = "1.0.219", features = ["serde_derive"] }
gtk4 = { version = "0.9.6", features = [ "v4_10" ] }
chrono = "0.4.40"
serde_default = "0.2.0"

View File

@ -49,7 +49,7 @@ cargo run -r # build and run
If you have Nix package manager installed, you can use:
```bash
nix build github:MeexReay/bRAC # build release (result/bin/bRAC))
nix build github:MeexReay/bRAC # build release (result/bin/bRAC)
nix run github:MeexReay/bRAC # build and run
```

View File

@ -35,7 +35,7 @@
devShells.default = self'.devShells.stable;
packages.bRAC = let
deps = [
deps = with pkgs; [
pkg-config
openssl
gtk4
@ -45,17 +45,11 @@
cargo = pkgs.rust-bin.stable.latest.minimal;
rustc = pkgs.rust-bin.stable.latest.minimal;
}).buildRustPackage {
inherit (cargoToml.package) name;
inherit (cargoToml.package) name version;
src = ./.;
cargoLock.lockFile = ./Cargo.lock;
version = lib.concatStrings [ cargoToml.package.version version ];
buildInputs = deps;
nativeBuildInputs = deps;
patchPhase = ''
substituteInPlace Cargo.toml --replace \
'version = "${cargoToml.package.version}"' \
'version = "${lib.concatStrings [ cargoToml.package.version version ]}"'
'';
};
devShells.nightly = (mkDevShell (pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default)));
@ -63,4 +57,4 @@
devShells.msrv = (mkDevShell pkgs.rust-bin.stable.${msrv}.default);
};
};
}
}

View File

@ -1,88 +1,31 @@
use std::str::FromStr;
use std::{fs, path::PathBuf, thread, time::Duration};
use std::{fs, path::PathBuf};
use serde_yml;
use serde_default::DefaultFromSerde;
use clap::Parser;
use super::gui::{ask_bool, ask_string, ask_string_option, ask_usize, show_message};
const MESSAGE_FORMAT: &str = "\u{B9AC}\u{3E70}<{name}> {text}";
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Config {
#[serde(default = "default_host")]
pub host: String,
#[serde(default)]
pub name: Option<String>,
#[serde(default = "default_message_format")]
pub message_format: String,
#[serde(default = "default_update_time")]
pub update_time: usize,
#[serde(default = "default_max_messages")]
pub max_messages: usize,
#[serde(default)]
pub enable_ip_viewing: bool,
#[serde(default)]
pub disable_ip_hiding: bool,
#[serde(default)]
pub enable_auth: bool,
#[serde(default)]
pub enable_ssl: bool,
#[serde(default)]
pub enable_chunked: bool,
}
fn default_true() -> bool { true }
fn default_max_messages() -> usize { 200 }
fn default_update_time() -> usize { 50 }
fn default_host() -> String { "meex.lol:11234".to_string() }
fn default_message_format() -> String { MESSAGE_FORMAT.to_string() }
pub fn configure(path: PathBuf) -> Config {
show_message("Client setup", format!("To configure the client, please answer a few questions. It won't take long.
You can reconfigure client in any moment via `bRAC --configure`
Config stores in path `{}`", path.to_string_lossy()));
let host = ask_string("Host", default_host());
let name = ask_string_option("Name", "ask every time");
let update_time = ask_usize("Update interval", default_update_time());
let max_messages = ask_usize("Max messages", default_max_messages());
let message_format = ask_string("Message format", default_message_format());
let enable_ip_viewing = ask_bool("Enable users IP viewing?", true);
let disable_ip_hiding = ask_bool("Enable your IP viewing?", false);
let enable_auth = ask_bool("Enable auth-mode?", false);
let enable_ssl = ask_bool("Enable SSL?", false);
let enable_chunked = ask_bool("Enable chunked reading?", true);
let config = Config {
host,
name,
message_format,
update_time,
max_messages,
enable_ip_viewing,
disable_ip_hiding,
enable_auth,
enable_ssl,
enable_chunked
};
let config_text = serde_yml::to_string(&config).expect("Config save error");
fs::create_dir_all(&path.parent().expect("Config save error")).expect("Config save error");
fs::write(&path, config_text).expect("Config save error");
show_message("Config saved!", "You can reconfigure it in any moment via `bRAC --configure`");
config
}
pub fn load_config(path: PathBuf) -> Config {
if !fs::exists(&path).unwrap_or_default() {
let config = configure(path.clone());
thread::sleep(Duration::from_secs(4));
config
} else {
let config = &fs::read_to_string(&path).expect("Config load error");
serde_yml::from_str(config).expect("Config load error")
}
#[derive(serde::Serialize, serde::Deserialize, DefaultFromSerde, Clone)]
pub struct Config {
#[serde(default = "default_host")] pub host: String,
#[serde(default)] pub name: Option<String>,
#[serde(default = "default_message_format")] pub message_format: String,
#[serde(default = "default_update_time")] pub update_time: usize,
#[serde(default = "default_max_messages")] pub max_messages: usize,
#[serde(default)] pub hide_my_ip: bool,
#[serde(default)] pub show_other_ip: bool,
#[serde(default)] pub auth_enabled: bool,
#[serde(default)] pub ssl_enabled: bool,
#[serde(default)] pub chunked_enabled: bool,
#[serde(default = "default_true")] pub formatting_enabled: bool,
#[serde(default = "default_true")] pub commands_enabled: bool,
}
pub fn get_config_path() -> PathBuf {
@ -124,6 +67,25 @@ pub fn get_config_path() -> PathBuf {
config_dir.join("config.yml")
}
pub fn load_config(path: PathBuf) -> Config {
if !fs::exists(&path).unwrap_or_default() {
let config = Config::default();
let config_text = serde_yml::to_string(&config).expect("Config save error");
fs::create_dir_all(&path.parent().expect("Config save error")).expect("Config save error");
fs::write(&path, config_text).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")
}
}
pub fn save_config(path: PathBuf, config: Config) {
let config_text = serde_yml::to_string(&config).expect("Config save error");
fs::create_dir_all(&path.parent().expect("Config save error")).expect("Config save error");
fs::write(&path, config_text).expect("Config save error");
}
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Args {
@ -131,18 +93,6 @@ pub struct Args {
#[arg(short='p', long)]
pub config_path: bool,
/// Use specified host
#[arg(short='H', long)]
pub host: Option<String>,
/// Use specified name
#[arg(short='n', long)]
pub name: Option<String>,
/// Use specified message format
#[arg(short='F', long)]
pub message_format: Option<String>,
/// Print unformatted messages from chat and exit
#[arg(short='r', long)]
pub read_messages: bool,
@ -150,36 +100,34 @@ pub struct Args {
/// Send unformatted message to chat and exit
#[arg(short='s', long, value_name="MESSAGE")]
pub send_message: Option<String>,
#[arg(short='H', long)] pub host: Option<String>,
#[arg(short='n', long)] pub name: Option<String>,
#[arg(long)] pub message_format: Option<String>,
#[arg(long)] pub update_time: Option<usize>,
#[arg(long)] pub max_messages: Option<usize>,
#[arg(long)] pub hide_my_ip: Option<bool>,
#[arg(long)] pub show_other_ip: Option<bool>,
#[arg(long)] pub auth_enabled:Option <bool>,
#[arg(long)] pub ssl_enabled: Option<bool>,
#[arg(long)] pub chunked_enabled: Option<bool>,
#[arg(long)] pub formatting_enabled: Option<bool>,
#[arg(long)] pub commands_enabled: Option<bool>,
}
/// Disable message formatting and sanitizing
#[arg(short='f', long)]
pub disable_formatting: bool,
/// Disable slash commands
#[arg(short='c', long)]
pub disable_commands: bool,
/// Disable ip hiding
#[arg(short='i', long)]
pub disable_ip_hiding: bool,
/// Enable users IP viewing
#[arg(short='v', long)]
pub enable_users_ip_viewing: bool,
/// Configure client
#[arg(short='C', long)]
pub configure: bool,
/// Enable authentication
#[arg(short='a', long)]
pub enable_auth: bool,
/// Enable SSL
#[arg(short='S', long)]
pub enable_ssl: bool,
/// Enable chunked reading
#[arg(short='u', long)]
pub enable_chunked: bool,
impl Args {
pub fn patch_config(&self, config: &mut Config) {
if let Some(v) = self.host.clone() { config.host = v }
if let Some(v) = self.name.clone() { config.name = Some(v) }
if let Some(v) = self.message_format.clone() { config.message_format = v }
if let Some(v) = self.update_time.clone() { config.update_time = v }
if let Some(v) = self.max_messages.clone() { config.max_messages = v }
if let Some(v) = self.hide_my_ip.clone() { config.hide_my_ip = v }
if let Some(v) = self.show_other_ip.clone() { config.show_other_ip = v }
if let Some(v) = self.auth_enabled.clone() { config.auth_enabled = v }
if let Some(v) = self.ssl_enabled.clone() { config.ssl_enabled = v }
if let Some(v) = self.chunked_enabled.clone() { config.chunked_enabled = v }
if let Some(v) = self.formatting_enabled.clone() { config.formatting_enabled = v }
if let Some(v) = self.commands_enabled.clone() { config.commands_enabled = v }
}
}

View File

@ -1,50 +1,63 @@
use std::sync::{Arc, RwLock};
use std::sync::{atomic::{AtomicUsize, Ordering}, mpsc::Sender, Arc, RwLock};
use rand::random;
use super::{config::{Args, Config}, gui::ask_string, ChatContext};
use super::config::Config;
pub struct Context {
pub chat: Arc<RwLock<Option<Arc<ChatContext>>>>,
pub host: String,
pub name: String,
pub disable_formatting: bool,
pub disable_commands: bool,
pub disable_hiding_ip: bool,
pub message_format: String,
pub update_time: usize,
pub max_messages: usize,
pub enable_ip_viewing: bool,
pub enable_auth: bool,
pub enable_ssl: bool,
pub enable_chunked: bool,
pub registered: Arc<RwLock<Option<String>>>,
pub config: Arc<RwLock<Config>>,
pub sender: Arc<RwLock<Option<Arc<Sender<String>>>>>,
pub messages: RwLock<Vec<String>>,
pub packet_size: AtomicUsize,
pub name: String
}
impl Context {
pub fn new(config: &Config, args: &Args) -> Context {
pub fn new(config: &Config) -> Context {
Context {
chat: Arc::new(RwLock::new(None)),
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::<u16>())
)),
disable_formatting: args.disable_formatting,
disable_commands: args.disable_commands,
disable_hiding_ip: args.disable_ip_hiding,
update_time: config.update_time,
max_messages: config.max_messages,
enable_ip_viewing: args.enable_users_ip_viewing || config.enable_ip_viewing,
enable_auth: args.enable_auth || config.enable_auth,
enable_ssl: args.enable_ssl || config.enable_ssl,
enable_chunked: args.enable_chunked || config.enable_chunked,
registered: Arc::new(RwLock::new(None)),
config: Arc::new(RwLock::new(config.clone())),
sender: Arc::new(RwLock::new(None)),
messages: RwLock::new(Vec::new()),
packet_size: AtomicUsize::default(),
name: config.name.clone().expect("not implemented"), // TODO: ask for name
}
}
pub fn chat(&self) -> Arc<ChatContext> {
self.chat.read().unwrap().clone().unwrap()
pub fn config<T>(&self, map: fn (&Config) -> T) -> T {
map(&self.config.read().unwrap())
}
pub fn packet_size(&self) -> usize {
self.packet_size.load(Ordering::SeqCst)
}
pub fn messages(&self) -> Vec<String> {
self.messages.read().unwrap().clone()
}
pub fn update(&self, max_length: usize, messages: Vec<String>, packet_size: usize) {
self.packet_size.store(packet_size, Ordering::SeqCst);
let mut messages = messages;
if messages.len() > max_length {
messages.drain(max_length..);
}
*self.messages.write().unwrap() = messages;
}
pub fn append_and_store(&self, max_length: usize, messages: Vec<String>, packet_size: usize) {
self.packet_size.store(packet_size, Ordering::SeqCst);
self.append(max_length, messages);
}
pub fn append(&self, max_length: usize, messages: Vec<String>) {
self.messages.write().unwrap().append(&mut messages.clone());
if self.messages.read().unwrap().len() > max_length {
self.messages.write().unwrap().drain(max_length..);
}
}
}
#[macro_export]
macro_rules! connect_rac {
($ctx:ident) => { &mut connect(&$ctx.config(|o| o.host.clone()), $ctx.config(|o| o.ssl_enabled))? };
}

View File

@ -1,4 +1,4 @@
use std::sync::{Arc, RwLock, mpsc::{channel, Sender, Receiver}};
use std::sync::{Arc, mpsc::{channel, Receiver}};
use std::cell::RefCell;
use std::time::{Duration, SystemTime};
use std::error::Error;
@ -17,15 +17,9 @@ use gtk4::{
Button, Calendar, CssProvider, Entry, Fixed, Justification, Label, ListBox, Orientation, Overlay, Picture, ScrolledWindow, Settings
};
use crate::proto::{connect, read_messages};
use crate::{connect_rac, proto::{connect, read_messages}};
use super::{on_send_message, parse_message, set_chat, ChatStorage, ctx::Context};
pub struct ChatContext {
pub messages: Arc<ChatStorage>,
pub registered: Arc<RwLock<Option<String>>>,
pub sender: Sender<String>
}
use super::{on_send_message, parse_message, ctx::Context};
struct UiModel {
chat_box: GtkBox,
@ -37,31 +31,31 @@ thread_local!(
);
pub fn add_chat_message(ctx: Arc<Context>, message: String) {
let _ = ctx.chat().sender.send(message);
let _ = ctx.sender.read().unwrap().clone().unwrap().send(message);
}
pub fn print_message(ctx: Arc<Context>, message: String) -> Result<(), Box<dyn Error>> {
ctx.chat().messages.append(ctx.max_messages, vec![message.clone()]);
ctx.append(ctx.config(|o| o.max_messages), vec![message.clone()]);
add_chat_message(ctx.clone(), message);
Ok(())
}
pub fn recv_tick(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
match read_messages(
&mut connect(&ctx.host, ctx.enable_ssl)?,
ctx.max_messages,
ctx.chat().messages.packet_size(),
!ctx.enable_ssl,
ctx.enable_chunked
connect_rac!(ctx),
ctx.config(|o| o.max_messages),
ctx.packet_size(),
!ctx.config(|o| o.ssl_enabled),
ctx.config(|o| o.chunked_enabled)
) {
Ok(Some((messages, size))) => {
if ctx.enable_chunked {
ctx.chat().messages.append_and_store(ctx.max_messages, messages.clone(), size);
if ctx.config(|o| o.chunked_enabled) {
ctx.append_and_store(ctx.config(|o| o.max_messages), messages.clone(), size);
for msg in messages {
add_chat_message(ctx.clone(), msg.clone());
}
} else {
ctx.chat().messages.update(ctx.max_messages, messages.clone(), size);
ctx.update(ctx.config(|o| o.max_messages), messages.clone(), size);
for msg in messages {
add_chat_message(ctx.clone(), msg.clone());
}
@ -69,37 +63,15 @@ pub fn recv_tick(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
},
Err(e) => {
let msg = format!("Read messages error: {}", e.to_string()).to_string();
ctx.chat().messages.append(ctx.max_messages, vec![msg.clone()]);
ctx.append(ctx.config(|o| o.max_messages), vec![msg.clone()]);
add_chat_message(ctx.clone(), msg.clone());
}
_ => {}
}
thread::sleep(Duration::from_millis(ctx.update_time as u64));
thread::sleep(Duration::from_millis(ctx.config(|o| o.update_time) as u64));
Ok(())
}
pub fn ask_usize(name: impl ToString, default: usize) -> usize {
todo!()
}
pub fn ask_string(name: impl ToString, default: impl ToString + Clone) -> String {
todo!()
}
pub fn ask_string_option(name: impl ToString, default: impl ToString) -> Option<String> {
let default = default.to_string();
todo!()
}
pub fn ask_bool(name: impl ToString, default: bool) -> bool {
todo!()
}
pub fn show_message(title: impl ToString, message: impl ToString) {
todo!()
}
fn load_pixbuf(data: &[u8]) -> Pixbuf {
let loader = PixbufLoader::new();
loader.write(data).unwrap();
@ -384,7 +356,7 @@ fn build_ui(ctx: Arc<Context>, app: &Application) -> UiModel {
let window = ApplicationWindow::builder()
.application(app)
.title(format!("bRAC - Connected to {} as {}", &ctx.host, &ctx.name))
.title(format!("bRAC - Connected to {} as {}", ctx.config(|o| o.host.clone()), &ctx.name))
.default_width(500)
.default_height(500)
.resizable(false)
@ -418,11 +390,7 @@ fn build_ui(ctx: Arc<Context>, app: &Application) -> UiModel {
fn setup(ctx: Arc<Context>, ui: UiModel) {
let (sender, receiver) = channel();
set_chat(ctx.clone(), ChatContext {
messages: Arc::new(ChatStorage::new()),
registered: Arc::new(RwLock::new(None)),
sender
});
*ctx.sender.write().unwrap() = Some(Arc::new(sender));
thread::spawn({
let ctx = ctx.clone();
@ -494,7 +462,7 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String) {
if let Some((date, ip, content, nick)) = parse_message(message.clone()) {
if let Some(ip) = ip {
if ctx.enable_ip_viewing {
if ctx.config(|o| o.show_other_ip) {
let ip = Label::builder()
.label(ip)
.margin_end(10)

View File

@ -1,10 +1,10 @@
use std::{
error::Error,
sync::{atomic::{AtomicUsize, Ordering}, Arc, RwLock},
sync::Arc,
time::{SystemTime, UNIX_EPOCH}
};
use crate::proto::{register_user, send_message_auth};
use crate::{connect_rac, proto::{register_user, send_message_auth}};
use super::{
proto::{connect, read_messages, send_message, send_message_spoof_auth},
@ -17,7 +17,6 @@ use regex::Regex;
use ctx::Context;
pub use gui::{
ChatContext,
print_message,
run_main_loop
};
@ -41,50 +40,6 @@ pub mod config;
pub mod ctx;
pub struct ChatStorage {
messages: RwLock<Vec<String>>,
packet_size: AtomicUsize
}
impl ChatStorage {
pub fn new() -> Self {
ChatStorage {
messages: RwLock::new(Vec::new()),
packet_size: AtomicUsize::default()
}
}
pub fn packet_size(&self) -> usize {
self.packet_size.load(Ordering::SeqCst)
}
pub fn messages(&self) -> Vec<String> {
self.messages.read().unwrap().clone()
}
pub fn update(&self, max_length: usize, messages: Vec<String>, packet_size: usize) {
self.packet_size.store(packet_size, Ordering::SeqCst);
let mut messages = messages;
if messages.len() > max_length {
messages.drain(max_length..);
}
*self.messages.write().unwrap() = messages;
}
pub fn append_and_store(&self, max_length: usize, messages: Vec<String>, packet_size: usize) {
self.packet_size.store(packet_size, Ordering::SeqCst);
self.append(max_length, messages);
}
pub fn append(&self, max_length: usize, messages: Vec<String>) {
self.messages.write().unwrap().append(&mut messages.clone());
if self.messages.read().unwrap().len() > max_length {
self.messages.write().unwrap().drain(max_length..);
}
}
}
const HELP_MESSAGE: &str = "Help message:
/help - show help message
/register password - register user
@ -111,14 +66,14 @@ pub fn on_command(ctx: Arc<Context>, command: &str) -> Result<(), Box<dyn Error>
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")?;
send_message(connect_rac!(ctx), "\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))?;
send_message(connect_rac!(ctx), &("\r".to_string()+&msg))?;
}
} else if command == "help" {
add_message(ctx.clone(), HELP_MESSAGE)?;
@ -128,10 +83,10 @@ pub fn on_command(ctx: Arc<Context>, command: &str) -> Result<(), Box<dyn Error>
return Ok(())
};
match register_user(&mut connect(&ctx.host, ctx.enable_ssl)?, &ctx.name, pass) {
match register_user(connect_rac!(ctx), &ctx.name, pass) {
Ok(true) => {
add_message(ctx.clone(), "you was registered successfully bro")?;
*ctx.chat().registered.write().unwrap() = Some(pass.to_string());
*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))?
@ -143,22 +98,22 @@ pub fn on_command(ctx: Arc<Context>, command: &str) -> Result<(), Box<dyn Error>
};
add_message(ctx.clone(), "ye bro you was logged in")?;
*ctx.chat().registered.write().unwrap() = Some(pass.to_string());
*ctx.registered.write().unwrap() = Some(pass.to_string());
} else if command == "ping" {
let mut before = ctx.chat().messages.packet_size();
let mut before = ctx.packet_size();
let message = format!("Checking ping... {:X}", SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis());
send_message(&mut connect(&ctx.host, ctx.enable_ssl)?, &message)?;
send_message(connect_rac!(ctx), &message)?;
let start = SystemTime::now();
loop {
let data = read_messages(
&mut connect(&ctx.host, ctx.enable_ssl)?,
ctx.max_messages,
connect_rac!(ctx),
ctx.config(|o| o.max_messages),
before,
!ctx.enable_ssl,
ctx.enable_chunked
!ctx.config(|o| o.ssl_enabled),
ctx.config(|o| o.chunked_enabled)
).ok().flatten();
if let Some((data, size)) = data {
@ -182,16 +137,16 @@ pub fn on_command(ctx: Arc<Context>, command: &str) -> Result<(), Box<dyn Error>
Ok(())
}
pub fn prepare_message(context: Arc<Context>, message: &str) -> String {
pub fn prepare_message(ctx: Arc<Context>, message: &str) -> String {
format!("{}{}{}",
if !context.disable_hiding_ip {
if ctx.config(|o| o.hide_my_ip) {
"\r\x07"
} else {
""
},
message,
if !context.disable_hiding_ip {
let spaces = if context.enable_auth {
if !ctx.config(|o| o.hide_my_ip) {
let spaces = if ctx.config(|o| o.auth_enabled) {
39
} else {
54
@ -209,22 +164,22 @@ pub fn prepare_message(context: Arc<Context>, message: &str) -> String {
}
pub fn on_send_message(ctx: Arc<Context>, message: &str) -> Result<(), Box<dyn Error>> {
if message.starts_with("/") && !ctx.disable_commands {
if message.starts_with("/") && ctx.config(|o| o.commands_enabled) {
on_command(ctx.clone(), &message)?;
} else {
let message = prepare_message(
ctx.clone(),
&ctx.message_format
&ctx.config(|o| o.message_format.clone())
.replace("{name}", &ctx.name)
.replace("{text}", &message)
);
if let Some(password) = ctx.chat().registered.read().unwrap().clone() {
send_message_auth(&mut connect(&ctx.host, ctx.enable_ssl)?, &ctx.name, &password, &message)?;
} else if ctx.enable_auth {
send_message_spoof_auth(&mut connect(&ctx.host, ctx.enable_ssl)?, &message)?;
if let Some(password) = ctx.registered.read().unwrap().clone() {
send_message_auth(connect_rac!(ctx), &ctx.name, &password, &message)?;
} else if ctx.config(|o| o.auth_enabled) {
send_message_spoof_auth(connect_rac!(ctx), &message)?;
} else {
send_message(&mut connect(&ctx.host, ctx.enable_ssl)?, &message)?;
send_message(connect_rac!(ctx), &message)?;
}
}
@ -274,8 +229,4 @@ pub fn find_username_color(message: &str) -> Option<(String, String, String)> {
}
}
None
}
pub fn set_chat(ctx: Arc<Context>, chat: ChatContext) {
*ctx.chat.write().unwrap() = Some(Arc::new(chat));
}

View File

@ -1,7 +1,7 @@
use std::sync::Arc;
use bRAC::proto::{connect, read_messages, send_message};
use bRAC::chat::{config::{configure, get_config_path, load_config, Args}, ctx::Context, run_main_loop};
use bRAC::chat::{config::{get_config_path, load_config, Args}, ctx::Context, run_main_loop};
use clap::Parser;
@ -15,22 +15,16 @@ fn main() {
return;
}
if args.configure {
configure(config_path);
return;
}
let config = load_config(config_path);
let ctx = Arc::new(Context::new(&config, &args));
let mut config = load_config(config_path);
if args.read_messages {
let mut stream = connect(&ctx.host, ctx.enable_ssl).expect("Error reading message");
let mut stream = connect(&config.host, config.ssl_enabled).expect("Error reading message");
print!("{}", read_messages(
&mut stream,
ctx.max_messages,
config.max_messages,
0,
!ctx.enable_ssl,
!config.ssl_enabled,
false
)
.ok().flatten()
@ -39,12 +33,21 @@ fn main() {
}
if let Some(message) = &args.send_message {
send_message(&mut connect(&ctx.host, ctx.enable_ssl).expect("Error sending message"), message).expect("Error sending message");
let mut stream = connect(&config.host, config.ssl_enabled).expect("Error sending message");
send_message(
&mut stream,
message
).expect("Error sending message");
}
if args.send_message.is_some() || args.read_messages {
return;
}
args.patch_config(&mut config);
let ctx = Arc::new(Context::new(&config));
run_main_loop(ctx.clone());
}