diff --git a/README.MD b/README.MD index 69a8d0f..850495b 100644 --- a/README.MD +++ b/README.MD @@ -27,7 +27,7 @@ | Linux | 🟢 | EasyLogin | 🟡 | File | 🟡[^1] | Leave Group | 🔴 | BotOffline | 🟢 | | | | ~~UnusualDevice
Password~~ | 🔴 | Forward | 🟢 | Set Special Title | 🔴 | Message | 🟢 | | | | ~~UnusualDevice
Easy~~ | 🔴 | ~~GreyTip~~ | 🔴 | Kick Member | 🔴 | Poke | 🟢 | -| | | ~~NewDeviceVerify~~ | 🔴 | GroupReaction | 🟡[^1] | Mute Member | 🔴 | MessageRecall | 🔴 | +| | | ~~NewDeviceVerify~~ | 🔴 | GroupReaction | 🟡[^1] | Mute Member | 🔴 | MessageRecall | 🟢 | | | | | | Image | 🟢 | Set Admin | 🔴 | GroupMemberDecrease | 🔴 | | | | | | Json | 🟢 | Friend Request | 🔴 | GroupMemberIncrease | 🔴 | | | | | | KeyBoard | 🔴 | Group Request | 🔴 | GroupPromoteAdmin | 🔴 | diff --git a/mania/src/core/business/messaging_logic.rs b/mania/src/core/business/messaging_logic.rs index e3928ed..6b5ff28 100644 --- a/mania/src/core/business/messaging_logic.rs +++ b/mania/src/core/business/messaging_logic.rs @@ -1,13 +1,16 @@ use crate::core::business::LogicRegistry; use crate::core::business::{BusinessHandle, LogicFlow}; use crate::core::event::message::push_msg::PushMessageEvent; +use crate::core::event::notify::friend_sys_recall::FriendSysRecallEvent; use crate::core::event::notify::group_sys_poke::GroupSysPokeEvent; use crate::core::event::notify::group_sys_reaction::GroupSysReactionEvent; +use crate::core::event::notify::group_sys_recall::GroupSysRecallEvent; use crate::core::event::notify::group_sys_request_join::GroupSysRequestJoinEvent; use crate::core::event::prelude::*; -use crate::event::friend::{FriendEvent, friend_message}; +use crate::event::friend::{FriendEvent, friend_message, friend_recall}; use crate::event::group::group_poke::GroupPokeEvent; use crate::event::group::group_reaction::GroupReactionEvent; +use crate::event::group::group_recall::GroupRecallEvent; use crate::event::group::{GroupEvent, group_join_request, group_message}; use crate::event::system::{SystemEvent, temp_message}; use crate::message::chain::{MessageChain, MessageType}; @@ -20,7 +23,9 @@ use std::sync::Arc; PushMessageEvent, GroupSysRequestJoinEvent, GroupSysPokeEvent, - GroupSysReactionEvent + GroupSysReactionEvent, + GroupSysRecallEvent, + FriendSysRecallEvent )] async fn messaging_logic( event: &mut dyn ServerEvent, @@ -170,6 +175,56 @@ async fn messaging_logic_incoming( } return event; } + if let Some(recall) = event.as_any_mut().downcast_mut::() { + if let Err(e) = handle + .event_dispatcher + .group + .send(Some(GroupEvent::GroupRecall(GroupRecallEvent { + group_uin: recall.group_uin, + author_uin: handle + .uid2uin(&recall.author_uid, Some(recall.group_uin)) + .await + .unwrap_or_default(), + operator_uin: if let Some(uid) = recall.operator_uid.as_ref() { + handle + .uid2uin(uid, Some(recall.group_uin)) + .await + .unwrap_or_default() + } else { + 0 + }, + sequence: recall.sequence, + time: recall.time, + random: recall.random, + tip: recall.tip.to_owned(), + }))) + { + tracing::error!("Failed to send group recall event: {:?}", e); + } + return event; + } + if let Some(recall) = event.as_any_mut().downcast_mut::() { + if let Err(e) = + handle + .event_dispatcher + .friend + .send(Some(FriendEvent::FriendRecallEvent( + friend_recall::FriendRecallEvent { + friend_uin: handle + .uid2uin(&recall.from_uid, None) + .await + .unwrap_or_default(), + client_sequence: recall.client_sequence, + time: recall.time, + random: recall.random, + tip: recall.tip.to_owned(), + }, + ))) + { + tracing::error!("Failed to send friend recall event: {:?}", e); + } + return event; + } } event } diff --git a/mania/src/core/event/message/push_msg.rs b/mania/src/core/event/message/push_msg.rs index fb1adfa..42a6da6 100644 --- a/mania/src/core/event/message/push_msg.rs +++ b/mania/src/core/event/message/push_msg.rs @@ -1,8 +1,10 @@ +use crate::core::event::notify::friend_sys_recall::FriendSysRecallEvent; use crate::core::event::notify::group_sys_poke::GroupSysPokeEvent; use crate::core::event::notify::group_sys_reaction::GroupSysReactionEvent; +use crate::core::event::notify::group_sys_recall::GroupSysRecallEvent; use crate::core::event::notify::group_sys_request_join::GroupSysRequestJoinEvent; use crate::core::event::prelude::*; -use crate::core::protos::message::{GroupJoin, NotifyMessageBody, PushMsg}; +use crate::core::protos::message::{FriendRecall, GroupJoin, NotifyMessageBody, PushMsg}; use crate::message::chain::MessageChain; use crate::message::packer::MessagePacker; @@ -131,6 +133,9 @@ impl ClientEvent for PushMessageEvent { PkgType::Event0x2DC => { extra = process_event_0x2dc(&packet, &mut extra)?.take(); } + PkgType::Event0x210 => { + extra = process_event_0x210(&packet, &mut extra)?.take(); + } // TODO: handle other message types _ => { tracing::warn!("receive unknown message type: {:?}", packet_type); @@ -140,6 +145,19 @@ impl ClientEvent for PushMessageEvent { } } +fn extract_fucking_head(msg_content: &Vec) -> Result<(u32, T), EventError> +where + T: prost::Message + Default, +{ + let mut packet_reader = PacketReader::new(Bytes::from(msg_content.to_owned())); + let group_uin = packet_reader.u32(); + packet_reader.u8(); + let proto = + packet_reader.read_with_length::<_, { PREFIX_U16 | PREFIX_LENGTH_ONLY }>(|p| p.bytes()); + let msg_body = T::decode(proto)?; + Ok((group_uin, msg_body)) +} + #[allow(clippy::single_match)] // FIXME: fn process_event_0x2dc<'a>( packet: &'a PushMsg, @@ -183,12 +201,7 @@ fn process_event_0x2dc<'a>( Some(content) => content, None => return Ok(extra), }; - let mut packet_reader = PacketReader::new(Bytes::from(msg_content.to_owned())); - let group_uin = packet_reader.u32(); - packet_reader.u8(); - let proto = packet_reader - .read_with_length::<_, { PREFIX_U16 | PREFIX_LENGTH_ONLY }>(|p| p.bytes()); - let msg_body = NotifyMessageBody::decode(proto)?; + let (group_uin, msg_body) = extract_fucking_head::(msg_content)?; match Event0x2DCSubType16Field13::try_from(msg_body.field13.unwrap_or_default()) { Ok(ev) => match ev { Event0x2DCSubType16Field13::GroupReactionNotice => { @@ -221,6 +234,37 @@ fn process_event_0x2dc<'a>( } } } + Event0x2DCSubType::GroupRecallNotice => { + let msg_content = match packet + .message + .as_ref() + .and_then(|m| m.body.as_ref()) + .and_then(|b| b.msg_content.as_ref()) + { + Some(content) => content, + None => return Ok(extra), + }; + let (_, recall_notify) = extract_fucking_head::(msg_content)?; + let recall = recall_notify.recall.ok_or(EventError::OtherError( + "Missing recall meta in 0x2dc sub type 17".into(), + ))?; + let tip_info = recall.tip_info.unwrap_or_default(); + let meta = recall + .recall_messages + .first() + .ok_or(EventError::OtherError( + "Missing recall message in 0x2dc sub type 17".into(), + ))?; + extra.as_mut().unwrap().push(Box::new(GroupSysRecallEvent { + group_uin: recall_notify.group_uin, + author_uid: meta.author_uid.to_owned(), + operator_uid: recall.operator_uid, + sequence: meta.sequence as u32, + time: meta.time, + random: meta.random, + tip: tip_info.tip, + })); + } Event0x2DCSubType::GroupGreyTipNotice => { let msg_content = match packet .message @@ -231,12 +275,7 @@ fn process_event_0x2dc<'a>( Some(content) => content, None => return Ok(extra), }; - let mut packet_reader = PacketReader::new(Bytes::from(msg_content.to_owned())); - let group_uin = packet_reader.u32(); - packet_reader.u8(); - let proto = packet_reader - .read_with_length::<_, { PREFIX_U16 | PREFIX_LENGTH_ONLY }>(|p| p.bytes()); - let grey_tip = NotifyMessageBody::decode(proto)?; + let (group_uin, grey_tip) = extract_fucking_head::(msg_content)?; let gray_tip_info = match grey_tip.gray_tip_info.as_ref() { Some(info) if info.busi_type == 12 => info, _ => return Ok(extra), @@ -282,3 +321,73 @@ fn process_event_0x2dc<'a>( } Ok(extra) } + +#[allow(clippy::single_match)] // FIXME: +fn process_event_0x210<'a>( + packet: &'a PushMsg, + extra: &'a mut Option>>, +) -> Result<&'a mut Option>>, EventError> { + let sub_type = Event0x210SubType::try_from( + packet + .message + .as_ref() + .ok_or(EventError::OtherError( + "Cannot get message in PushMsg".to_string(), + ))? + .content_head + .as_ref() + .ok_or(EventError::OtherError( + "Cannot get content_head in PushMsg".to_string(), + ))? + .sub_type + .ok_or(EventError::OtherError( + "Cannot get sub_type in PushMsgContentHead".to_string(), + ))?, + ); + let sub_type = match sub_type { + Ok(sub_type) => sub_type, + Err(_) => { + tracing::warn!( + "receive unknown olpush message 0x210 sub type: {:?}", + sub_type + ); + return Ok(extra); + } + }; + match sub_type { + Event0x210SubType::FriendRecallNotice => { + let msg_content = match packet + .message + .as_ref() + .and_then(|m| m.body.as_ref()) + .and_then(|b| b.msg_content.as_ref()) + { + Some(content) => content, + None => return Ok(extra), + }; + let response_head = match packet + .message + .as_ref() + .and_then(|m| m.response_head.as_ref()) + { + Some(content) => content, + None => return Ok(extra), + }; + let friend_request = FriendRecall::decode(Bytes::from(msg_content.to_owned()))?; + let info = friend_request.info.ok_or(EventError::OtherError( + "Missing friend request info in 0x210 sub type 138".into(), + ))?; + extra.as_mut().unwrap().push(Box::new(FriendSysRecallEvent { + from_uid: response_head.from_uid.to_owned().unwrap_or_default(), + client_sequence: info.sequence, + time: info.time, + random: info.random, + tip: info.tip_info.unwrap_or_default().tip.unwrap_or_default(), + })); + } + _ => { + tracing::warn!("receive unknown message 0x210 sub type: {:?}", sub_type); + } + } + Ok(extra) +} diff --git a/mania/src/core/event/notify/friend_sys_recall.rs b/mania/src/core/event/notify/friend_sys_recall.rs new file mode 100644 index 0000000..8709555 --- /dev/null +++ b/mania/src/core/event/notify/friend_sys_recall.rs @@ -0,0 +1,10 @@ +use crate::core::event::prelude::*; + +#[derive(Debug, DummyEvent, Default)] +pub struct FriendSysRecallEvent { + pub from_uid: String, + pub client_sequence: u32, + pub time: u32, + pub random: u32, + pub tip: String, +} diff --git a/mania/src/core/event/notify/group_sys_recall.rs b/mania/src/core/event/notify/group_sys_recall.rs new file mode 100644 index 0000000..f90a373 --- /dev/null +++ b/mania/src/core/event/notify/group_sys_recall.rs @@ -0,0 +1,12 @@ +use crate::core::event::prelude::*; + +#[derive(Debug, DummyEvent, Default)] +pub struct GroupSysRecallEvent { + pub group_uin: u32, + pub author_uid: String, + pub operator_uid: Option, + pub sequence: u32, + pub time: u32, + pub random: u32, + pub tip: String, +} diff --git a/mania/src/core/event/notify/mod.rs b/mania/src/core/event/notify/mod.rs index 232a00e..dc61f3e 100644 --- a/mania/src/core/event/notify/mod.rs +++ b/mania/src/core/event/notify/mod.rs @@ -1,3 +1,5 @@ +pub mod friend_sys_recall; pub mod group_sys_poke; pub mod group_sys_reaction; +pub mod group_sys_recall; pub mod group_sys_request_join; diff --git a/mania/src/core/protos/message/notify.proto b/mania/src/core/protos/message/notify.proto index 4110d64..797e542 100644 --- a/mania/src/core/protos/message/notify.proto +++ b/mania/src/core/protos/message/notify.proto @@ -20,6 +20,11 @@ message FriendRecallInfo { uint32 PkgNum = 7; uint32 PkgIndex = 8; uint32 DivSeq = 9; + FriendRecallTipInfo TipInfo = 13; +} + +message FriendRecallTipInfo { + optional string Tip = 2; } message NewFriend { @@ -157,6 +162,11 @@ message GroupRecall { bytes UserDef = 5; int32 GroupType = 6; int32 OpType = 7; + GroupRecallTipInfo TipInfo = 9; +} + +message GroupRecallTipInfo { + string Tip = 2; } message RecallMessage { diff --git a/mania/src/event/friend.rs b/mania/src/event/friend.rs index 2a1f354..399f60b 100644 --- a/mania/src/event/friend.rs +++ b/mania/src/event/friend.rs @@ -1,9 +1,11 @@ pub mod friend_message; pub mod friend_poke; +pub mod friend_recall; #[derive(Debug)] #[allow(clippy::large_enum_variant)] // FIXME: do we need spilt or refactoring? pub enum FriendEvent { FriendPokeEvent(friend_poke::FriendPokeEvent), // FIXME: clippy warn: at least 80 bytes FriendMessageEvent(friend_message::FriendMessageEvent), // FIXME: clippy warn: at least 320 bytes + FriendRecallEvent(friend_recall::FriendRecallEvent), } diff --git a/mania/src/event/friend/friend_recall.rs b/mania/src/event/friend/friend_recall.rs new file mode 100644 index 0000000..b4c7aa3 --- /dev/null +++ b/mania/src/event/friend/friend_recall.rs @@ -0,0 +1,10 @@ +pub use mania_macros::ManiaEvent; + +#[derive(ManiaEvent)] +pub struct FriendRecallEvent { + pub friend_uin: u32, + pub client_sequence: u32, + pub time: u32, + pub random: u32, + pub tip: String, +}