mirror of
https://github.com/MeexReay/bRAC.git
synced 2025-06-24 10:52:58 +03:00
Compare commits
4 Commits
efc202153f
...
f615811f90
Author | SHA1 | Date | |
---|---|---|---|
f615811f90 | |||
374dab3951 | |||
0260206500 | |||
9c29d4e742 |
@ -11,7 +11,7 @@ better RAC client
|
|||||||
|
|
||||||
- gtk4 modern GUI
|
- gtk4 modern GUI
|
||||||
- RACv1.99.x and RACv2.0 compatible
|
- RACv1.99.x and RACv2.0 compatible
|
||||||
- WRAC compatible (can be enabled in the settings)
|
- WRAC compatible ([docs](docs/wrac.md))
|
||||||
- chat commands (type /help)
|
- chat commands (type /help)
|
||||||
- no ip and date visible for anyone
|
- no ip and date visible for anyone
|
||||||
- uses TOR proxy server by default (meex.lol:11234)
|
- uses TOR proxy server by default (meex.lol:11234)
|
||||||
@ -90,6 +90,7 @@ messages starting with a slash are sent to chat only if the `--disable-commands`
|
|||||||
## see also
|
## see also
|
||||||
|
|
||||||
- [RAC-Hub - all about RAC protocol](https://the-stratosphere-solutions.github.io/RAC-Hub/)
|
- [RAC-Hub - all about RAC protocol](https://the-stratosphere-solutions.github.io/RAC-Hub/)
|
||||||
|
- [WRAC protocol (v2.0)](docs/wrac.md)
|
||||||
- [RAC protocol (v2.0)](https://gitea.bedohswe.eu.org/pixtaded/crab#rac-protocol)
|
- [RAC protocol (v2.0)](https://gitea.bedohswe.eu.org/pixtaded/crab#rac-protocol)
|
||||||
- [CRAB - client & server for RAC](https://gitea.bedohswe.eu.org/pixtaded/crab)
|
- [CRAB - client & server for RAC](https://gitea.bedohswe.eu.org/pixtaded/crab)
|
||||||
- [Mefidroniy - client for RAC](https://github.com/OctoBanon-Main/mefedroniy-client)
|
- [Mefidroniy - client for RAC](https://github.com/OctoBanon-Main/mefedroniy-client)
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
# Cross-compile on Linux to Windows
|
|
||||||
|
|
||||||
## Install dev packages
|
|
||||||
|
|
||||||
on Nix:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nix-shell -p pkgsCross.mingwW64.stdenv.cc pkgsCross.mingwW64.windows.pthreads pkgsCross.mingwW64.gtk4
|
|
||||||
```
|
|
||||||
|
|
||||||
## Build
|
|
||||||
|
|
||||||
```bash
|
|
||||||
build build/windows-x86_64
|
|
||||||
```
|
|
84
docs/wrac.md
Normal file
84
docs/wrac.md
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# WRACv2.0 Protocol
|
||||||
|
|
||||||
|
Uses websocket for connections, and sends binary data only (works in packet-way manner)
|
||||||
|
|
||||||
|
Totally inherits all packets of RACv2, except of reading messages
|
||||||
|
|
||||||
|
## Sending messages
|
||||||
|
|
||||||
|
Client sends:
|
||||||
|
|
||||||
|
- Byte `0x01`
|
||||||
|
- Message text
|
||||||
|
|
||||||
|
## Sending authorized messages
|
||||||
|
|
||||||
|
Client sends:
|
||||||
|
|
||||||
|
- Byte `0x02`
|
||||||
|
- Username
|
||||||
|
- `\n`
|
||||||
|
- Password
|
||||||
|
- `\n`
|
||||||
|
- Message
|
||||||
|
|
||||||
|
Server sends:
|
||||||
|
|
||||||
|
- nothing if message was sent successfully
|
||||||
|
- `0x01` if the user does not exists
|
||||||
|
- `0x02` if the password is incorrect
|
||||||
|
|
||||||
|
## Registration users
|
||||||
|
|
||||||
|
Client sends:
|
||||||
|
|
||||||
|
- Byte `0x03`
|
||||||
|
- Username
|
||||||
|
- `\n`
|
||||||
|
- Password
|
||||||
|
|
||||||
|
Server sends:
|
||||||
|
|
||||||
|
- nothing if user was registered successfully
|
||||||
|
- `0x01` if the username is already taken
|
||||||
|
|
||||||
|
## Reading messages
|
||||||
|
|
||||||
|
### Getting message length
|
||||||
|
|
||||||
|
Client sends:
|
||||||
|
|
||||||
|
- Byte `0x00`
|
||||||
|
|
||||||
|
Server sends:
|
||||||
|
|
||||||
|
- Size of all messages in ASCII (data_size)
|
||||||
|
|
||||||
|
### Normal reading
|
||||||
|
|
||||||
|
This packet is independent from getting message length packet.
|
||||||
|
|
||||||
|
Client sends:
|
||||||
|
|
||||||
|
- Byte `0x00`
|
||||||
|
- Byte `0x01`
|
||||||
|
|
||||||
|
Server sends:
|
||||||
|
|
||||||
|
- All messages
|
||||||
|
|
||||||
|
### Chunked reading
|
||||||
|
|
||||||
|
This packet is independent from getting message length packet.
|
||||||
|
|
||||||
|
Client sends:
|
||||||
|
|
||||||
|
- Byte `0x00`
|
||||||
|
- Byte `0x02`
|
||||||
|
- Size of messages you have in ASCII (last_size)
|
||||||
|
|
||||||
|
Server sends:
|
||||||
|
|
||||||
|
- All new messages
|
||||||
|
|
||||||
|
*for example: if you want to read last N bytes, last_size = data_size - N*
|
@ -27,11 +27,9 @@ pub struct Config {
|
|||||||
#[serde(default = "default_true")] pub hide_my_ip: bool,
|
#[serde(default = "default_true")] pub hide_my_ip: bool,
|
||||||
#[serde(default)] pub show_other_ip: bool,
|
#[serde(default)] pub show_other_ip: bool,
|
||||||
#[serde(default)] pub auth_enabled: bool,
|
#[serde(default)] pub auth_enabled: bool,
|
||||||
#[serde(default)] pub ssl_enabled: bool,
|
|
||||||
#[serde(default = "default_true")] pub chunked_enabled: bool,
|
#[serde(default = "default_true")] pub chunked_enabled: bool,
|
||||||
#[serde(default = "default_true")] pub formatting_enabled: bool,
|
#[serde(default = "default_true")] pub formatting_enabled: bool,
|
||||||
#[serde(default = "default_true")] pub commands_enabled: bool,
|
#[serde(default = "default_true")] pub commands_enabled: bool,
|
||||||
#[serde(default)] pub wrac_enabled: bool,
|
|
||||||
#[serde(default)] pub proxy: Option<String>,
|
#[serde(default)] pub proxy: Option<String>,
|
||||||
#[serde(default = "default_true")] pub notifications_enabled: bool,
|
#[serde(default = "default_true")] pub notifications_enabled: bool,
|
||||||
#[serde(default)] pub debug_logs: bool,
|
#[serde(default)] pub debug_logs: bool,
|
||||||
@ -121,13 +119,11 @@ pub struct Args {
|
|||||||
#[arg(long)] pub hide_my_ip: Option<bool>,
|
#[arg(long)] pub hide_my_ip: Option<bool>,
|
||||||
#[arg(long)] pub show_other_ip: Option<bool>,
|
#[arg(long)] pub show_other_ip: Option<bool>,
|
||||||
#[arg(long)] pub auth_enabled:Option <bool>,
|
#[arg(long)] pub auth_enabled:Option <bool>,
|
||||||
#[arg(long)] pub ssl_enabled: Option<bool>,
|
|
||||||
#[arg(long)] pub remove_gui_shit: Option<bool>,
|
#[arg(long)] pub remove_gui_shit: Option<bool>,
|
||||||
#[arg(long)] pub chunked_enabled: Option<bool>,
|
#[arg(long)] pub chunked_enabled: Option<bool>,
|
||||||
#[arg(long)] pub formatting_enabled: Option<bool>,
|
#[arg(long)] pub formatting_enabled: Option<bool>,
|
||||||
#[arg(long)] pub commands_enabled: Option<bool>,
|
#[arg(long)] pub commands_enabled: Option<bool>,
|
||||||
#[arg(long)] pub notifications_enabled: Option<bool>,
|
#[arg(long)] pub notifications_enabled: Option<bool>,
|
||||||
#[arg(long)] pub wrac_enabled: Option<bool>,
|
|
||||||
#[arg(long)] pub proxy: Option<String>,
|
#[arg(long)] pub proxy: Option<String>,
|
||||||
#[arg(long)] pub debug_logs: bool,
|
#[arg(long)] pub debug_logs: bool,
|
||||||
}
|
}
|
||||||
@ -146,12 +142,10 @@ impl Args {
|
|||||||
if let Some(v) = self.show_other_ip { config.show_other_ip = v }
|
if let Some(v) = self.show_other_ip { config.show_other_ip = v }
|
||||||
if let Some(v) = self.remove_gui_shit { config.remove_gui_shit = v }
|
if let Some(v) = self.remove_gui_shit { config.remove_gui_shit = v }
|
||||||
if let Some(v) = self.auth_enabled { config.auth_enabled = v }
|
if let Some(v) = self.auth_enabled { config.auth_enabled = v }
|
||||||
if let Some(v) = self.ssl_enabled { config.ssl_enabled = v }
|
|
||||||
if let Some(v) = self.chunked_enabled { config.chunked_enabled = v }
|
if let Some(v) = self.chunked_enabled { config.chunked_enabled = v }
|
||||||
if let Some(v) = self.formatting_enabled { config.formatting_enabled = v }
|
if let Some(v) = self.formatting_enabled { config.formatting_enabled = v }
|
||||||
if let Some(v) = self.commands_enabled { config.commands_enabled = v }
|
if let Some(v) = self.commands_enabled { config.commands_enabled = v }
|
||||||
if let Some(v) = self.notifications_enabled { config.notifications_enabled = v }
|
if let Some(v) = self.notifications_enabled { config.notifications_enabled = v }
|
||||||
if let Some(v) = self.wrac_enabled { config.wrac_enabled = v }
|
|
||||||
if self.debug_logs { config.debug_logs = true }
|
if self.debug_logs { config.debug_logs = true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use super::config::Config;
|
|||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub registered: RwLock<Option<String>>,
|
pub registered: RwLock<Option<String>>,
|
||||||
pub config: RwLock<Config>,
|
pub config: RwLock<Config>,
|
||||||
pub sender: RwLock<Option<Arc<Sender<(String, bool)>>>>,
|
pub sender: RwLock<Option<Arc<Sender<(Vec<String>, bool)>>>>,
|
||||||
pub messages: RwLock<Vec<String>>,
|
pub messages: RwLock<Vec<String>>,
|
||||||
pub packet_size: AtomicUsize,
|
pub packet_size: AtomicUsize,
|
||||||
pub name: RwLock<String>,
|
pub name: RwLock<String>,
|
||||||
@ -78,9 +78,7 @@ macro_rules! connect_rac {
|
|||||||
($ctx:ident) => {
|
($ctx:ident) => {
|
||||||
&mut connect(
|
&mut connect(
|
||||||
&$ctx.config(|o| o.host.clone()),
|
&$ctx.config(|o| o.host.clone()),
|
||||||
$ctx.config(|o| o.ssl_enabled),
|
$ctx.config(|o| o.proxy.clone())
|
||||||
$ctx.config(|o| o.proxy.clone()),
|
|
||||||
$ctx.config(|o| o.wrac_enabled)
|
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
}
|
}
|
113
src/chat/gui.rs
113
src/chat/gui.rs
@ -1,4 +1,4 @@
|
|||||||
use std::sync::{atomic::Ordering, mpsc::{channel, Receiver}, Arc, RwLock};
|
use std::sync::{atomic::Ordering, mpsc::channel, Arc, RwLock};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
@ -6,7 +6,7 @@ use std::error::Error;
|
|||||||
|
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
|
|
||||||
use gtk4 as gtk;
|
use gtk4::{self as gtk};
|
||||||
|
|
||||||
use gtk::gdk_pixbuf::{Pixbuf, PixbufAnimation, PixbufLoader};
|
use gtk::gdk_pixbuf::{Pixbuf, PixbufAnimation, PixbufLoader};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
@ -27,9 +27,7 @@ use gtk::{
|
|||||||
Justification, Label, ListBox, Orientation, Overlay, Picture, ScrolledWindow, Settings, Window
|
Justification, Label, ListBox, Orientation, Overlay, Picture, ScrolledWindow, Settings, Window
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{chat::config::{default_konata_size, default_oof_update_time}, proto::parse_rac_url};
|
use super::{config::{default_max_messages, default_update_time, default_konata_size, default_oof_update_time, get_config_path, save_config, Config},
|
||||||
|
|
||||||
use super::{config::{default_max_messages, default_update_time, get_config_path, save_config, Config},
|
|
||||||
ctx::Context, on_send_message, parse_message, print_message, recv_tick, sanitize_message, SERVER_LIST};
|
ctx::Context, on_send_message, parse_message, print_message, recv_tick, sanitize_message, SERVER_LIST};
|
||||||
|
|
||||||
struct UiModel {
|
struct UiModel {
|
||||||
@ -45,15 +43,15 @@ struct UiModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
thread_local!(
|
thread_local!(
|
||||||
static GLOBAL: RefCell<Option<(UiModel, Receiver<String>)>> = RefCell::new(None);
|
static GLOBAL: RefCell<Option<UiModel>> = RefCell::new(None);
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn clear_chat_messages(ctx: Arc<Context>, message: String) {
|
pub fn clear_chat_messages(ctx: Arc<Context>, messages: Vec<String>) {
|
||||||
let _ = ctx.sender.read().unwrap().clone().unwrap().send((message, true));
|
let _ = ctx.sender.read().unwrap().clone().unwrap().send((messages, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_chat_message(ctx: Arc<Context>, message: String) {
|
pub fn add_chat_messages(ctx: Arc<Context>, messages: Vec<String>) {
|
||||||
let _ = ctx.sender.read().unwrap().clone().unwrap().send((message, false));
|
let _ = ctx.sender.read().unwrap().clone().unwrap().send((messages, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_pixbuf(data: &[u8]) -> Result<Pixbuf, Box<dyn Error>> {
|
fn load_pixbuf(data: &[u8]) -> Result<Pixbuf, Box<dyn Error>> {
|
||||||
@ -159,25 +157,33 @@ fn open_settings(ctx: Arc<Context>, app: &Application) {
|
|||||||
vbox.set_margin_start(15);
|
vbox.set_margin_start(15);
|
||||||
vbox.set_margin_end(15);
|
vbox.set_margin_end(15);
|
||||||
|
|
||||||
let host_entry = gui_entry_setting!("Host", host, ctx, vbox);
|
let settings_vbox = GtkBox::new(Orientation::Vertical, 10);
|
||||||
let name_entry = gui_option_entry_setting!("Name", name, ctx, vbox);
|
|
||||||
let message_format_entry = gui_entry_setting!("Message Format", message_format, ctx, vbox);
|
let host_entry = gui_entry_setting!("Host", host, ctx, settings_vbox);
|
||||||
let proxy_entry = gui_option_entry_setting!("Socks5 proxy", proxy, ctx, vbox);
|
let name_entry = gui_option_entry_setting!("Name", name, ctx, settings_vbox);
|
||||||
let update_time_entry = gui_usize_entry_setting!("Update Time", update_time, ctx, vbox);
|
let message_format_entry = gui_entry_setting!("Message Format", message_format, ctx, settings_vbox);
|
||||||
let oof_update_time_entry = gui_usize_entry_setting!("Out-of-focus Update Time", oof_update_time, ctx, vbox);
|
let proxy_entry = gui_option_entry_setting!("Socks5 proxy", proxy, ctx, settings_vbox);
|
||||||
let max_messages_entry = gui_usize_entry_setting!("Max Messages", max_messages, ctx, vbox);
|
let update_time_entry = gui_usize_entry_setting!("Update Time", update_time, ctx, settings_vbox);
|
||||||
let hide_my_ip_entry = gui_checkbox_setting!("Hide My IP", hide_my_ip, ctx, vbox);
|
let oof_update_time_entry = gui_usize_entry_setting!("Out-of-focus Update Time", oof_update_time, ctx, settings_vbox);
|
||||||
let show_other_ip_entry = gui_checkbox_setting!("Show Other IP", show_other_ip, ctx, vbox);
|
let max_messages_entry = gui_usize_entry_setting!("Max Messages", max_messages, ctx, settings_vbox);
|
||||||
let auth_enabled_entry = gui_checkbox_setting!("Fake Auth Enabled", auth_enabled, ctx, vbox);
|
let hide_my_ip_entry = gui_checkbox_setting!("Hide My IP", hide_my_ip, ctx, settings_vbox);
|
||||||
let ssl_enabled_entry = gui_checkbox_setting!("SSL Enabled", ssl_enabled, ctx, vbox);
|
let show_other_ip_entry = gui_checkbox_setting!("Show Other IP", show_other_ip, ctx, settings_vbox);
|
||||||
let wrac_enabled_entry = gui_checkbox_setting!("WRAC Enabled", wrac_enabled, ctx, vbox);
|
let auth_enabled_entry = gui_checkbox_setting!("Fake Auth Enabled", auth_enabled, ctx, settings_vbox);
|
||||||
let chunked_enabled_entry = gui_checkbox_setting!("Chunked Enabled", chunked_enabled, ctx, vbox);
|
let chunked_enabled_entry = gui_checkbox_setting!("Chunked Enabled", chunked_enabled, ctx, settings_vbox);
|
||||||
let formatting_enabled_entry = gui_checkbox_setting!("Formatting Enabled", formatting_enabled, ctx, vbox);
|
let formatting_enabled_entry = gui_checkbox_setting!("Formatting Enabled", formatting_enabled, ctx, settings_vbox);
|
||||||
let commands_enabled_entry = gui_checkbox_setting!("Commands Enabled", commands_enabled, ctx, vbox);
|
let commands_enabled_entry = gui_checkbox_setting!("Commands Enabled", commands_enabled, ctx, settings_vbox);
|
||||||
let notifications_enabled_entry = gui_checkbox_setting!("Notifications Enabled", notifications_enabled, ctx, vbox);
|
let notifications_enabled_entry = gui_checkbox_setting!("Notifications Enabled", notifications_enabled, ctx, settings_vbox);
|
||||||
let debug_logs_entry = gui_checkbox_setting!("Debug Logs", debug_logs, ctx, vbox);
|
let debug_logs_entry = gui_checkbox_setting!("Debug Logs", debug_logs, ctx, settings_vbox);
|
||||||
let konata_size_entry = gui_usize_entry_setting!("Konata Size", konata_size, ctx, vbox);
|
let konata_size_entry = gui_usize_entry_setting!("Konata Size", konata_size, ctx, settings_vbox);
|
||||||
let remove_gui_shit_entry = gui_checkbox_setting!("Remove Gui Shit", remove_gui_shit, ctx, vbox);
|
let remove_gui_shit_entry = gui_checkbox_setting!("Remove Gui Shit", remove_gui_shit, ctx, settings_vbox);
|
||||||
|
|
||||||
|
let scrollable = ScrolledWindow::builder()
|
||||||
|
.child(&settings_vbox)
|
||||||
|
.vexpand(true)
|
||||||
|
.hexpand(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
vbox.append(&scrollable);
|
||||||
|
|
||||||
let save_button = Button::builder()
|
let save_button = Button::builder()
|
||||||
.label("Save")
|
.label("Save")
|
||||||
@ -195,12 +201,10 @@ fn open_settings(ctx: Arc<Context>, app: &Application) {
|
|||||||
#[weak] hide_my_ip_entry,
|
#[weak] hide_my_ip_entry,
|
||||||
#[weak] show_other_ip_entry,
|
#[weak] show_other_ip_entry,
|
||||||
#[weak] auth_enabled_entry,
|
#[weak] auth_enabled_entry,
|
||||||
#[weak] ssl_enabled_entry,
|
|
||||||
#[weak] chunked_enabled_entry,
|
#[weak] chunked_enabled_entry,
|
||||||
#[weak] formatting_enabled_entry,
|
#[weak] formatting_enabled_entry,
|
||||||
#[weak] commands_enabled_entry,
|
#[weak] commands_enabled_entry,
|
||||||
#[weak] notifications_enabled_entry,
|
#[weak] notifications_enabled_entry,
|
||||||
#[weak] wrac_enabled_entry,
|
|
||||||
#[weak] proxy_entry,
|
#[weak] proxy_entry,
|
||||||
#[weak] debug_logs_entry,
|
#[weak] debug_logs_entry,
|
||||||
#[weak] oof_update_time_entry,
|
#[weak] oof_update_time_entry,
|
||||||
@ -267,8 +271,6 @@ fn open_settings(ctx: Arc<Context>, app: &Application) {
|
|||||||
remove_gui_shit: remove_gui_shit_entry.is_active(),
|
remove_gui_shit: remove_gui_shit_entry.is_active(),
|
||||||
show_other_ip: show_other_ip_entry.is_active(),
|
show_other_ip: show_other_ip_entry.is_active(),
|
||||||
auth_enabled: auth_enabled_entry.is_active(),
|
auth_enabled: auth_enabled_entry.is_active(),
|
||||||
ssl_enabled: ssl_enabled_entry.is_active(),
|
|
||||||
wrac_enabled: wrac_enabled_entry.is_active(),
|
|
||||||
chunked_enabled: chunked_enabled_entry.is_active(),
|
chunked_enabled: chunked_enabled_entry.is_active(),
|
||||||
formatting_enabled: formatting_enabled_entry.is_active(),
|
formatting_enabled: formatting_enabled_entry.is_active(),
|
||||||
commands_enabled: commands_enabled_entry.is_active(),
|
commands_enabled: commands_enabled_entry.is_active(),
|
||||||
@ -305,8 +307,6 @@ fn open_settings(ctx: Arc<Context>, app: &Application) {
|
|||||||
#[weak] hide_my_ip_entry,
|
#[weak] hide_my_ip_entry,
|
||||||
#[weak] show_other_ip_entry,
|
#[weak] show_other_ip_entry,
|
||||||
#[weak] auth_enabled_entry,
|
#[weak] auth_enabled_entry,
|
||||||
#[weak] ssl_enabled_entry,
|
|
||||||
#[weak] wrac_enabled_entry,
|
|
||||||
#[weak] chunked_enabled_entry,
|
#[weak] chunked_enabled_entry,
|
||||||
#[weak] formatting_enabled_entry,
|
#[weak] formatting_enabled_entry,
|
||||||
#[weak] commands_enabled_entry,
|
#[weak] commands_enabled_entry,
|
||||||
@ -325,20 +325,18 @@ fn open_settings(ctx: Arc<Context>, app: &Application) {
|
|||||||
hide_my_ip_entry.set_active(config.hide_my_ip);
|
hide_my_ip_entry.set_active(config.hide_my_ip);
|
||||||
show_other_ip_entry.set_active(config.show_other_ip);
|
show_other_ip_entry.set_active(config.show_other_ip);
|
||||||
auth_enabled_entry.set_active(config.auth_enabled);
|
auth_enabled_entry.set_active(config.auth_enabled);
|
||||||
ssl_enabled_entry.set_active(config.ssl_enabled);
|
|
||||||
wrac_enabled_entry.set_active(config.wrac_enabled);
|
|
||||||
chunked_enabled_entry.set_active(config.chunked_enabled);
|
chunked_enabled_entry.set_active(config.chunked_enabled);
|
||||||
formatting_enabled_entry.set_active(config.formatting_enabled);
|
formatting_enabled_entry.set_active(config.formatting_enabled);
|
||||||
commands_enabled_entry.set_active(config.commands_enabled);
|
commands_enabled_entry.set_active(config.commands_enabled);
|
||||||
notifications_enabled_entry.set_active(config.notifications_enabled);
|
notifications_enabled_entry.set_active(config.notifications_enabled);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
let window = Window::builder()
|
let window = Window::builder()
|
||||||
.application(app)
|
.application(app)
|
||||||
.title("Settings")
|
.title("Settings")
|
||||||
.default_width(400)
|
.default_width(400)
|
||||||
.default_height(500)
|
.default_height(500)
|
||||||
|
.resizable(true)
|
||||||
.decorated(true)
|
.decorated(true)
|
||||||
.child(&vbox)
|
.child(&vbox)
|
||||||
.build();
|
.build();
|
||||||
@ -397,7 +395,7 @@ fn build_menu(ctx: Arc<Context>, app: &Application) {
|
|||||||
move |_, _, _| {
|
move |_, _, _| {
|
||||||
AboutDialog::builder()
|
AboutDialog::builder()
|
||||||
.application(&app)
|
.application(&app)
|
||||||
.authors(["TheMixRay", "MeexReay"])
|
.authors(["MeexReay"])
|
||||||
.license(" DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
.license(" DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
Version 2, December 2004
|
Version 2, December 2004
|
||||||
|
|
||||||
@ -470,11 +468,7 @@ fn build_ui(ctx: Arc<Context>, app: &Application) -> UiModel {
|
|||||||
#[weak] ctx,
|
#[weak] ctx,
|
||||||
move |_, _, _, _| {
|
move |_, _, _, _| {
|
||||||
let mut config = ctx.config.read().unwrap().clone();
|
let mut config = ctx.config.read().unwrap().clone();
|
||||||
if let Some((_, ssl, wrac)) = parse_rac_url(&url) {
|
config.host = url.clone();
|
||||||
config.host = url.clone();
|
|
||||||
config.wrac_enabled = wrac;
|
|
||||||
config.ssl_enabled = ssl;
|
|
||||||
}
|
|
||||||
ctx.set_config(&config);
|
ctx.set_config(&config);
|
||||||
save_config(get_config_path(), &config);
|
save_config(get_config_path(), &config);
|
||||||
}
|
}
|
||||||
@ -609,7 +603,7 @@ fn build_ui(ctx: Arc<Context>, app: &Application) -> UiModel {
|
|||||||
if let Err(e) = on_send_message(ctx.clone(), &text_entry.text()) {
|
if let Err(e) = on_send_message(ctx.clone(), &text_entry.text()) {
|
||||||
if ctx.config(|o| o.debug_logs) {
|
if ctx.config(|o| o.debug_logs) {
|
||||||
let msg = format!("Send message error: {}", e.to_string()).to_string();
|
let msg = format!("Send message error: {}", e.to_string()).to_string();
|
||||||
add_chat_message(ctx.clone(), msg);
|
add_chat_messages(ctx.clone(), vec![msg]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -630,7 +624,7 @@ fn build_ui(ctx: Arc<Context>, app: &Application) -> UiModel {
|
|||||||
if let Err(e) = on_send_message(ctx.clone(), &text_entry.text()) {
|
if let Err(e) = on_send_message(ctx.clone(), &text_entry.text()) {
|
||||||
if ctx.config(|o| o.debug_logs) {
|
if ctx.config(|o| o.debug_logs) {
|
||||||
let msg = format!("Send message error: {}", e.to_string()).to_string();
|
let msg = format!("Send message error: {}", e.to_string()).to_string();
|
||||||
add_chat_message(ctx.clone(), msg);
|
add_chat_messages(ctx.clone(), vec![msg]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -697,8 +691,6 @@ fn setup(_: &Application, ctx: Arc<Context>, ui: UiModel) {
|
|||||||
*ctx.sender.write().unwrap() = Some(Arc::new(sender));
|
*ctx.sender.write().unwrap() = Some(Arc::new(sender));
|
||||||
|
|
||||||
run_recv_loop(ctx.clone());
|
run_recv_loop(ctx.clone());
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
|
||||||
|
|
||||||
ui.window.connect_notify(Some("is-active"), {
|
ui.window.connect_notify(Some("is-active"), {
|
||||||
let ctx = ctx.clone();
|
let ctx = ctx.clone();
|
||||||
@ -709,10 +701,15 @@ fn setup(_: &Application, ctx: Arc<Context>, ui: UiModel) {
|
|||||||
ctx.is_focused.store(is_focused, Ordering::SeqCst);
|
ctx.is_focused.store(is_focused, Ordering::SeqCst);
|
||||||
|
|
||||||
if is_focused {
|
if is_focused {
|
||||||
make_recv_tick(ctx.clone());
|
thread::spawn({
|
||||||
|
let ctx = ctx.clone();
|
||||||
|
move || {
|
||||||
|
make_recv_tick(ctx.clone());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
GLOBAL.with(|global| {
|
GLOBAL.with(|global| {
|
||||||
if let Some((ui, _)) = &*global.borrow() {
|
if let Some(ui) = &*global.borrow() {
|
||||||
#[cfg(feature = "libnotify")]
|
#[cfg(feature = "libnotify")]
|
||||||
for i in ui.notifications.read().unwrap().clone() {
|
for i in ui.notifications.read().unwrap().clone() {
|
||||||
i.close().expect("libnotify close error");
|
i.close().expect("libnotify close error");
|
||||||
@ -728,25 +725,25 @@ fn setup(_: &Application, ctx: Arc<Context>, ui: UiModel) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
GLOBAL.with(|global| {
|
GLOBAL.with(|global| {
|
||||||
*global.borrow_mut() = Some((ui, rx));
|
*global.borrow_mut() = Some(ui);
|
||||||
});
|
});
|
||||||
|
|
||||||
thread::spawn({
|
thread::spawn({
|
||||||
let ctx = ctx.clone();
|
let ctx = ctx.clone();
|
||||||
move || {
|
move || {
|
||||||
while let Ok((message, clear)) = receiver.recv() {
|
while let Ok((messages, clear)) = receiver.recv() {
|
||||||
let _ = tx.send(message.clone());
|
|
||||||
let ctx = ctx.clone();
|
let ctx = ctx.clone();
|
||||||
timeout_add_once(Duration::ZERO, move || {
|
timeout_add_once(Duration::ZERO, move || {
|
||||||
GLOBAL.with(|global| {
|
GLOBAL.with(|global| {
|
||||||
if let Some((ui, rx)) = &*global.borrow() {
|
if let Some(ui) = &*global.borrow() {
|
||||||
if clear {
|
if clear {
|
||||||
while let Some(row) = ui.chat_box.last_child() {
|
while let Some(row) = ui.chat_box.last_child() {
|
||||||
ui.chat_box.remove(&row);
|
ui.chat_box.remove(&row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let message: String = rx.recv().unwrap();
|
for message in messages.iter() {
|
||||||
on_add_message(ctx.clone(), &ui, message, !clear);
|
on_add_message(ctx.clone(), &ui, message.to_string(), !clear);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -815,7 +812,7 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String, notify: bool
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: cache these colors maybe??
|
// TODO: softcode these colors
|
||||||
|
|
||||||
let (ip_color, date_color, text_color) = if ui.is_dark_theme {
|
let (ip_color, date_color, text_color) = if ui.is_dark_theme {
|
||||||
(
|
(
|
||||||
@ -887,7 +884,7 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String, notify: bool
|
|||||||
|
|
||||||
timeout_add_local_once(Duration::from_millis(1000), move || {
|
timeout_add_local_once(Duration::from_millis(1000), move || {
|
||||||
GLOBAL.with(|global| {
|
GLOBAL.with(|global| {
|
||||||
if let Some((ui, _)) = &*global.borrow() {
|
if let Some(ui) = &*global.borrow() {
|
||||||
let o = &ui.chat_scrolled;
|
let o = &ui.chat_scrolled;
|
||||||
o.vadjustment().set_value(o.vadjustment().upper() - o.vadjustment().page_size());
|
o.vadjustment().set_value(o.vadjustment().upper() - o.vadjustment().page_size());
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use crate::connect_rac;
|
|||||||
|
|
||||||
use super::proto::{connect, read_messages, send_message, send_message_spoof_auth, register_user, send_message_auth};
|
use super::proto::{connect, read_messages, send_message, send_message_spoof_auth, register_user, send_message_auth};
|
||||||
|
|
||||||
use gui::{add_chat_message, clear_chat_messages};
|
use gui::{add_chat_messages, clear_chat_messages};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ pub fn on_command(ctx: Arc<Context>, command: &str) -> Result<(), Box<dyn Error>
|
|||||||
return Ok(())
|
return Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
match register_user(connect_rac!(ctx), &ctx.name(), pass, !ctx.config(|o| o.ssl_enabled)) {
|
match register_user(connect_rac!(ctx), &ctx.name(), pass) {
|
||||||
Ok(true) => {
|
Ok(true) => {
|
||||||
add_message(ctx.clone(), "you was registered successfully bro")?;
|
add_message(ctx.clone(), "you was registered successfully bro")?;
|
||||||
*ctx.registered.write().unwrap() = Some(pass.to_string());
|
*ctx.registered.write().unwrap() = Some(pass.to_string());
|
||||||
@ -118,7 +118,6 @@ pub fn on_command(ctx: Arc<Context>, command: &str) -> Result<(), Box<dyn Error>
|
|||||||
connect_rac!(ctx),
|
connect_rac!(ctx),
|
||||||
ctx.config(|o| o.max_messages),
|
ctx.config(|o| o.max_messages),
|
||||||
before,
|
before,
|
||||||
!ctx.config(|o| o.ssl_enabled),
|
|
||||||
ctx.config(|o| o.chunked_enabled)
|
ctx.config(|o| o.chunked_enabled)
|
||||||
).ok().flatten();
|
).ok().flatten();
|
||||||
|
|
||||||
@ -171,7 +170,7 @@ pub fn prepare_message(ctx: Arc<Context>, message: &str) -> String {
|
|||||||
|
|
||||||
pub fn print_message(ctx: Arc<Context>, message: String) -> Result<(), Box<dyn Error>> {
|
pub fn print_message(ctx: Arc<Context>, message: String) -> Result<(), Box<dyn Error>> {
|
||||||
ctx.add_message(ctx.config(|o| o.max_messages), vec![message.clone()]);
|
ctx.add_message(ctx.config(|o| o.max_messages), vec![message.clone()]);
|
||||||
add_chat_message(ctx.clone(), message);
|
add_chat_messages(ctx.clone(), vec![message]);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +181,6 @@ pub fn recv_tick(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
connect_rac!(ctx),
|
connect_rac!(ctx),
|
||||||
ctx.config(|o| o.max_messages),
|
ctx.config(|o| o.max_messages),
|
||||||
ctx.packet_size(),
|
ctx.packet_size(),
|
||||||
!ctx.config(|o| o.ssl_enabled),
|
|
||||||
ctx.config(|o| o.chunked_enabled)
|
ctx.config(|o| o.chunked_enabled)
|
||||||
) {
|
) {
|
||||||
Ok(Some((messages, size))) => {
|
Ok(Some((messages, size))) => {
|
||||||
@ -190,33 +188,19 @@ pub fn recv_tick(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
ctx.add_messages_packet(ctx.config(|o| o.max_messages), messages.clone(), size);
|
ctx.add_messages_packet(ctx.config(|o| o.max_messages), messages.clone(), size);
|
||||||
if last_size == 0 {
|
if last_size == 0 {
|
||||||
if messages.len() >= 1 {
|
if messages.len() >= 1 {
|
||||||
clear_chat_messages(ctx.clone(), messages[0].clone());
|
clear_chat_messages(ctx.clone(), messages);
|
||||||
if messages.len() >= 2 {
|
|
||||||
for msg in &messages[1..] {
|
|
||||||
add_chat_message(ctx.clone(), msg.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for msg in messages {
|
add_chat_messages(ctx.clone(), messages);
|
||||||
add_chat_message(ctx.clone(), msg.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.put_messages_packet(ctx.config(|o| o.max_messages), messages.clone(), size);
|
ctx.put_messages_packet(ctx.config(|o| o.max_messages), messages.clone(), size);
|
||||||
if messages.len() >= 1 {
|
clear_chat_messages(ctx.clone(), messages);
|
||||||
clear_chat_messages(ctx.clone(), messages[0].clone());
|
|
||||||
if messages.len() >= 2 {
|
|
||||||
for msg in &messages[1..] {
|
|
||||||
add_chat_message(ctx.clone(), msg.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if ctx.config(|o| o.debug_logs) {
|
if ctx.config(|o| o.debug_logs) {
|
||||||
add_chat_message(ctx.clone(), format!("Read messages error: {}", e.to_string()));
|
add_chat_messages(ctx.clone(), vec![format!("Read messages error: {}", e.to_string())]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -237,9 +221,9 @@ pub fn on_send_message(ctx: Arc<Context>, message: &str) -> Result<(), Box<dyn E
|
|||||||
);
|
);
|
||||||
|
|
||||||
if let Some(password) = ctx.registered.read().unwrap().clone() {
|
if let Some(password) = ctx.registered.read().unwrap().clone() {
|
||||||
send_message_auth(connect_rac!(ctx), &ctx.name(), &password, &message, !ctx.config(|o| o.ssl_enabled))?;
|
send_message_auth(connect_rac!(ctx), &ctx.name(), &password, &message)?;
|
||||||
} else if ctx.config(|o| o.auth_enabled) {
|
} else if ctx.config(|o| o.auth_enabled) {
|
||||||
send_message_spoof_auth(connect_rac!(ctx), &message, !ctx.config(|o| o.ssl_enabled))?;
|
send_message_spoof_auth(connect_rac!(ctx), &message)?;
|
||||||
} else {
|
} else {
|
||||||
send_message(connect_rac!(ctx), &message)?;
|
send_message(connect_rac!(ctx), &message)?;
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,12 @@ fn main() {
|
|||||||
let mut config = load_config(config_path);
|
let mut config = load_config(config_path);
|
||||||
|
|
||||||
if args.read_messages {
|
if args.read_messages {
|
||||||
let mut stream = connect(&config.host, config.ssl_enabled, config.proxy.clone(), config.wrac_enabled).expect("Error reading message");
|
let mut stream = connect(&config.host, config.proxy.clone()).expect("Error reading message");
|
||||||
|
|
||||||
print!("{}", read_messages(
|
print!("{}", read_messages(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
config.max_messages,
|
config.max_messages,
|
||||||
0,
|
0,
|
||||||
!config.ssl_enabled,
|
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
.ok().flatten()
|
.ok().flatten()
|
||||||
@ -35,7 +34,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(message) = &args.send_message {
|
if let Some(message) = &args.send_message {
|
||||||
let mut stream = connect(&config.host, config.ssl_enabled, config.proxy.clone(), config.wrac_enabled).expect("Error sending message");
|
let mut stream = connect(&config.host, config.proxy.clone()).expect("Error sending message");
|
||||||
|
|
||||||
send_message(
|
send_message(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
|
@ -114,9 +114,8 @@ pub fn parse_rac_url(url: &str) -> Option<(String, bool, bool)> {
|
|||||||
/// ssl - wrap with ssl client, write false if you dont know what it is
|
/// ssl - wrap with ssl client, write false if you dont know what it is
|
||||||
/// proxy - socks5 proxy (host, (user, pass))
|
/// proxy - socks5 proxy (host, (user, pass))
|
||||||
/// wrac - to use wrac protocol
|
/// wrac - to use wrac protocol
|
||||||
pub fn connect(host: &str, ssl: bool, proxy: Option<String>, wrac: bool) -> Result<RacStream, Box<dyn Error>> {
|
pub fn connect(host: &str, proxy: Option<String>) -> Result<RacStream, Box<dyn Error>> {
|
||||||
let (host, ssl_, wrac_) = parse_rac_url(host).ok_or::<Box<dyn Error>>("url parse error".into())?;
|
let (host, ssl, wrac) = parse_rac_url(host).ok_or::<Box<dyn Error>>("url parse error".into())?;
|
||||||
let (ssl, wrac) = (ssl_ || ssl, wrac_ || wrac);
|
|
||||||
|
|
||||||
let stream: Box<dyn Stream> = if let Some(proxy) = proxy {
|
let stream: Box<dyn Stream> = if let Some(proxy) = proxy {
|
||||||
if let Some((proxy, auth)) = parse_socks5_url(&proxy) {
|
if let Some((proxy, auth)) = parse_socks5_url(&proxy) {
|
||||||
@ -172,14 +171,14 @@ pub fn connect(host: &str, ssl: bool, proxy: Option<String>, wrac: bool) -> Resu
|
|||||||
/// register_user(stream, name, name)
|
/// register_user(stream, name, name)
|
||||||
/// send_message_spoof_auth(stream, name + "> " + message)
|
/// send_message_spoof_auth(stream, name + "> " + message)
|
||||||
/// }
|
/// }
|
||||||
pub fn send_message_spoof_auth(stream: &mut RacStream, message: &str, remove_null: bool) -> Result<(), Box<dyn Error>> {
|
pub fn send_message_spoof_auth(stream: &mut RacStream, message: &str) -> Result<(), Box<dyn Error>> {
|
||||||
let Some((name, message)) = message.split_once("> ") else { return send_message(stream, message) };
|
let Some((name, message)) = message.split_once("> ") else { return send_message(stream, message) };
|
||||||
|
|
||||||
if let Ok(f) = send_message_auth(stream, &name, &message, &message, remove_null) {
|
if let Ok(f) = send_message_auth(stream, &name, &message, &message) {
|
||||||
if f != 0 {
|
if f != 0 {
|
||||||
let name = format!("\x1f{name}");
|
let name = format!("\x1f{name}");
|
||||||
register_user(stream, &name, &name, remove_null)?;
|
register_user(stream, &name, &name)?;
|
||||||
send_message_spoof_auth(stream, &format!("{name}> {message}"), remove_null)?;
|
send_message_spoof_auth(stream, &format!("{name}> {message}"))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,12 +211,11 @@ pub fn send_message(
|
|||||||
pub fn register_user(
|
pub fn register_user(
|
||||||
stream: &mut RacStream,
|
stream: &mut RacStream,
|
||||||
name: &str,
|
name: &str,
|
||||||
password: &str,
|
password: &str
|
||||||
remove_null: bool
|
|
||||||
) -> Result<bool, Box<dyn Error>> {
|
) -> Result<bool, Box<dyn Error>> {
|
||||||
match stream {
|
match stream {
|
||||||
RacStream::WRAC(websocket) => wrac::register_user(websocket, name, password),
|
RacStream::WRAC(websocket) => wrac::register_user(websocket, name, password),
|
||||||
RacStream::RAC(stream) => rac::register_user(stream, name, password, remove_null)
|
RacStream::RAC(stream) => rac::register_user(stream, name, password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,12 +234,11 @@ pub fn send_message_auth(
|
|||||||
stream: &mut RacStream,
|
stream: &mut RacStream,
|
||||||
name: &str,
|
name: &str,
|
||||||
password: &str,
|
password: &str,
|
||||||
message: &str,
|
message: &str
|
||||||
remove_null: bool
|
|
||||||
) -> Result<u8, Box<dyn Error>> {
|
) -> Result<u8, Box<dyn Error>> {
|
||||||
match stream {
|
match stream {
|
||||||
RacStream::WRAC(websocket) => wrac::send_message_auth(websocket, name, password, message),
|
RacStream::WRAC(websocket) => wrac::send_message_auth(websocket, name, password, message),
|
||||||
RacStream::RAC(stream) => rac::send_message_auth(stream, name, password, message, remove_null)
|
RacStream::RAC(stream) => rac::send_message_auth(stream, name, password, message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,12 +253,11 @@ pub fn send_message_auth(
|
|||||||
pub fn read_messages(
|
pub fn read_messages(
|
||||||
stream: &mut RacStream,
|
stream: &mut RacStream,
|
||||||
max_messages: usize,
|
max_messages: usize,
|
||||||
last_size: usize,
|
last_size: usize,
|
||||||
remove_null: bool,
|
|
||||||
chunked: bool
|
chunked: bool
|
||||||
) -> Result<Option<(Vec<String>, usize)>, Box<dyn Error>> {
|
) -> Result<Option<(Vec<String>, usize)>, Box<dyn Error>> {
|
||||||
match stream {
|
match stream {
|
||||||
RacStream::WRAC(websocket) => wrac::read_messages(websocket, max_messages, last_size, chunked),
|
RacStream::WRAC(websocket) => wrac::read_messages(websocket, max_messages, last_size, chunked),
|
||||||
RacStream::RAC(stream) => rac::read_messages(stream, max_messages, last_size, remove_null, chunked)
|
RacStream::RAC(stream) => rac::read_messages(stream, max_messages, last_size, chunked)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,23 +20,13 @@ pub fn send_message(stream: &mut impl Write, message: &str) -> Result<(), Box<dy
|
|||||||
pub fn register_user(
|
pub fn register_user(
|
||||||
stream: &mut (impl Write + Read),
|
stream: &mut (impl Write + Read),
|
||||||
name: &str,
|
name: &str,
|
||||||
password: &str,
|
password: &str
|
||||||
remove_null: bool
|
|
||||||
) -> Result<bool, Box<dyn Error>> {
|
) -> Result<bool, Box<dyn Error>> {
|
||||||
stream.write_all(format!("\x03{name}\n{password}").as_bytes())?;
|
stream.write_all(format!("\x03{name}\n{password}").as_bytes())?;
|
||||||
if remove_null {
|
if let Ok(out) = skip_null(stream) {
|
||||||
if let Ok(out) = skip_null(stream) {
|
Ok(out[0] == 0)
|
||||||
Ok(out[0] == 0)
|
|
||||||
} else {
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let mut buf = vec![0];
|
Ok(true)
|
||||||
if let Ok(1) = stream.read(&mut buf) {
|
|
||||||
Ok(buf[0] == 0)
|
|
||||||
} else {
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,24 +45,13 @@ pub fn send_message_auth(
|
|||||||
stream: &mut (impl Write + Read),
|
stream: &mut (impl Write + Read),
|
||||||
name: &str,
|
name: &str,
|
||||||
password: &str,
|
password: &str,
|
||||||
message: &str,
|
message: &str,
|
||||||
remove_null: bool
|
|
||||||
) -> Result<u8, Box<dyn Error>> {
|
) -> Result<u8, Box<dyn Error>> {
|
||||||
stream.write_all(format!("\x02{name}\n{password}\n{message}").as_bytes())?;
|
stream.write_all(format!("\x02{name}\n{password}\n{message}").as_bytes())?;
|
||||||
|
if let Ok(out) = skip_null(stream) {
|
||||||
if remove_null {
|
Ok(out[0])
|
||||||
if let Ok(out) = skip_null(stream) {
|
|
||||||
Ok(out[0])
|
|
||||||
} else {
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let mut buf = vec![0];
|
Ok(0)
|
||||||
if let Ok(1) = stream.read(&mut buf) {
|
|
||||||
Ok(buf[0])
|
|
||||||
} else {
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,26 +86,17 @@ pub fn read_messages(
|
|||||||
stream: &mut (impl Read + Write),
|
stream: &mut (impl Read + Write),
|
||||||
max_messages: usize,
|
max_messages: usize,
|
||||||
last_size: usize,
|
last_size: usize,
|
||||||
remove_null: bool,
|
|
||||||
chunked: bool
|
chunked: bool
|
||||||
) -> Result<Option<(Vec<String>, usize)>, Box<dyn Error>> {
|
) -> Result<Option<(Vec<String>, usize)>, Box<dyn Error>> {
|
||||||
stream.write_all(&[0x00])?;
|
stream.write_all(&[0x00])?;
|
||||||
|
|
||||||
let packet_size = {
|
let packet_size = {
|
||||||
let data = if remove_null {
|
let mut data = skip_null(stream)?;
|
||||||
let mut data = skip_null(stream)?;
|
let mut buf = vec![0; 10];
|
||||||
let mut buf = vec![0; 10];
|
let len = stream.read(&mut buf)?;
|
||||||
let len = stream.read(&mut buf)?;
|
buf.truncate(len);
|
||||||
buf.truncate(len);
|
data.append(&mut buf);
|
||||||
data.append(&mut buf);
|
remove_trailing_null(&mut data)?;
|
||||||
remove_trailing_null(&mut data)?;
|
|
||||||
data
|
|
||||||
} else {
|
|
||||||
let mut data = vec![0; 10];
|
|
||||||
let len = stream.read(&mut data)?;
|
|
||||||
data.truncate(len);
|
|
||||||
data
|
|
||||||
};
|
|
||||||
|
|
||||||
String::from_utf8(data)?
|
String::from_utf8(data)?
|
||||||
.trim_matches(char::from(0))
|
.trim_matches(char::from(0))
|
||||||
@ -145,17 +115,10 @@ pub fn read_messages(
|
|||||||
packet_size - last_size
|
packet_size - last_size
|
||||||
};
|
};
|
||||||
|
|
||||||
let packet_data = if remove_null {
|
let mut packet_data = skip_null(stream)?;
|
||||||
let mut data = skip_null(stream)?;
|
let mut buf = vec![0; to_read - 1];
|
||||||
let mut buf = vec![0; to_read - 1];
|
stream.read_exact(&mut buf)?;
|
||||||
stream.read_exact(&mut buf)?;
|
packet_data.append(&mut buf);
|
||||||
data.append(&mut buf);
|
|
||||||
data
|
|
||||||
} else {
|
|
||||||
let mut data = vec![0; to_read];
|
|
||||||
stream.read_exact(&mut data)?;
|
|
||||||
data
|
|
||||||
};
|
|
||||||
|
|
||||||
let packet_data = String::from_utf8_lossy(&packet_data).to_string();
|
let packet_data = String::from_utf8_lossy(&packet_data).to_string();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user