Skip to content

Commit

Permalink
feat: impl record parse
Browse files Browse the repository at this point in the history
  • Loading branch information
pk5ls20 committed Feb 6, 2025
1 parent ed20f81 commit 46eb7fe
Show file tree
Hide file tree
Showing 9 changed files with 343 additions and 10 deletions.
2 changes: 1 addition & 1 deletion README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
|----------|:-------:|----------------------------|:-------:|:--------------|:-------:|:------------------|:-------:|:--------------------|:-------:|
| Windows | 🔴 | QrCode | 🟢 | BounceFace | 🔴 | Poke | 🔴 | Captcha | 🔴 |
| macOS | 🔴 | ~~Password~~ | 🔴 | Face | 🟡 [^1] | Recall | 🔴 | BotOnline | 🔴 |
| Linux | 🟢 | EasyLogin | 🟢 | File | 🟡[^1] | Leave Group | 🔴 | BotOffline | 🔴 |
| Linux | 🟢 | EasyLogin | 🟡 | File | 🟡[^1] | Leave Group | 🔴 | BotOffline | 🔴 |
| | | UnusualDevice<br/>Password | 🔴 | Forward | 🟡[^1] | Set Special Title | 🔴 | Message | 🔴 |
| | | UnusualDevice<br/>Easy | 🔴 | ~~GreyTip~~ | 🔴 | Kick Member | 🔴 | Poke | 🔴 |
| | | ~~NewDeviceVerify~~ | 🔴 | GroupReaction | 🔴 | Mute Member | 🔴 | MessageRecall | 🔴 |
Expand Down
55 changes: 55 additions & 0 deletions mania/src/core/business/messaging_logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,61 @@ async fn messaging_logic_incoming(
_ => None,
}
}
Entity::Record(ref mut record) => {
let node = || -> Option<_> {
record
.msg_info
.as_ref()
.and_then(|info| info.msg_info_body.first())
.and_then(|node| node.index.clone())
};
let url_result = match (&record.msg_info, &record.audio_uuid) {
(Some(_), _) => match &chain.typ {
MessageType::Group(grp) => {
handle
.download_group_record_by_node(
grp.group_uin,
node(),
)
.await
}
MessageType::Friend(_) | MessageType::Temp => {
handle.download_c2c_record_by_node(node()).await
}
_ => continue,
},
(None, Some(uuid)) => match &chain.typ {
MessageType::Group(grp) => {
handle
.download_group_record_by_uuid(
grp.group_uin,
Some(uuid.clone()),
)
.await
}
MessageType::Friend(_) | MessageType::Temp => {
handle
.download_c2c_record_by_uuid(Some(uuid.clone()))
.await
}
_ => continue,
},
_ => {
tracing::error!(
"{:?} Missing msg_info or audio_uuid!",
record
);
continue;
}
};
record.audio_url = match url_result {
Ok(url) => url,
Err(e) => {
tracing::error!("Failed to download record: {:?}", e);
continue;
}
}
}
_ => {}
}
}
Expand Down
2 changes: 2 additions & 0 deletions mania/src/core/event/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ pub mod image_c2c_download;
pub mod image_group_download;
pub mod multi_msg_download;
pub mod push_msg;
pub mod record_c2c_download;
pub mod record_group_download;
20 changes: 14 additions & 6 deletions mania/src/core/event/message/push_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,24 @@ impl ClientEvent for PushMessageEvent {
PkgType::try_from(typ).map_err(|_| EventError::UnknownOlpushMessageTypeError(typ))?;
let mut chain = MessageChain::default(); // FIXME: maybe exist better way to handle this
match packet_type {
PkgType::PrivateMessage | PkgType::GroupMessage | PkgType::TempMessage => {
chain = MessagePacker::parse_chain(packet.message.expect("PushMsgBody is None"))
PkgType::PrivateMessage
| PkgType::GroupMessage
| PkgType::TempMessage
| PkgType::PrivateRecordMessage => {
chain =
MessagePacker::parse_chain(packet.message.ok_or_else(|| {
EventError::OtherError("PushMsgBody is None".to_string())
})?)
.map_err(|e| EventError::OtherError(format!("parse_chain failed: {}", e)))?;
}
PkgType::PrivateFileMessage => {
chain =
MessagePacker::parse_private_file(packet.message.expect("PushMsgBody is None"))
.map_err(|e| {
EventError::OtherError(format!("parse_private_file failed: {}", e))
})?;
MessagePacker::parse_private_file(packet.message.ok_or_else(|| {
EventError::OtherError("PushMsgBody is None".to_string())
})?)
.map_err(|e| {
EventError::OtherError(format!("parse_file_chain failed: {}", e))
})?;
}
// TODO: handle other message types
_ => {
Expand Down
64 changes: 64 additions & 0 deletions mania/src/core/event/message/record_c2c_download.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::core::event::prelude::*;
use crate::core::protos::service::oidb::{
C2cUserInfo, ClientMeta, CommonHead, DownloadExt, DownloadReq, IndexNode, MultiMediaReqHead,
Ntv2RichMediaReq, Ntv2RichMediaResp, SceneInfo, VideoDownloadExt,
};

#[commend("OidbSvcTrpcTcp.0x126d_200")]
#[derive(Debug, ServerEvent, Default)]
pub struct RecordC2CDownloadEvent {
pub self_uid: String,
pub node: Option<IndexNode>,
pub file_uuid: String,
pub audio_url: String,
}

impl ClientEvent for RecordC2CDownloadEvent {
fn build(&self, _: &Context) -> BinaryPacket {
let packet = dda!(Ntv2RichMediaReq {
req_head: Some(MultiMediaReqHead {
common: Some(CommonHead {
request_id: 1,
command: 200,
}),
scene: Some(dda!(SceneInfo {
request_type: 1,
business_type: 3,
scene_type: 1,
c2c: Some(C2cUserInfo {
account_type: 2,
target_uid: self.self_uid.to_owned(),
}),
})),
client: Some(ClientMeta { agent_type: 2 }),
}),
download: Some(DownloadReq {
node: Some(self.node.clone().unwrap_or(dda!(IndexNode {
file_uuid: self.file_uuid.to_owned(), // TODO: mut?
}),)),
download: Some(dda!(DownloadExt {
video: Some(dda!(VideoDownloadExt {
busi_type: 0,
scene_type: 0,
}))
})),
}),
});
OidbPacket::new(0x126D, 200, packet.encode_to_vec(), false, true).to_binary()
}

fn parse(packet: Bytes, _: &Context) -> Result<Box<dyn ServerEvent>, EventError> {
let packet = OidbPacket::parse_into::<Ntv2RichMediaResp>(packet)?;
let download = packet.download.ok_or(EventError::OtherError(
"Missing Ntv2RichMediaResp download response".to_string(),
))?;
let info = download.info.as_ref().ok_or(EventError::OtherError(
"Missing Ntv2RichMediaResp download info".to_string(),
))?;
let url = format!(
"https://{}{}{}",
info.domain, info.url_path, download.r_key_param
);
Ok(Box::new(dda!(RecordC2CDownloadEvent { audio_url: url })))
}
}
63 changes: 63 additions & 0 deletions mania/src/core/event/message/record_group_download.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use crate::core::event::prelude::*;
use crate::core::protos::service::oidb::{
ClientMeta, CommonHead, DownloadExt, DownloadReq, IndexNode, MultiMediaReqHead, NtGroupInfo,
Ntv2RichMediaReq, Ntv2RichMediaResp, SceneInfo, VideoDownloadExt,
};

#[commend("OidbSvcTrpcTcp.0x126e_200")]
#[derive(Debug, ServerEvent, Default)]
pub struct RecordGroupDownloadEvent {
pub group_uin: u32,
pub node: Option<IndexNode>,
pub file_uuid: String,
pub audio_url: String,
}

impl ClientEvent for RecordGroupDownloadEvent {
fn build(&self, _: &Context) -> BinaryPacket {
let packet = dda!(Ntv2RichMediaReq {
req_head: Some(MultiMediaReqHead {
common: Some(CommonHead {
request_id: 4,
command: 200,
}),
scene: Some(dda!(SceneInfo {
request_type: 1,
business_type: 3,
scene_type: 2,
group: Some(NtGroupInfo {
group_uin: self.group_uin,
}),
})),
client: Some(ClientMeta { agent_type: 2 }),
}),
download: Some(DownloadReq {
node: Some(self.node.clone().unwrap_or(dda!(IndexNode {
file_uuid: self.file_uuid.to_owned(), // TODO: mut?
}),)),
download: Some(dda!(DownloadExt {
video: Some(dda!(VideoDownloadExt {
busi_type: 0,
scene_type: 0,
}))
})),
}),
});
OidbPacket::new(0x126E, 200, packet.encode_to_vec(), false, true).to_binary()
}

fn parse(packet: Bytes, _: &Context) -> Result<Box<dyn ServerEvent>, EventError> {
let packet = OidbPacket::parse_into::<Ntv2RichMediaResp>(packet)?;
let download = packet.download.ok_or(EventError::OtherError(
"Missing Ntv2RichMediaResp download response".to_string(),
))?;
let info = download.info.as_ref().ok_or(EventError::OtherError(
"Missing Ntv2RichMediaResp download info".to_string(),
))?;
let url = format!(
"https://{}{}{}",
info.domain, info.url_path, download.r_key_param
);
Ok(Box::new(dda!(RecordGroupDownloadEvent { audio_url: url })))
}
}
74 changes: 74 additions & 0 deletions mania/src/core/operation/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use crate::core::event::message::file_group_download::FileGroupDownloadEvent;
use crate::core::event::message::image_c2c_download::ImageC2CDownloadEvent;
use crate::core::event::message::image_group_download::ImageGroupDownloadEvent;
use crate::core::event::message::multi_msg_download::MultiMsgDownloadEvent;
use crate::core::event::message::record_c2c_download::RecordC2CDownloadEvent;
use crate::core::event::message::record_group_download::RecordGroupDownloadEvent;
use crate::core::event::system::fetch_rkey::FetchRKeyEvent;
use crate::core::event::{downcast_event, downcast_mut_event};
use crate::core::protos::service::oidb::IndexNode;
Expand Down Expand Up @@ -102,4 +104,76 @@ impl BusinessHandle {
let event: &mut FileC2CDownloadEvent = downcast_mut_event(&mut *res).unwrap();
Ok(event.file_url.to_owned())
}

// TODO: Should parameter requests use an enum?
pub(crate) async fn download_group_record_by_node(
self: &Arc<Self>,
group_uin: u32,
node: Option<IndexNode>,
) -> crate::Result<String> {
self.download_group_record_inner(group_uin, node, None)
.await
}

pub(crate) async fn download_group_record_by_uuid(
self: &Arc<Self>,
group_uin: u32,
audio_uuid: Option<String>,
) -> crate::Result<String> {
self.download_group_record_inner(group_uin, None, audio_uuid)
.await
}

async fn download_group_record_inner(
self: &Arc<Self>,
group_uin: u32,
node: Option<IndexNode>,
audio_uuid: Option<String>,
) -> crate::Result<String> {
let mut event = dda!(RecordGroupDownloadEvent {
group_uin,
node,
file_uuid: audio_uuid.unwrap_or_default(),
});
let mut res = self.send_event(&mut event).await?;
let event: &mut RecordGroupDownloadEvent = downcast_mut_event(&mut *res).unwrap();
Ok(event.audio_url.to_owned())
}

// TODO: Should parameter requests use an enum?
pub(crate) async fn download_c2c_record_by_node(
self: &Arc<Self>,
node: Option<IndexNode>,
) -> crate::Result<String> {
self.download_c2c_record_inner(node, None).await
}

pub(crate) async fn download_c2c_record_by_uuid(
self: &Arc<Self>,
audio_uuid: Option<String>,
) -> crate::Result<String> {
self.download_c2c_record_inner(None, audio_uuid).await
}

async fn download_c2c_record_inner(
self: &Arc<Self>,
node: Option<IndexNode>,
audio_uuid: Option<String>,
) -> crate::Result<String> {
let self_uid = self
.context
.key_store
.uid
.load()
.as_ref()
.map(|arc| arc.as_ref().clone());
let mut event = dda!(RecordC2CDownloadEvent {
self_uid: self_uid.expect("Missing self_uid"),
node,
file_uuid: audio_uuid.unwrap_or_default(),
});
let mut res = self.send_event(&mut event).await?;
let event: &mut RecordC2CDownloadEvent = downcast_mut_event(&mut *res).unwrap();
Ok(event.audio_url.to_owned())
}
}
13 changes: 10 additions & 3 deletions mania/src/message/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod light_app;
pub mod market_face;
pub mod mention;
pub mod multi_msg;
pub mod record;
pub mod text;

pub use face::FaceEntity as Face;
Expand All @@ -18,6 +19,7 @@ pub use light_app::LightAppEntity as LightApp;
pub use market_face::MarketFaceEntity as MarketFace;
pub use mention::MentionEntity as Mention;
pub use multi_msg::MultiMsgEntity as MultiMsg;
pub use record::RecordEntity as Record;
pub use text::TextEntity as Text;

use crate::core::protos::message::Elem;
Expand Down Expand Up @@ -45,6 +47,7 @@ pub enum Entity {
MultiMsg(multi_msg::MultiMsgEntity),
Mention(mention::MentionEntity),
File(file::FileEntity),
Record(record::RecordEntity),
}

macro_rules! impl_entity_show {
Expand Down Expand Up @@ -106,10 +109,14 @@ macro_rules! impl_entity_unpack {
}
}

impl_entity_show!(Text, Json, Image, Face, Forward, MarketFace, LightApp, MultiMsg, Mention, File);
impl_entity_pack!(Text, Json, Image, Face, Forward, MarketFace, LightApp, MultiMsg, Mention, File);
impl_entity_show!(
Text, Json, Image, Face, Forward, MarketFace, LightApp, MultiMsg, Mention, File, Record
);
impl_entity_pack!(
Text, Json, Image, Face, Forward, MarketFace, LightApp, MultiMsg, Mention, File, Record
);
impl_entity_unpack!(
Text, Json, Image, Face, Forward, MarketFace, LightApp, MultiMsg, Mention, File
Text, Json, Image, Face, Forward, MarketFace, LightApp, MultiMsg, Mention, File, Record
);

impl Entity {
Expand Down
Loading

0 comments on commit 46eb7fe

Please sign in to comment.