mirror of
https://github.com/MeexReay/bRAC.git
synced 2025-05-06 13:38:04 +03:00
config refactor and some fixes like always
This commit is contained in:
parent
8dba6f2fd9
commit
592874680c
60
Cargo.lock
generated
60
Cargo.lock
generated
@ -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"
|
||||
|
@ -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"
|
@ -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
|
||||
```
|
||||
|
||||
|
12
flake.nix
12
flake.nix
@ -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);
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
@ -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))? };
|
||||
}
|
@ -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)
|
||||
|
@ -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));
|
||||
}
|
29
src/main.rs
29
src/main.rs
@ -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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user