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,
+}