Skip to content

Commit

Permalink
Refactor settings.rs and parser.rs for improved readability and maint…
Browse files Browse the repository at this point in the history
…ainability
  • Loading branch information
Xerxes-2 committed Apr 20, 2024
1 parent c04a23f commit 7520fe2
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 90 deletions.
139 changes: 66 additions & 73 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ async fn shutdown_signal() {
}

#[derive(Clone)]
struct ActionHandler(
Arc<Mutex<parser::Parser>>,
Arc<settings::Settings>,
reqwest::Client,
);
struct ActionHandler {
parser: Arc<Mutex<parser::Parser>>,
settings: Arc<settings::Settings>,
client: reqwest::Client,
}

pub const SERIALIZE_OPTIONS: SerializeOptions = SerializeOptions::new()
.skip_default_fields(false)
Expand All @@ -58,29 +58,25 @@ impl WebSocketHandler for ActionHandler {
}
})
.collect::<String>();
event!(Level::DEBUG, "{} {}", direction_char, hex);
let mut parser = self.0.lock().unwrap();
let parsed = parser.parse(&buf);
debug!("{} {}", direction_char, hex);
let mut parser = self.parser.lock().unwrap();
let parsed = parser.parse(buf);
let parsed = match parsed {
Ok(parsed) => parsed,
Err(e) => {
event!(Level::ERROR, "Failed to parse message: {:?}", e);
error!("Failed to parse message: {:?}", e);
return Some(msg);
}
};
event!(
Level::INFO,
"拦截到: {}, {}, {:?}, {}",
direction_char,
parsed.id,
parsed.msg_type,
parsed.method_name
info!(
"监听到: {}, {}, {:?}, {}",
direction_char, parsed.id, parsed.msg_type, parsed.method_name
);
if direction_char == '\u{2193}' {
return Some(msg);
}
if let Err(e) = self.send_message(parsed) {
event!(Level::ERROR, "Failed to send message: {:?}", e);
error!("Failed to send message: {:?}", e);
}
}
Some(msg)
Expand All @@ -89,31 +85,30 @@ impl WebSocketHandler for ActionHandler {

impl ActionHandler {
fn send_message(&self, mut parsed: LiqiMessage) -> Result<(), Box<dyn Error>> {
let settings = self.1.clone();
let json_body: String;
event!(Level::INFO, "Method: {}", parsed.method_name);
if settings
.send_method
.iter()
.all(|x| !parsed.method_name.contains(x))
{
let settings = self.settings.clone();
let json_data: JsonValue;
if !settings.is_method(&parsed.method_name) {
return Ok(());
}
if parsed.method_name.contains(".lq.ActionPrototype") {
let name = parsed.data.get("name").ok_or("No name field")?.to_string();
event!(Level::INFO, "Action: {}", name);
if settings.send_action.iter().all(|x| !name.contains(x)) {
event!(Level::INFO, "Action {} not in send_action", name);
if parsed.method_name == ".lq.ActionPrototype" {
let name = parsed
.data
.get("name")
.ok_or("No name field")?
.as_str()
.ok_or("name is not a string")?
.to_owned();
if !settings.is_action(&name) {
return Ok(());
}
let data = parsed.data.get_mut("data").ok_or("No data field")?;
if name.contains("ActionNewRound") {
if name == "ActionNewRound" {
data.as_object_mut()
.ok_or("data is not an object")?
.insert("md5".to_string(), json!(RANDOM_MD5));
}
json_body = serde_json::to_string(data)?;
} else if parsed.method_name.contains(".lq.FastTest.syncGame") {
json_data = data.take();
} else if parsed.method_name == ".lq.FastTest.syncGame" {
let game_restore = parsed
.data
.get("game_restore")
Expand All @@ -124,30 +119,31 @@ impl ActionHandler {
.ok_or("actions is not an array")?;
let mut actions: Vec<Action> = vec![];
for item in game_restore.iter() {
let action_name = item.get("name").ok_or("No name field")?.as_str().ok_or(
"
name is not a string
",
)?;
let action_data = item.get("data").ok_or("No data field")?.as_str().unwrap_or(
"
data is not a string",
);
if action_data.len() == 0 {
let action_name = item
.get("name")
.ok_or("No name field")?
.as_str()
.ok_or("name is not a string")?;
let action_data = item
.get("data")
.ok_or("No data field")?
.as_str()
.unwrap_or("data is not a string");
if action_data.is_empty() {
let action = Action {
name: action_name.to_string(),
data: JsonValue::Object(Map::new()),
};
actions.push(action);
} else {
let b64 = BASE64_STANDARD.decode(action_data)?;
let parser = self.0.lock().unwrap();
let parser = self.parser.lock().unwrap();
let action_type = parser
.pool
.get_message_by_name(&action_name)
.get_message_by_name(action_name)
.ok_or("Invalid action type")?;
let mut action_obj = DynamicMessage::decode(action_type, b64.as_ref())?;
if action_name.contains(".lq.ActionNewRound") {
if action_name == ".lq.ActionNewRound" {
action_obj.set_field_by_name("md5", Value::String(RANDOM_MD5.to_string()));
}
let value: JsonValue = my_serialize(action_obj)?;
Expand All @@ -163,26 +159,22 @@ impl ActionHandler {
"sync_game_actions".to_string(),
serde_json::to_value(actions)?,
);
json_body = serde_json::to_string(&map)?;
json_data = JsonValue::Object(map);
} else {
json_body = serde_json::to_string(&parsed.data)?;
json_data = parsed.data;
}

// post data to API, no verification
let client = self.2.clone();
let future = client
.post(&settings.api_url)
.body(json_body.to_owned())
.send();
let client = self.client.clone();
let future = client.post(&settings.api_url).json(&json_data).send();

handle_future(future);
event!(Level::INFO, "已发送: {}", json_body);
info!("已发送: {}", json_data);

let json_obj: JsonValue = serde_json::from_str(&json_body)?;
if let Some(liqi_data) = json_obj.get("liqi") {
if let Some(liqi_data) = json_data.get("liqi") {
let res = client.post(&settings.api_url).json(liqi_data).send();
handle_future(res);
event!(Level::INFO, "已发送: {:?}", liqi_data);
info!("已发送: {:?}", liqi_data);
}

Ok(())
Expand All @@ -196,10 +188,10 @@ fn handle_future(
match future.await {
Ok(res) => {
let body = res.text().await.unwrap_or_default();
event!(Level::INFO, "小助手已接收: {}", body);
info!("小助手已接收: {}", body);
}
Err(e) => {
event!(Level::ERROR, "请求失败: {:?}", e);
error!("请求失败: {:?}", e);
}
}
});
Expand All @@ -221,26 +213,27 @@ async fn main() {

// print red declaimer text
println!(
"{}",
"\x1b[31m
本项目完全免费开源,如果您购买了此程序,请立即退款!
项目地址: https://github.com/Xerxes-2/mahjong_helper_majsoul_hudsucker/
本程序仅供学习交流使用,严禁用于商业用途!
请遵守当地法律法规,对于使用本程序所产生的任何后果,作者概不负责!
请勿将本程序用于非法用途,否则后果自负!
\x1b[0m"
);
let parser = parser::Parser::new();
let settings = settings::Settings::new();
if let Err(e) = settings {
error!("{}", e);
// press any key to exit
println!("按任意键退出");
let _ = std::io::stdin().read(&mut [0u8]).unwrap();
return;
}
let settings = settings.unwrap();
let settings = match settings {
Ok(settings) => settings,
Err(e) => {
error!("{}", e);
// press any key to exit
println!("按任意键退出");
let mut stdin = std::io::stdin();
let _ = stdin.read(&mut [0u8]).unwrap_or_default();
return;
}
};
let client = reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(true)
.build()
Expand All @@ -250,11 +243,11 @@ async fn main() {
.with_addr(SocketAddr::from(([127, 0, 0, 1], 23410)))
.with_rustls_client()
.with_ca(ca)
.with_websocket_handler(ActionHandler(
Arc::new(Mutex::new(parser)),
Arc::new(settings),
.with_websocket_handler(ActionHandler {
parser: Arc::new(Mutex::new(parser)),
settings: Arc::new(settings),
client,
))
})
.with_graceful_shutdown(shutdown_signal())
.build();

Expand Down
24 changes: 11 additions & 13 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use prost_reflect::{DescriptorPool, DynamicMessage, MessageDescriptor};
use serde::Serialize;
use serde_json::Value as JsonValue;
use std::{collections::HashMap, error::Error};
use tracing::*;

use crate::SERIALIZE_OPTIONS;

Expand Down Expand Up @@ -46,7 +45,8 @@ impl Parser {
pub fn new() -> Self {
let json_str = include_str!("liqi.json");
let proto_json = serde_json::from_str(json_str).expect("Failed to parse liqi.json");
let pool = DescriptorPool::decode(include_bytes!("liqi.desc").as_ref()).unwrap();
let pool = DescriptorPool::decode(include_bytes!("liqi.desc").as_ref())
.expect("Failed to decode liqi.desc");
Self {
total: 0,
respond_type: HashMap::new(),
Expand All @@ -57,7 +57,7 @@ impl Parser {

pub fn parse(&mut self, buf: &[u8]) -> Result<LiqiMessage, Box<dyn Error>> {
let msg_type_byte = buf[0];
if msg_type_byte < 1 || msg_type_byte > 3 {
if !(1..=3).contains(&msg_type_byte) {
return Err("Invalid message type".into());
}
let msg_type = match msg_type_byte {
Expand All @@ -73,11 +73,11 @@ impl Parser {
MessageType::Notify => {
let blks = buf_to_blocks(&buf[1..]).ok_or("Failed to parse blocks")?;
method_name = String::from_utf8(blks[0].data.clone())?;
let method_name_list: Vec<&str> = method_name.split(".").collect();
let method_name_list: Vec<&str> = method_name.split('.').collect();
let message_name = method_name_list[2];
let message_type = self
.pool
.get_message_by_name(&to_fqn(&message_name))
.get_message_by_name(&to_fqn(message_name))
.ok_or("Invalid message type")?;
let dyn_msg = DynamicMessage::decode(message_type, blks[1].data.as_ref())?;
data_obj = my_serialize(dyn_msg)?;
Expand All @@ -93,7 +93,7 @@ impl Parser {
let my_decoded = decode(&decoded);
let action_type = self
.pool
.get_message_by_name(&to_fqn(&action_name))
.get_message_by_name(&to_fqn(action_name))
.ok_or("Invalid action type")?;
let action_msg = DynamicMessage::decode(action_type, my_decoded.as_ref())?;
let action_obj = my_serialize(action_msg)?;
Expand All @@ -113,7 +113,7 @@ impl Parser {
// ascii decode into method name, method_name = msg_block[0]["data"].decode()
let method_block = &blocks[0];
method_name = String::from_utf8(method_block.data.to_owned())?;
let method_name_list: Vec<&str> = method_name.split(".").collect();
let method_name_list: Vec<&str> = method_name.split('.').collect();
let lq = method_name_list[1];
let service = method_name_list[2];
let rpc = method_name_list[3];
Expand Down Expand Up @@ -143,7 +143,7 @@ impl Parser {
MessageType::Response => {
msg_id = u16::from_le_bytes([buf[1], buf[2]]) as usize;
let blocks = buf_to_blocks(&buf[3..]).ok_or("Failed to parse blocks")?;
assert!(blocks[0].data.len() == 0);
assert!(blocks[0].data.is_empty());
let resp_type: MessageDescriptor;
(method_name, resp_type) = self
.respond_type
Expand Down Expand Up @@ -176,8 +176,6 @@ struct Block {
}

fn buf_to_blocks(buf: &[u8]) -> Option<Vec<Block>> {
let hex_str = buf.iter().map(|b| format!("{:02x}", b)).collect::<String>();
event!(Level::DEBUG, "buf: {}", hex_str);
let mut blocks = Vec::new();
let mut i = 0;
let l = buf.len();
Expand Down Expand Up @@ -228,13 +226,13 @@ fn parse_var_int(buf: &[u8], p: usize) -> (usize, usize) {
}

fn decode(data: &[u8]) -> Vec<u8> {
let keys = vec![0x84, 0x5E, 0x4E, 0x42, 0x39, 0xA2, 0x1F, 0x60, 0x1C];
let keys = [0x84, 0x5E, 0x4E, 0x42, 0x39, 0xA2, 0x1F, 0x60, 0x1C];
let mut data = data.to_vec();
let k = keys.len();
let d = data.len();
for i in 0..d {
let u = (23 ^ d) + 5 * i + keys[i % k] & 255;
let u = ((23 ^ d) + 5 * i + keys[i % k]) & 255;
data[i] ^= u as u8;
}
return data;
data
}
22 changes: 18 additions & 4 deletions src/settings.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::Deserialize;
use serde_json;
use tracing::event;
use std::collections::HashSet;
use tracing::info;

#[derive(Deserialize, Debug)]
pub struct Settings {
Expand All @@ -10,6 +10,10 @@ pub struct Settings {
pub send_action: Vec<String>,
#[serde(rename(deserialize = "API_URL"))]
pub api_url: String,
#[serde(skip)]
methods_set: HashSet<String>,
#[serde(skip)]
actions_set: HashSet<String>,
}

impl Settings {
Expand All @@ -28,9 +32,19 @@ impl Settings {
|_| std::fs::read_to_string("settings.json"),
)
.map_err(|e| format!("无法读取settings.json: {}", e))?;
let settings: Settings =
let mut settings: Settings =
serde_json::from_str(&settings).map_err(|e| format!("无法解析settings.json: {}", e))?;
event!(tracing::Level::INFO, "已载入配置: {:?}", settings);
info!("已载入配置: {:?}", settings);
settings.methods_set = settings.send_method.iter().cloned().collect();
settings.actions_set = settings.send_action.iter().cloned().collect();
Ok(settings)
}

pub fn is_method(&self, method: &str) -> bool {
self.methods_set.contains(method)
}

pub fn is_action(&self, action: &str) -> bool {
self.actions_set.contains(action)
}
}

0 comments on commit 7520fe2

Please sign in to comment.