commit e37498bb0e87fceacb59a152493d9bce21564518
parent 818b57435449883a0fe798dfa2056880fab5dea6
Author: Strange <StrangeGuy6228@protonmail.com>
Date: Sun, 21 Apr 2024 19:01:52 +0530
BHC 1st captcha removed => completely ripped ClientType:BHC&DAN, either provide the url with -url or defuault url=blkhat.onion
Diffstat:
| M | src/main.rs | | | 290 | ++++++------------------------------------------------------------------------- |
1 file changed, 21 insertions(+), 269 deletions(-)
diff --git a/src/main.rs b/src/main.rs
@@ -18,7 +18,6 @@ use crossterm::{
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
-use http::StatusCode;
use lazy_static::lazy_static;
use linkify::LinkFinder;
use log::LevelFilter;
@@ -37,7 +36,6 @@ use serde_derive::{Deserialize, Serialize};
use std::collections::HashMap;
use std::io::Cursor;
use std::io::{self, Write};
-use std::process;
use std::process::Command;
use std::sync::Mutex;
use std::sync::{Arc, MutexGuard};
@@ -64,9 +62,6 @@ const SEND_TO_STAFFS: &str = "s %";
const SEND_TO_ADMINS: &str = "s _";
const SOUND1: &[u8] = include_bytes!("sound1.mp3");
const DKF_URL: &str = "http://dkforestseeaaq2dqz2uflmlsybvnq2irzn4ygyvu53oazyorednviid.onion";
-const BHCLI_BLOG_URL: &str =
- "http://dkforestseeaaq2dqz2uflmlsybvnq2irzn4ygyvu53oazyorednviid.onion/bhcli";
-// const BAN_IMPOSTERS: bool = true;
const SERVER_DOWN_500_ERR: &str = "500 Internal Server Error, server down";
const SERVER_DOWN_ERR: &str = "502 Bad Gateway, server down";
const KICKED_ERR: &str = "You have been kicked";
@@ -76,9 +71,6 @@ const CAPTCHA_WG_ERR: &str = "Wrong Captcha";
const CAPTCHA_FAILED_SOLVE_ERR: &str = "Failed solve captcha";
const CAPTCHA_USED_ERR: &str = "Captcha already used or timed out";
const UNKNOWN_ERR: &str = "Unknown error";
-const N0TR1V: &str = "n0tr1v";
-const STUXNET: &str = "STUXNET";
-// const FAGGOT: &str = "faggot";
const DNMX_URL: &str = "http://hxuzjtocnzvv5g2rtg2bhwkcbupmk7rclb6lly3fo4tvqkk5oyrv3nid.onion";
lazy_static! {
@@ -189,17 +181,6 @@ impl LeChatPHPConfig {
staffs_tag: "[Staff] ".to_owned(),
}
}
-
- fn new_dans_chat_config() -> Self {
- Self {
- url: "http://danschat356lctri3zavzh6fbxg2a7lo6z3etgkctzzpspewu7zdsaqd.onion".to_owned(),
- datetime_fmt: "%d-%m %H:%M:%S".to_owned(),
- page_php: "chat.php".to_owned(),
- keepalive_send_to: None,
- members_tag: "[Members] ".to_owned(),
- staffs_tag: "[Staff] ".to_owned(),
- }
- }
}
struct BaseClient {
@@ -208,7 +189,6 @@ struct BaseClient {
}
struct LeChatPHPClient {
- chat_type: ClientType,
base_client: BaseClient,
guest_color: String,
client: Client,
@@ -243,27 +223,34 @@ impl LeChatPHPClient {
| LoginErr::NicknameErr
| LoginErr::UnknownErr => {
log::error!("{}", e);
+ println!("Login error: {}", e); // Print error message
break;
}
LoginErr::CaptchaFailedSolveErr => {
log::error!("{}", e);
+ println!("Captcha failed to solve: {}", e); // Print error message
continue;
}
LoginErr::CaptchaWgErr | LoginErr::CaptchaUsedErr => {}
LoginErr::ServerDownErr | LoginErr::ServerDown500Err => {
log::error!("{}", e);
+ println!("Server is down: {}", e); // Print error message
}
LoginErr::Reqwest(err) => {
if err.is_connect() {
log::error!("{}\nIs tor proxy enabled ?", err);
+ println!("Connection error: {}\nIs tor proxy enabled ?", err); // Print error message
break;
} else if err.is_timeout() {
log::error!("timeout: {}", err);
+ println!("Timeout error: {}", err); // Print error message
} else {
log::error!("{}", err);
+ println!("Reqwest error: {}", err); // Print error message
}
}
},
+
Ok(()) => {
attempt = 0;
match self.get_msgs() {
@@ -365,7 +352,6 @@ impl LeChatPHPClient {
let is_muted = Arc::clone(&self.is_muted);
let exit_rx = sig.lock().unwrap().clone();
let sig = Arc::clone(sig);
- let tx = self.tx.clone();
let members_tag = self.config.members_tag.clone();
thread::spawn(move || loop {
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
@@ -378,7 +364,6 @@ impl LeChatPHPClient {
&page_php,
&session,
&username,
- &tx,
&users,
&sig,
&messages_updated_tx,
@@ -449,6 +434,7 @@ impl LeChatPHPClient {
app.members_tag = self.config.members_tag.clone();
app.staffs_tag = self.config.staffs_tag.clone();
+ // process()
// Draw UI
terminal.draw(|f| {
draw_terminal_frame(f, &mut app, &messages, &users, &self.base_client.username);
@@ -499,98 +485,6 @@ impl LeChatPHPClient {
if self.session.is_some() {
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 = 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();
- let index_url = META_REFRESH_RGX.captures(&meta_content).unwrap()[1].to_owned();
- resp_txt = self
- .client
- .get(format!("{}/{}", &self.config.url, index_url))
- .send()
- .unwrap()
- .text()
- .unwrap();
- }
- let doc = Document::from(resp_txt.as_str());
- let form_action = doc
- .find(Name("form"))
- .next()
- .unwrap()
- .attr("action")
- .context("form action not found")
- .unwrap()
- .to_owned();
- let captcha_url = doc
- .find(Name("img"))
- .next()
- .unwrap()
- .attr("src")
- .context("img src not found")
- .unwrap()
- .to_owned();
-
- let captcha_bytes = self
- .client
- .get(format!("{}/{}", &self.config.url, captcha_url))
- .send()
- .unwrap()
- .bytes()
- .unwrap();
- let img = image::load_from_memory(&captcha_bytes).unwrap();
- let img_buf = image::imageops::resize(
- &img,
- img.width(),
- img.height(),
- image::imageops::FilterType::Nearest,
- );
- // Save captcha as file on disk
- img_buf.save("captcha.gif").unwrap();
- termage::display_image("captcha.gif", img.width(), img.height());
- // Enter captcha
- print!("captcha: ");
- let mut captcha_input = String::new();
- io::stdout().flush().unwrap();
- io::stdin().read_line(&mut captcha_input).unwrap();
- trim_newline(&mut captcha_input);
- let params = vec![
- ("input", captcha_input),
- ("submit", "Enter+Chat".to_owned()),
- ];
- let resp = self
- .client
- .post(format!("{}/{}", &self.config.url, form_action))
- .form(¶ms)
- .send()
- .unwrap();
- if resp.status() != StatusCode::SEE_OTHER {
- return Err(LoginErr::CaptchaWgErr);
- }
- self.config.page_php = resp
- .headers()
- .get("location")
- .map(|v| v.to_str().unwrap())
- .unwrap_or(&self.config.page_php)
- .to_string();
- }
self.session = Some(lechatphp::login(
&self.client,
&self.config.url,
@@ -1235,22 +1129,6 @@ impl LeChatPHPClient {
}
}
- // fn handle_normal_mode_key_event_debug(&mut self, app: &mut App) {
- // if let Some(idx) = app.items.state.selected() {
- // if let Some(item) = app.items.items.get(idx) {
- // log::error!("{:?}", item.text.text());
- // }
- // }
- // }
-
- // fn handle_normal_mode_key_event_debug2(&mut self, app: &mut App) {
- // if let Some(idx) = app.items.state.selected() {
- // if let Some(item) = app.items.items.get(idx) {
- // log::error!("{:?} {:?}", item.text, item.upload_link);
- // }
- // }
- // }
-
fn handle_normal_mode_key_event_toggle_mute(&mut self) {
let mut is_muted = self.is_muted.lock().unwrap();
*is_muted = !*is_muted;
@@ -1425,20 +1303,11 @@ impl LeChatPHPClient {
let input: String = app.input.drain(..).collect();
app.input_idx = 0;
- if app.commands.commands.is_empty() {
- log::error!("Commands hashmap is empty!");
- } else {
- for (command, action) in &app.commands.commands {
- log::error!("command: {}, action: {}", command, action);
- }
- }
-
// Iterate over commands and execute associated actions
for (command, action) in &app.commands.commands {
- log::error!("command :{} action :{}", command, action);
+ // log::error!("command :{} action :{}", command, action);
let expected_input = format!("!{}", command);
if input == expected_input {
- log::error!("inside if");
// Execute the action by posting a message
self.post_msg(PostType::Post(action.clone(), None)).unwrap();
// Return Ok(()) if the action is executed successfully
@@ -1549,7 +1418,7 @@ impl LeChatPHPClient {
"This is your warning - {}, will be kicked next !rules",
msg
);
- log::error!("The Strange end_msg is :{}", end_msg);
+ // log::error!("The Strange end_msg is :{}", end_msg);
self.post_msg(PostType::Post(end_msg, None)).unwrap();
} else {
if input.starts_with("/") && !input.starts_with("/me ") {
@@ -1975,7 +1844,6 @@ fn get_msgs(
page_php: &str,
session: &str,
username: &str,
- tx: &crossbeam_channel::Sender<PostType>,
users: &Arc<Mutex<Users>>,
sig: &Arc<Mutex<Sig>>,
messages_updated_tx: &crossbeam_channel::Sender<()>,
@@ -2008,8 +1876,6 @@ fn get_msgs(
members_tag,
username,
should_notify,
- tx,
- sig,
);
// Build messages vector. Tag deleted messages.
update_messages(new_messages, messages, datetime_fmt);
@@ -2020,7 +1886,6 @@ fn get_msgs(
}
{
let mut users = users.lock().unwrap();
- // ban_imposters(&tx, &username, &users);
*users = extract_users(&doc);
}
Ok(())
@@ -2033,21 +1898,17 @@ fn process_new_messages(
members_tag: &str,
username: &str,
should_notify: &mut bool,
- tx: &crossbeam_channel::Sender<PostType>,
- sig: &Arc<Mutex<Sig>>,
) {
- if let Some(last_known_msg) = messages.get(0) {
+ if let Some(last_known_msg) = messages.first() {
let last_known_msg_parsed_dt = parse_date(&last_known_msg.date, datetime_fmt);
let filtered = new_messages.iter().filter(|new_msg| {
last_known_msg_parsed_dt <= parse_date(&new_msg.date, datetime_fmt)
&& !(new_msg.date == last_known_msg.date && last_known_msg.text == new_msg.text)
});
for new_msg in filtered {
- if let Some((from, to_opt, msg)) = get_message(&new_msg.text, &members_tag) {
+ if let Some((_, to_opt, msg)) = get_message(&new_msg.text, members_tag) {
// Process new messages
- if username == N0TR1V {
- n0tr1v_only_process_msg(&from, &msg, &tx, &sig);
- }
+
// Notify when tagged
if msg.contains(format!("@{}", &username).as_str()) {
*should_notify = true;
@@ -2114,31 +1975,6 @@ fn update_messages(
messages.truncate(1000);
}
-fn n0tr1v_only_process_msg(
- from: &str,
- msg: &str,
- tx: &crossbeam_channel::Sender<PostType>,
- sig: &Arc<Mutex<Sig>>,
-) {
- // !bhcli filters
- if msg == "!bhcli" {
- let msg = format!("@{} -> {}", from, BHCLI_BLOG_URL).to_owned();
- tx.send(PostType::Post(msg, None)).unwrap();
- } else if msg == "/logout" && from == STUXNET {
- log::error!("forced logout by {}", from);
- sig.lock().unwrap().signal(&ExitSignal::Terminate);
- return;
- }
- // Auto kick spammers
- // if from != N0TR1V && from != FAGGOT {
- // if msg.contains(FAGGOT) && (msg.contains("pedo") || msg.contains("child")) {
- // let msg = "spam".to_owned();
- // let username_to_kick = from.to_owned();
- // tx.send(PostType::Kick(msg, username_to_kick)).unwrap();
- // }
- // }
-}
-
fn delete_message(
client: &Client,
full_url: &str,
@@ -2174,81 +2010,17 @@ fn delete_message(
Ok(())
}
-// fn ban_imposters(tx: &crossbeam_channel::Sender<PostType>, account_username: &str, users: &Users) {
-// if BAN_IMPOSTERS {
-// if users.admin.len() == 0 && (users.staff.len() == 0 || account_username == N0TR1V) {
-// let n0tr1v_rgx = Regex::new(r#"n[o0]tr[1il][vy]"#).unwrap(); // o 0 | 1 i l | v y
-// let molester_rgx = Regex::new(r#"m[o0][1l][e3][s5$]t[e3]r"#).unwrap();
-// let rapist_rgx = Regex::new(r#"r[a4]p[i1l]st"#).unwrap();
-// let hitler_rgx = Regex::new(r#"h[i1l]t[l1]er"#).unwrap();
-// let himmler_rgx = Regex::new(r#"h[i1]m+l[e3]r"#).unwrap();
-// let mengele_rgx = Regex::new(r#"m[e3]ng[e3]l[e3]"#).unwrap();
-// let goebbels_rgx = Regex::new(r#"g[o0][e|3]b+[e3]ls"#).unwrap();
-// let heydrich_rgx = Regex::new(r#"h[e3]ydr[i1]ch"#).unwrap();
-// let globocnik_rgx = Regex::new(r#"gl[o0]b[o0]cn[i1l]k"#).unwrap();
-// let dirlewanger_rgx = Regex::new(r#"d[i1]rl[e3]wang[e3]r"#).unwrap();
-// let jeckeln_rgx = Regex::new(r#"j[e3]ck[e3]ln"#).unwrap();
-// let kramer_rgx = Regex::new(r#"kram[e3]r"#).unwrap();
-// let blobel_rgx = Regex::new(r#"bl[o0]b[e3]l"#).unwrap();
-// let stangl_rgx = Regex::new(r#"stangl"#).unwrap();
-// for (_color, username) in &users.guests {
-// let lower_name = username.to_lowercase();
-// // Names that anyone using bhcli will ban
-// if n0tr1v_rgx.is_match(&lower_name) || lower_name.contains("pedo") {
-// let msg = "forbidden name".to_owned();
-// let username = username.to_owned();
-// tx.send(PostType::Kick(msg, username)).unwrap();
-// }
-// // Names that only "n0tr1v" will ban
-// if account_username == N0TR1V {
-// if lower_name.contains("fuck")
-// || lower_name.contains("nigger")
-// || lower_name.contains("nigga")
-// || lower_name.contains("chink")
-// || lower_name.contains("atomwaffen")
-// || lower_name.contains("altright")
-// || hitler_rgx.is_match(&lower_name)
-// || goebbels_rgx.is_match(&lower_name)
-// || himmler_rgx.is_match(&lower_name)
-// || mengele_rgx.is_match(&lower_name)
-// || heydrich_rgx.is_match(&lower_name)
-// || globocnik_rgx.is_match(&lower_name)
-// || dirlewanger_rgx.is_match(&lower_name)
-// || jeckeln_rgx.is_match(&lower_name)
-// || kramer_rgx.is_match(&lower_name)
-// || blobel_rgx.is_match(&lower_name)
-// || stangl_rgx.is_match(&lower_name)
-// || rapist_rgx.is_match(&lower_name)
-// || molester_rgx.is_match(&lower_name)
-// {
-// let msg = "forbidden name".to_owned();
-// let username = username.to_owned();
-// tx.send(PostType::Kick(msg, username)).unwrap();
-// }
-// }
-// }
-// }
-// }
-// }
-
impl ChatClient {
fn new(params: Params) -> Self {
let mut c = new_default_le_chat_php_client(params.clone());
- match params.chat_type {
- ClientType::Custom => {
- c.config.url = params.url.unwrap_or("".to_owned());
- c.config.page_php = params.page_php.unwrap_or("chat.php".to_owned());
- c.config.datetime_fmt = params.datetime_fmt.unwrap_or("%m-%d %H:%M:%S".to_owned());
- c.config.members_tag = params.members_tag.unwrap_or("[M] ".to_owned());
- c.config.keepalive_send_to = None;
- }
- ClientType::Dan => {
- c.config = LeChatPHPConfig::new_dans_chat_config();
- }
- ClientType::BHC => {
- c.config = LeChatPHPConfig::new_black_hat_chat_config();
- }
- }
+ c.config.url = params.url.unwrap_or(
+ "http://blkhatjxlrvc5aevqzz5t6kxldayog6jlx5h7glnu44euzongl4fh5ad.onion/index.php"
+ .to_owned(),
+ );
+ c.config.page_php = params.page_php.unwrap_or("chat.php".to_owned());
+ c.config.datetime_fmt = params.datetime_fmt.unwrap_or("%m-%d %H:%M:%S".to_owned());
+ c.config.members_tag = params.members_tag.unwrap_or("[M] ".to_owned());
+ c.config.keepalive_send_to = None;
Self {
le_chat_php_client: c,
}
@@ -2263,7 +2035,6 @@ fn new_default_le_chat_php_client(params: Params) -> LeChatPHPClient {
let (color_tx, color_rx) = crossbeam_channel::unbounded();
let (tx, rx) = crossbeam_channel::unbounded();
LeChatPHPClient {
- chat_type: params.chat_type,
base_client: BaseClient {
username: params.username,
password: params.password,
@@ -2294,7 +2065,6 @@ struct ChatClient {
#[derive(Debug, Clone)]
struct Params {
- chat_type: ClientType,
url: Option<String>,
page_php: Option<String>,
datetime_fmt: Option<String>,
@@ -2412,13 +2182,6 @@ fn ask_password(password: Option<String>) -> String {
password.unwrap_or_else(|| rpassword::prompt_password("Password: ").unwrap())
}
-#[derive(Debug, Clone, PartialEq)]
-enum ClientType {
- BHC,
- Dan,
- Custom,
-}
-
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DkfNotifierResp {
@@ -2517,12 +2280,10 @@ impl Default for Commands {
// Strange
// Function to read the configuration file and parse it
-// Function to read the configuration file and parse it
fn read_commands_file(file_path: &str) -> Result<Commands, Box<dyn std::error::Error>> {
// Read the contents of the file
let commands_content = std::fs::read_to_string(file_path)?;
// log::error!("Read file contents: {}", commands_content);
-
// Deserialize the contents into a Commands struct
let commands: Commands = toml::from_str(&commands_content)?;
// log::error!(
@@ -2581,16 +2342,7 @@ fn main() -> anyhow::Result<()> {
let username = ask_username(opts.username);
let password = ask_password(opts.password);
- let chat_type = if opts.url.is_some() {
- ClientType::Custom
- } else if opts.dan {
- ClientType::Dan
- } else {
- ClientType::BHC
- };
-
let params = Params {
- chat_type,
url: opts.url,
page_php: opts.page_php,
datetime_fmt: opts.datetime_fmt,