diff --git a/connect.py b/connect.py index 0733340..286f905 100644 --- a/connect.py +++ b/connect.py @@ -188,13 +188,13 @@ async def add_message(data: Dict[str, Any]): room_id = data['roomId'] if not is_self: - if data.get('message').get('content') == '/bot': + if content == '/bot': message = Message(content='icalingua bot test', room_id=data['roomId']) await sio.emit('sendMessage', message.to_json()) - elif data.get('message').get('content').startswith('=='): + elif content.startswith('=='): - evals: str = data.get('message').get('content')[2:] + evals: str = content[2:] # quene = multiprocessing.Queue() # def run(quene, evals): @@ -226,7 +226,7 @@ async def add_message(data: Dict[str, Any]): await asyncio.sleep(random.random() * 2) await sio.emit('sendMessage', message.to_json()) - elif data['message']['content'] == '!!jrrp': + elif content == '!!jrrp': randomer = random.Random(f'{sender_id}-{data["message"]["date"]}-jrrp-v2') result = randomer.randint(0, 50) + randomer.randint(0, 50) print(f'{sender_name} 今日人品值为 {result}') diff --git a/ica-rs/Cargo.lock b/ica-rs/Cargo.lock index bdb9111..0b81553 100644 --- a/ica-rs/Cargo.lock +++ b/ica-rs/Cargo.lock @@ -545,6 +545,7 @@ dependencies = [ "hex", "rust_socketio", "serde_json", + "toml", ] [[package]] @@ -1026,6 +1027,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1248,6 +1258,40 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -1613,6 +1657,15 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +[[package]] +name = "winnow" +version = "0.5.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/ica-rs/Cargo.toml b/ica-rs/Cargo.toml index 03b0c91..2afab5f 100644 --- a/ica-rs/Cargo.toml +++ b/ica-rs/Cargo.toml @@ -11,6 +11,7 @@ ed25519-dalek = "2.1.0" hex = "0.4.3" rust_socketio = "0.4.4" serde_json = "1.0.108" +toml = "0.8.8" [patch.crates-io] -rust_socketio = { path = "../../../rust-socketio/socketio" } \ No newline at end of file +rust_socketio = { path = "../../../rust-socketio/socketio" } diff --git a/ica-rs/src/client.rs b/ica-rs/src/client.rs index c3d1e0e..b8dd086 100644 --- a/ica-rs/src/client.rs +++ b/ica-rs/src/client.rs @@ -1,25 +1,65 @@ +use serde_json::Value; use ed25519_dalek::{Signature, Signer, SigningKey}; +use rust_socketio::{ClientBuilder, Event, Payload, RawClient}; pub struct IcalinguaSinger { pub host: String, - pub pub_key: SigningKey, + pub private_key: SigningKey, } impl IcalinguaSinger { - pub fn new(host: String, pub_key: &str) -> Self { + pub fn new_from_config(config_file_path: String) -> Self { + // try read config from file + let config = std::fs::read_to_string(config_file_path).expect("Failed to read config file"); + let config: toml::Value = toml::from_str(&config).expect("Failed to parse config file"); + let host = config["host"] + .as_str() + .expect("host should be string") + .to_string(); + let pub_key = config["private_key"] + .as_str() + .expect("private_key should be string") + .to_string(); + + Self::new_from_raw(host, pub_key) + } + + pub fn new_from_raw(host: String, pub_key: String) -> Self { let array_key: [u8; 32] = hex::decode(pub_key).unwrap().try_into().unwrap(); let signing_key: SigningKey = SigningKey::from_bytes(&array_key); Self { host, - pub_key: signing_key, + private_key: signing_key, } } pub fn sign_for_salt(&self, salt: String) -> Vec { let salt: Vec = hex::decode(salt).unwrap(); - let signature: Signature = self.pub_key.sign(salt.as_slice()); + let signature: Signature = self.private_key.sign(salt.as_slice()); signature.to_bytes().to_vec() } + + pub fn sign_callback(&self, payload: Payload, client: RawClient, _id: Option) { + let require_data = match payload { + Payload::Text(json_value) => Some(json_value), + _ => None, + } + .expect("Payload should be Json data"); + + let (auth_key, version) = (&require_data[0], &require_data[1]); + // println!("auth_key: {:?}, version: {:?}", auth_key, version); + let auth_key = match &require_data.get(0) { + Some(Value::String(auth_key)) => Some(auth_key), + _ => None, + } + .expect("auth_key should be string"); + + let salt = hex::decode(auth_key).expect("Got an invalid salt from the server"); + let signature: Signature = self.private_key.sign(salt.as_slice()); + + let sign = signature.to_bytes().to_vec(); + client.emit("auth", sign).unwrap(); + } } diff --git a/ica-rs/src/main.rs b/ica-rs/src/main.rs index 405715b..72f3d09 100644 --- a/ica-rs/src/main.rs +++ b/ica-rs/src/main.rs @@ -5,68 +5,50 @@ use rust_socketio::{ClientBuilder, Event, Payload, RawClient}; use serde_json::Value; use std::time::Duration; -#[allow(unused)] -fn require_auth_callback(payload: Payload, client: RawClient, _id: Option) { - let key = std::env::args().nth(2).expect("No key given"); - let require_data = match payload { - Payload::Text(json_value) => Some(json_value), - _ => None, - } - .expect("Payload should be Json data"); - - let (auth_key, version) = (&require_data[0], &require_data[1]); - // println!("auth_key: {:?}, version: {:?}", auth_key, version); - let auth_key = match &require_data.get(0) { - Some(Value::String(auth_key)) => Some(auth_key), - _ => None, - } - .expect("auth_key should be string"); - - let array_key: [u8; 32] = hex::decode(key) - .expect("Key should be hex") - .try_into() - .expect("Key should be 32 bytes"); - - let signing_key = SigningKey::from_bytes(&array_key); - - let salt = hex::decode(auth_key).expect("Got an invalid salt from the server"); - let signature: Signature = signing_key.sign(salt.as_slice()); - // let sign = hex::encode(signature.to_bytes()); - let sign = signature.to_bytes().to_vec(); - client.emit("auth", sign).unwrap(); -} - #[allow(unused)] fn any_event(event: Event, payload: Payload, _client: RawClient, id: Option) { - println!("event: {} |{:?}|id{:?}", event, payload, id) + match payload { + Payload::Binary(ref data) => { + println!("event: {} |{:?}|id{:?}", event, data, id) + } + Payload::Text(ref data) => { + print!("\x1b[35mevent: {event}\x1b[0m"); + for value in data { + print!("|{}", value.to_string()); + } + println!("|id:{:?}|", id); + } + _ => (), + } + // println!("event: {} |{:?}|id{:?}", event, payload, id) } fn ws_main() { // define a callback which is called when a payload is received // this callback gets the payload as well as an instance of the // socket to communicate with the server - let connect_call_back = |payload: Payload, _client: RawClient, _id| { - match payload { - Payload::Text(values) => { - if let Some(value) = values.first() { - if let Some("authSucceed") = value.as_str() { - println!("\x1b[32m已经登录到 icalingua!\x1b[0m"); - } + let connect_call_back = |payload: Payload, _client: RawClient, _id| match payload { + Payload::Text(values) => { + if let Some(value) = values.first() { + if let Some("authSucceed") = value.as_str() { + println!("\x1b[32m已经登录到 icalingua!\x1b[0m"); } - }, - _ => () + } } + _ => (), }; // 从命令行获取 host 和 key - let host = std::env::args().nth(1).expect("No host given"); + // 从命令行获取配置文件路径 + let config_path = std::env::args().nth(1).expect("No config path given"); + let ica_singer = client::IcalinguaSinger::new_from_config(config_path); // get a socket that is connected to the admin namespace - let socket = ClientBuilder::new(host) + let socket = ClientBuilder::new(ica_singer.host.clone()) // .namespace("/admin") .on_any(any_event) .on("message", connect_call_back) - .on("requireAuth", require_auth_callback) + .on("requireAuth", move |a, b, c| ica_singer.sign_callback(a, b, c)) .connect() .expect("Connection failed");