bhcli

A TUI for chatting on LE PHP Chats (onion)
git clone https://git.dasho.dev/n0tr1v/bhcli.git
Log | Files | Refs | README

commit e3573fe1352aaab4ad4157305d73e7066bde51e7
parent da6683780ac7aa5580ead9703a3346fbd224fea0
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Sun, 17 Mar 2024 10:41:17 -0700

jump to top message with gg

Diffstat:
MREADME.md | 1+
Msrc/main.rs | 43++++++++++++++++++++++++++++++++++++++++---
Msrc/util/mod.rs | 7+++++++
3 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md @@ -45,6 +45,7 @@ Pre-buit binaries can be found on the [official website](http://dkforestseeaaq2d - Page up the messages list `ctrl+U` | `page up` - Going down 1 message `j` | `down arrow` - Going up 1 message `k` | `up arrow` +- Jump to Top Message `gg` ## Build from source diff --git a/src/main.rs b/src/main.rs @@ -3,6 +3,7 @@ mod lechatphp; mod bhc; use anyhow::{anyhow, Context}; +use std::process; use log; use log::LevelFilter; use log4rs::append::file::FileAppender; @@ -216,6 +217,7 @@ struct LeChatPHPClient { client: Client, session: Option<String>, config: LeChatPHPConfig, + last_key_event: Option<KeyCode>, manual_captcha: bool, refresh_rate: u64, max_login_retry: isize, @@ -479,7 +481,22 @@ impl LeChatPHPClient { return Ok(()); } if self.chat_type == ClientType::BHC { - let mut resp_txt = self.client.get(&self.config.url).send().unwrap().text().unwrap(); + //let mut resp_txt = self.client.get(&self.config.url).send().unwrap().text().unwrap(); + let mut resp_txt = match self.client.get(&self.config.url).send() { + Ok(response) => { + match response.text() { + Ok(text) => text, + Err(err) => { + println!("Error: {}\nCheck Your Tor Connection", err); + process::exit(0); + } + } + }, + Err(err) => { + println!("Error: {}\nCheck Your Tor Connection", err); + process::exit(0); + } + }; let doc = Document::from(resp_txt.as_str()); if let Some(meta) = doc.find(Name("meta")).next() { let meta_content = meta.attr("content").context("meta content not found").unwrap().to_owned(); @@ -579,6 +596,9 @@ impl LeChatPHPClient { } fn handle_key_event(&mut self, app: &mut App, messages: &Arc<Mutex<Vec<Message>>>, users: &Arc<Mutex<Users>>, key_event: KeyEvent) -> Result<(), ExitSignal> { + if app.input_mode != InputMode::Normal { + self.last_key_event = None; + } match app.input_mode { InputMode::LongMessage => self.handle_long_message_mode_key_event(app, key_event, messages), InputMode::Normal => self.handle_normal_mode_key_event(app, key_event, messages), @@ -627,8 +647,10 @@ impl LeChatPHPClient { KeyEvent { code: KeyCode::PageDown, modifiers: KeyModifiers::NONE, .. } => self.handle_normal_mode_key_event_page_down(app), KeyEvent { code: KeyCode::Esc, modifiers: KeyModifiers::NONE, .. } => self.handle_normal_mode_key_event_esc(app), KeyEvent { code: KeyCode::Char('u'), modifiers: KeyModifiers::SHIFT, .. } => self.handle_normal_mode_key_event_shift_u(app), + KeyEvent { code: KeyCode::Char('g'), modifiers: KeyModifiers::NONE, .. } => self.handle_normal_mode_key_event_g(app), _ => {} } + self.last_key_event = Some(key_event.code); Ok(()) } @@ -682,7 +704,7 @@ impl LeChatPHPClient { fn handle_normal_mode_key_event_down(&mut self, app: &mut App) { app.items.next() } - + fn handle_normal_mode_key_event_slash(&mut self, app: &mut App) { app.items.unselect(); app.input = "/".to_owned(); @@ -796,6 +818,15 @@ impl LeChatPHPClient { self.display_guest_view = !self.display_guest_view; } + + fn handle_normal_mode_key_event_g(&mut self, app: &mut App) { + // Handle "gg" key combination + if self.last_key_event == Some(KeyCode::Char('g')) { + app.items.select_top(); + self.last_key_event = None; + } + } + fn handle_normal_mode_key_event_toggle_hidden(&mut self) { self.display_hidden_msgs = !self.display_hidden_msgs; } @@ -1238,7 +1269,7 @@ fn post_msg(client: &Client, post_type_recv: PostType, full_url: &str, session: let mut should_reset_keepalive_timer = false; retry_fn(|| -> anyhow::Result<RetryErr> { let post_type = post_type_recv.clone(); - let resp_text = client.get(url.clone()).send()?.text()?; + let resp_text = client.get(url).send()?.text()?; let doc = Document::from(resp_text.as_str()); let nc = doc.find(Attr("name", "nc")).next().context("nc not found")?; let nc_value = nc.attr("value").context("nc value not found")?.to_owned(); @@ -1654,6 +1685,7 @@ fn new_default_le_chat_php_client(params: Params) -> LeChatPHPClient { max_login_retry: params.max_login_retry, guest_color: params.guest_color, session: None, + last_key_event: None, client: params.client, manual_captcha: params.manual_captcha, refresh_rate: params.refresh_rate, @@ -2214,6 +2246,10 @@ impl Users { out.extend(&self.guests); out } + + // fn is_guest(&self, name: &str) -> bool { + // self.guests.iter().find(|(_, username)| username == name).is_some() + // } } fn extract_users(doc: &Document) -> Users { @@ -2608,6 +2644,7 @@ fn random_string(n: usize) -> String { std::str::from_utf8(&s).unwrap().to_owned() } +#[derive(PartialEq)] enum InputMode { LongMessage, Normal, diff --git a/src/util/mod.rs b/src/util/mod.rs @@ -52,4 +52,11 @@ impl<T> StatefulList<T> { pub fn unselect(&mut self) { self.state.select(None); } + + pub fn select_top(&mut self) { + if self.items.is_empty() { + return; + } + self.state.select(Some(0)); + } }