@@ -5,19 +5,16 @@ use hudsucker::{
5
5
tokio_tungstenite:: tungstenite:: Message ,
6
6
* ,
7
7
} ;
8
+ use once_cell:: sync:: Lazy ;
8
9
use prost_reflect:: { DynamicMessage , SerializeOptions , Value } ;
9
10
use serde_json:: { json, Map , Value as JsonValue } ;
10
- use std:: {
11
- error:: Error ,
12
- future:: Future ,
13
- io:: Read ,
14
- sync:: { Arc , Mutex } ,
15
- } ;
11
+ use std:: { error:: Error , future:: Future , sync:: Mutex } ;
16
12
use std:: { format, net:: SocketAddr } ;
17
13
use tracing:: * ;
18
14
mod parser;
19
15
mod settings;
20
- use parser:: { Action , LiqiMessage } ;
16
+ use parser:: { Action , LiqiMessage , Parser } ;
17
+ use settings:: Settings ;
21
18
22
19
use crate :: parser:: my_serialize;
23
20
@@ -28,157 +25,162 @@ async fn shutdown_signal() {
28
25
}
29
26
30
27
#[ derive( Clone ) ]
31
- struct ActionHandler {
32
- parser : Arc < Mutex < parser:: Parser > > ,
33
- settings : Arc < settings:: Settings > ,
34
- client : reqwest:: Client ,
35
- }
28
+ struct ActionHandler ;
36
29
37
30
pub const SERIALIZE_OPTIONS : SerializeOptions = SerializeOptions :: new ( )
38
31
. skip_default_fields ( false )
39
32
. use_proto_field_name ( true ) ;
40
33
41
34
pub const RANDOM_MD5 : & str = "0123456789abcdef0123456789abcdef" ;
42
35
36
+ static PARSER : Mutex < Lazy < Parser > > = Mutex :: new ( Lazy :: < Parser , _ > :: new ( Parser :: new) ) ;
37
+ static CLIENT : Lazy < reqwest:: Client > = Lazy :: new ( || {
38
+ reqwest:: ClientBuilder :: new ( )
39
+ . danger_accept_invalid_certs ( true )
40
+ . build ( )
41
+ . expect ( "Failed to create reqwest client" )
42
+ } ) ;
43
+ static SETTINGS : Lazy < Settings > = Lazy :: new ( Settings :: new) ;
44
+
43
45
impl WebSocketHandler for ActionHandler {
44
46
async fn handle_message ( & mut self , _ctx : & WebSocketContext , msg : Message ) -> Option < Message > {
45
47
let direction_char = match _ctx {
46
48
WebSocketContext :: ClientToServer { .. } => '\u{2191}' ,
47
49
WebSocketContext :: ServerToClient { .. } => '\u{2193}' ,
48
50
} ;
49
- if let Message :: Binary ( buf) = & msg {
50
- // convert binary message to hex string
51
- let hex = buf
52
- . iter ( )
53
- . map ( |b| {
54
- if * b >= 0x20 && * b <= 0x7e {
55
- format ! ( "{}" , * b as char )
56
- } else {
57
- format ! ( "{:02x} " , b)
51
+ let msg_clone = msg. clone ( ) ;
52
+ tokio:: spawn ( async move {
53
+ if let Message :: Binary ( buf) = msg_clone {
54
+ // convert binary message to hex string
55
+ let hex = buf
56
+ . iter ( )
57
+ . map ( |b| {
58
+ if * b >= 0x20 && * b <= 0x7e {
59
+ format ! ( "{}" , * b as char )
60
+ } else {
61
+ format ! ( "{:02x} " , b)
62
+ }
63
+ } )
64
+ . collect :: < String > ( ) ;
65
+ debug ! ( "{} {}" , direction_char, hex) ;
66
+ let mut parser = PARSER . lock ( ) . unwrap ( ) ;
67
+ let parsed = parser. parse ( & buf) ;
68
+ let parsed = match parsed {
69
+ Ok ( parsed) => parsed,
70
+ Err ( e) => {
71
+ error ! ( "Failed to parse message: {:?}" , e) ;
72
+ return ;
58
73
}
59
- } )
60
- . collect :: < String > ( ) ;
61
- debug ! ( "{} {}" , direction_char , hex ) ;
62
- let mut parser = self . parser . lock ( ) . unwrap ( ) ;
63
- let parsed = parser . parse ( buf ) ;
64
- let parsed = match parsed {
65
- Ok ( parsed ) => parsed ,
66
- Err ( e ) => {
67
- error ! ( "Failed to parse message: {:?}" , e ) ;
68
- return Some ( msg ) ;
74
+ } ;
75
+ info ! (
76
+ "监听到: {}, {}, {:?}, {}" ,
77
+ direction_char , parsed . id , parsed . msg_type , parsed . method_name
78
+ ) ;
79
+ if direction_char == '\u{2193}' {
80
+ return ;
81
+ }
82
+ if let Err ( e ) = send_message ( parsed ) {
83
+ error ! ( "Failed to send message: {:?}" , e ) ;
69
84
}
70
- } ;
71
- info ! (
72
- "监听到: {}, {}, {:?}, {}" ,
73
- direction_char, parsed. id, parsed. msg_type, parsed. method_name
74
- ) ;
75
- if direction_char == '\u{2193}' {
76
- return Some ( msg) ;
77
- }
78
- if let Err ( e) = self . send_message ( parsed) {
79
- error ! ( "Failed to send message: {:?}" , e) ;
80
85
}
81
- }
86
+ } ) ;
82
87
Some ( msg)
83
88
}
84
89
}
85
90
86
- impl ActionHandler {
87
- fn send_message ( & self , mut parsed : LiqiMessage ) -> Result < ( ) , Box < dyn Error > > {
88
- let settings = self . settings . clone ( ) ;
89
- let json_data: JsonValue ;
90
- if !settings. is_method ( & parsed. method_name ) {
91
+ fn send_message ( mut parsed : LiqiMessage ) -> Result < ( ) , Box < dyn Error > > {
92
+ let json_data: JsonValue ;
93
+ if !SETTINGS . is_method ( & parsed. method_name ) {
94
+ return Ok ( ( ) ) ;
95
+ }
96
+ if parsed. method_name == ".lq.ActionPrototype" {
97
+ let name = parsed
98
+ . data
99
+ . get ( "name" )
100
+ . ok_or ( "No name field" ) ?
101
+ . as_str ( )
102
+ . ok_or ( "name is not a string" ) ?
103
+ . to_owned ( ) ;
104
+ if !SETTINGS . is_action ( & name) {
91
105
return Ok ( ( ) ) ;
92
106
}
93
- if parsed. method_name == ".lq.ActionPrototype" {
94
- let name = parsed
95
- . data
107
+ let data = parsed. data . get_mut ( "data" ) . ok_or ( "No data field" ) ?;
108
+ if name == "ActionNewRound" {
109
+ data. as_object_mut ( )
110
+ . ok_or ( "data is not an object" ) ?
111
+ . insert ( "md5" . to_string ( ) , json ! ( RANDOM_MD5 ) ) ;
112
+ }
113
+ json_data = data. take ( ) ;
114
+ } else if parsed. method_name == ".lq.FastTest.syncGame" {
115
+ let game_restore = parsed
116
+ . data
117
+ . get ( "game_restore" )
118
+ . ok_or ( "No game_restore field" ) ?
119
+ . get ( "actions" )
120
+ . ok_or ( "No actions field" ) ?
121
+ . as_array ( )
122
+ . ok_or ( "actions is not an array" ) ?;
123
+ let mut actions: Vec < Action > = vec ! [ ] ;
124
+ for item in game_restore. iter ( ) {
125
+ let action_name = item
96
126
. get ( "name" )
97
127
. ok_or ( "No name field" ) ?
98
128
. as_str ( )
99
- . ok_or ( "name is not a string" ) ?
100
- . to_owned ( ) ;
101
- if !settings. is_action ( & name) {
102
- return Ok ( ( ) ) ;
103
- }
104
- let data = parsed. data . get_mut ( "data" ) . ok_or ( "No data field" ) ?;
105
- if name == "ActionNewRound" {
106
- data. as_object_mut ( )
107
- . ok_or ( "data is not an object" ) ?
108
- . insert ( "md5" . to_string ( ) , json ! ( RANDOM_MD5 ) ) ;
109
- }
110
- json_data = data. take ( ) ;
111
- } else if parsed. method_name == ".lq.FastTest.syncGame" {
112
- let game_restore = parsed
113
- . data
114
- . get ( "game_restore" )
115
- . ok_or ( "No game_restore field" ) ?
116
- . get ( "actions" )
117
- . ok_or ( "No actions field" ) ?
118
- . as_array ( )
119
- . ok_or ( "actions is not an array" ) ?;
120
- let mut actions: Vec < Action > = vec ! [ ] ;
121
- for item in game_restore. iter ( ) {
122
- let action_name = item
123
- . get ( "name" )
124
- . ok_or ( "No name field" ) ?
125
- . as_str ( )
126
- . ok_or ( "name is not a string" ) ?;
127
- let action_data = item
128
- . get ( "data" )
129
- . ok_or ( "No data field" ) ?
130
- . as_str ( )
131
- . unwrap_or ( "data is not a string" ) ;
132
- if action_data. is_empty ( ) {
133
- let action = Action {
134
- name : action_name. to_string ( ) ,
135
- data : JsonValue :: Object ( Map :: new ( ) ) ,
136
- } ;
137
- actions. push ( action) ;
138
- } else {
139
- let b64 = BASE64_STANDARD . decode ( action_data) ?;
140
- let parser = self . parser . lock ( ) . unwrap ( ) ;
141
- let action_type = parser
142
- . pool
143
- . get_message_by_name ( action_name)
144
- . ok_or ( "Invalid action type" ) ?;
145
- let mut action_obj = DynamicMessage :: decode ( action_type, b64. as_ref ( ) ) ?;
146
- if action_name == ".lq.ActionNewRound" {
147
- action_obj. set_field_by_name ( "md5" , Value :: String ( RANDOM_MD5 . to_string ( ) ) ) ;
148
- }
149
- let value: JsonValue = my_serialize ( action_obj) ?;
150
- let action = Action {
151
- name : action_name. to_string ( ) ,
152
- data : value,
153
- } ;
154
- actions. push ( action) ;
129
+ . ok_or ( "name is not a string" ) ?;
130
+ let action_data = item
131
+ . get ( "data" )
132
+ . ok_or ( "No data field" ) ?
133
+ . as_str ( )
134
+ . unwrap_or ( "data is not a string" ) ;
135
+ if action_data. is_empty ( ) {
136
+ let action = Action {
137
+ name : action_name. to_string ( ) ,
138
+ data : JsonValue :: Object ( Map :: new ( ) ) ,
139
+ } ;
140
+ actions. push ( action) ;
141
+ } else {
142
+ let b64 = BASE64_STANDARD . decode ( action_data) ?;
143
+ let parser = PARSER . lock ( ) . unwrap ( ) ;
144
+ let action_type = parser
145
+ . pool
146
+ . get_message_by_name ( action_name)
147
+ . ok_or ( "Invalid action type" ) ?;
148
+ let mut action_obj = DynamicMessage :: decode ( action_type, b64. as_ref ( ) ) ?;
149
+ if action_name == ".lq.ActionNewRound" {
150
+ action_obj. set_field_by_name ( "md5" , Value :: String ( RANDOM_MD5 . to_string ( ) ) ) ;
155
151
}
152
+ let value: JsonValue = my_serialize ( action_obj) ?;
153
+ let action = Action {
154
+ name : action_name. to_string ( ) ,
155
+ data : value,
156
+ } ;
157
+ actions. push ( action) ;
156
158
}
157
- let mut map = Map :: new ( ) ;
158
- map. insert (
159
- "sync_game_actions" . to_string ( ) ,
160
- serde_json:: to_value ( actions) ?,
161
- ) ;
162
- json_data = JsonValue :: Object ( map) ;
163
- } else {
164
- json_data = parsed. data ;
165
159
}
160
+ let mut map = Map :: new ( ) ;
161
+ map. insert (
162
+ "sync_game_actions" . to_string ( ) ,
163
+ serde_json:: to_value ( actions) ?,
164
+ ) ;
165
+ json_data = JsonValue :: Object ( map) ;
166
+ } else {
167
+ json_data = parsed. data ;
168
+ }
166
169
167
- // post data to API, no verification
168
- let client = self . client . clone ( ) ;
169
- let future = client. post ( & settings. api_url ) . json ( & json_data) . send ( ) ;
170
-
171
- handle_future ( future) ;
172
- info ! ( "已发送: {}" , json_data) ;
170
+ // post data to API, no verification
171
+ let client = CLIENT . clone ( ) ;
172
+ let future = client. post ( & SETTINGS . api_url ) . json ( & json_data) . send ( ) ;
173
173
174
- if let Some ( liqi_data) = json_data. get ( "liqi" ) {
175
- let res = client. post ( & settings. api_url ) . json ( liqi_data) . send ( ) ;
176
- handle_future ( res) ;
177
- info ! ( "已发送: {:?}" , liqi_data) ;
178
- }
174
+ handle_future ( future) ;
175
+ info ! ( "已发送: {}" , json_data) ;
179
176
180
- Ok ( ( ) )
177
+ if let Some ( liqi_data) = json_data. get ( "liqi" ) {
178
+ let res = client. post ( & SETTINGS . api_url ) . json ( liqi_data) . send ( ) ;
179
+ handle_future ( res) ;
180
+ info ! ( "已发送: {:?}" , liqi_data) ;
181
181
}
182
+
183
+ Ok ( ( ) )
182
184
}
183
185
184
186
fn handle_future (
@@ -221,33 +223,12 @@ async fn main() {
221
223
请遵守当地法律法规,对于使用本程序所产生的任何后果,作者概不负责!
222
224
\x1b [0m"
223
225
) ;
224
- let parser = parser:: Parser :: new ( ) ;
225
- let settings = settings:: Settings :: new ( ) ;
226
- let settings = match settings {
227
- Ok ( settings) => settings,
228
- Err ( e) => {
229
- error ! ( "{}" , e) ;
230
- // press any key to exit
231
- println ! ( "按任意键退出" ) ;
232
- let mut stdin = std:: io:: stdin ( ) ;
233
- let _ = stdin. read ( & mut [ 0u8 ] ) . unwrap_or_default ( ) ;
234
- return ;
235
- }
236
- } ;
237
- let client = reqwest:: ClientBuilder :: new ( )
238
- . danger_accept_invalid_certs ( true )
239
- . build ( )
240
- . expect ( "Failed to create reqwest client" ) ;
241
226
242
227
let proxy = Proxy :: builder ( )
243
228
. with_addr ( SocketAddr :: from ( ( [ 127 , 0 , 0 , 1 ] , 23410 ) ) )
244
229
. with_rustls_client ( )
245
230
. with_ca ( ca)
246
- . with_websocket_handler ( ActionHandler {
247
- parser : Arc :: new ( Mutex :: new ( parser) ) ,
248
- settings : Arc :: new ( settings) ,
249
- client,
250
- } )
231
+ . with_websocket_handler ( ActionHandler )
251
232
. with_graceful_shutdown ( shutdown_signal ( ) )
252
233
. build ( ) ;
253
234
0 commit comments