Skip to content

Commit

Permalink
feat: internal impl for send_message
Browse files Browse the repository at this point in the history
  • Loading branch information
pk5ls20 committed Feb 15, 2025
1 parent 0596be7 commit 57a0127
Show file tree
Hide file tree
Showing 38 changed files with 886 additions and 129 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ uuid = { version = "1.12.1", features = ["serde", "v4"] }

[profile.release]
opt-level = 2
debug = false
debug = true
lto = true
incremental = false
codegen-units = 1
Expand Down
2 changes: 1 addition & 1 deletion README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
| | | | | LightApp | 🟢 | ~~Voice Call~~ | 🔴 | GroupInvite | 🟢 |
| | | | | LongMsg | 🟡[^1] | Client Key | 🔴 | GroupRequestJoin | 🟢 |
| | | | | Markdown | 🔴 | Cookies | 🔴 | FriendRequest | 🟢 |
| | | | | MarketFace | 🟡[^1] | Send Message | 🔴 | ~~FriendTyping~~ | 🔴 |
| | | | | MarketFace | 🟡[^1] | Send Message | 🟡 | ~~FriendTyping~~ | 🔴 |
| | | | | Mention | 🟢 | | | ~~FriendVoiceCall~~ | 🔴 |
| | | | | MultiMsg | 🟡[^1] | | | | |
| | | | | Poke | 🔴 | | | | |
Expand Down
65 changes: 50 additions & 15 deletions examples/multi_login.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use mania::event::group::GroupEvent;
use mania::message::builder::MessageChainBuilder;
use mania::{Client, ClientConfig, DeviceInfo, KeyStore};
use std::fs;
use std::io::stdout;
Expand Down Expand Up @@ -48,44 +50,75 @@ async fn main() {
});
let need_login = key_store.is_expired();
let mut client = Client::new(config, device, key_store).await.unwrap();
let operator = client.handle().operator();
let mut event_listener = operator.event_listener.clone();

let op = client.handle().operator().clone();
let send_op = client.handle().operator().clone();
let mut group_receiver = op.event_listener.group.clone();
let mut system_receiver = op.event_listener.system.clone();
let mut friend_receiver = op.event_listener.friend.clone();

tokio::spawn(async move {
loop {
tokio::select! {
_ = event_listener.system.changed() => {
if let Some(ref be) = *event_listener.system.borrow() {
tracing::info!("[SystemEvent] {:?}", be);
_ = system_receiver.changed() => {
if let Some(ref se) = *system_receiver.borrow() {
tracing::info!("[SystemEvent] {:?}", se);
}
}
_ = event_listener.friend.changed() => {
if let Some(ref fe) = *event_listener.friend.borrow() {
_ = friend_receiver.changed() => {
if let Some(ref fe) = *friend_receiver.borrow() {
tracing::info!("[FriendEvent] {:?}", fe);
}
}
_ = event_listener.group.changed() => {
if let Some(ref ge) = *event_listener.group.borrow() {
tracing::info!("[GroupEvent] {:?}", ge);
_ = group_receiver.changed() => {
let maybe_data = {
let guard = group_receiver.borrow();
if let Some(ref ge) = *guard {
tracing::info!("[GroupEvent] {:?}", ge);
match ge {
GroupEvent::GroupMessage(gme) => {
if let mania::message::chain::MessageType::Group(gmeu) = &gme.chain.typ {
let chain_str = gme.chain.to_string();
Some((chain_str, gmeu.group_uin))
} else {
None
}
}
_ => None,
}
} else {
None
}
};
if let Some((chain_str, group_uin)) = maybe_data {
if chain_str.contains("/mania ping") {
let chain = MessageChainBuilder::group(group_uin)
.text("pong")
.build();
send_op.send_message(chain).await.unwrap();
}
}
}
}
}
});

tokio::spawn(async move {
client.spawn().await;
});

if need_login {
tracing::warn!("Session is invalid, need to login again!");
let login_res: Result<(), String> = async {
let (url, bytes) = operator.fetch_qrcode().await.map_err(|e| e.to_string())?;
let (url, bytes) = op.fetch_qrcode().await.map_err(|e| e.to_string())?;
let qr_code_name = format!("qrcode_{}.png", Uuid::new_v4());
fs::write(&qr_code_name, &bytes).map_err(|e| e.to_string())?;
tracing::info!(
"QR code fetched successfully! url: {}, saved to {}",
url,
qr_code_name
);
let login_res = operator.login_by_qrcode().await.map_err(|e| e.to_string());
let login_res = op.login_by_qrcode().await.map_err(|e| e.to_string());
match fs::remove_file(&qr_code_name).map_err(|e| e.to_string()) {
Ok(_) => tracing::info!("QR code file {} deleted successfully", qr_code_name),
Err(e) => tracing::error!("Failed to delete QR code file {}: {}", qr_code_name, e),
Expand All @@ -99,15 +132,17 @@ async fn main() {
} else {
tracing::info!("Session is still valid, trying to online...");
}
let _tx = match operator.online().await {

let _tx = match op.online().await {
Ok(tx) => tx,
Err(e) => {
panic!("Failed to set online status: {:?}", e);
}
};
operator
.update_key_store()

op.update_key_store()
.save("keystore.json")
.unwrap_or_else(|e| tracing::error!("Failed to save key store: {:?}", e));

tokio::signal::ctrl_c().await.unwrap();
}
48 changes: 47 additions & 1 deletion mania-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,58 @@ use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use quote::quote;
use syn::{
Data, DeriveInput, Fields, ItemFn, ItemStruct, LitInt, LitStr, Path, Token,
Data, DeriveInput, Fields, ItemFn, ItemStruct, LitBool, LitInt, LitStr, Path, Token,
parse::{Parse, ParseStream},
parse_macro_input,
punctuated::Punctuated,
};

struct PackContentArgs {
need_pack: LitBool,
}

impl Parse for PackContentArgs {
fn parse(input: ParseStream) -> syn::Result<Self> {
let need_pack = input.parse()?;
Ok(Self { need_pack })
}
}

#[proc_macro_attribute]
pub fn pack_content(attr: TokenStream, item: TokenStream) -> TokenStream {
let args = parse_macro_input!(attr as PackContentArgs);
let input_struct = parse_macro_input!(item as ItemStruct);
let ident = &input_struct.ident;
let expend = match args.need_pack.value {
true => {
quote! {
#input_struct
impl crate::message::entity::MessageContentImplChecker for #ident {
fn need_pack(&self) -> bool {
true
}
}
}
}
false => {
quote! {
#input_struct
impl crate::message::entity::MessageContentImplChecker for #ident {
fn need_pack(&self) -> bool {
true
}
}
impl crate::message::entity::MessageContentImpl for #ident {
fn pack_content(&self) -> Option<bytes::Bytes> {
None
}
}
}
}
};
expend.into()
}

#[proc_macro_attribute]
pub fn command(attr: TokenStream, item: TokenStream) -> TokenStream {
let command_str = parse_macro_input!(attr as LitStr);
Expand Down
90 changes: 88 additions & 2 deletions mania/src/core/business/messaging_logic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::core::business::LogicRegistry;
use crate::core::business::{BusinessHandle, LogicFlow};
use crate::core::event::message::push_msg::PushMessageEvent;
use crate::core::event::message::send_message::SendMessageEvent;
use crate::core::event::notify::bot_sys_rename::BotSysRenameEvent;
use crate::core::event::notify::friend_sys_new::FriendSysNewEvent;
use crate::core::event::notify::friend_sys_poke::FriendSysPokeEvent;
Expand All @@ -25,6 +26,7 @@ use crate::core::event::notify::group_sys_request_join::GroupSysRequestJoinEvent
use crate::core::event::notify::group_sys_special_title::GroupSysSpecialTitleEvent;
use crate::core::event::notify::group_sys_todo::GroupSysTodoEvent;
use crate::core::event::prelude::*;
use crate::entity::bot_group_member::FetchGroupMemberStrategy;
use crate::event::friend::friend_poke::FriendPokeEvent;
use crate::event::friend::{
FriendEvent, friend_message, friend_new, friend_recall, friend_rename, friend_request,
Expand All @@ -47,6 +49,7 @@ use mania_macros::handle_event;
use std::sync::Arc;

#[handle_event(
SendMessageEvent,
PushMessageEvent,
GroupSysRequestJoinEvent,
GroupSysInviteEvent,
Expand Down Expand Up @@ -94,7 +97,7 @@ async fn messaging_logic_incoming(
if let Some(msg) = event.as_any_mut().downcast_mut::<PushMessageEvent>() {
if let Some(mut chain) = msg.chain.take() {
resolve_incoming_chain(&mut chain, handle.clone()).await;
// TODO: await ResolveChainMetadata(push.Chain);
resolve_chain_metadata(&mut chain, handle.clone()).await;
// TODO: MessageFilter.Filter(push.Chain);
// TODO?: sb tx! Collection.Invoker.PostEvent(new GroupInvitationEvent(groupUin, chain.FriendUin, sequence));
match &chain.typ {
Expand Down Expand Up @@ -844,7 +847,90 @@ async fn resolve_incoming_chain(chain: &mut MessageChain, handle: Arc<BusinessHa

async fn messaging_logic_outgoing(
event: &mut dyn ServerEvent,
_: Arc<BusinessHandle>,
handle: Arc<BusinessHandle>,
) -> &dyn ServerEvent {
match event {
_ if let Some(send) = event.as_any_mut().downcast_mut::<SendMessageEvent>() => {
resolve_chain_metadata(&mut send.chain, handle.clone()).await;
resolve_outgoing_chain(&mut send.chain, handle.clone()).await;
// TODO: await Collection.Highway.UploadResources(send.Chain);
}
_ => {}
}
event
}

async fn resolve_outgoing_chain(_: &mut MessageChain, _: Arc<BusinessHandle>) {}

// TODO: return result!!!
async fn resolve_chain_metadata(
chain: &mut MessageChain,
handle: Arc<BusinessHandle>,
) -> &mut MessageChain {
match chain.typ {
MessageType::Group(ref mut grp)
if handle.context.config.fetch_group_member_strategy
== FetchGroupMemberStrategy::Full =>
{
let members = handle
.fetch_maybe_cached_group_members(
grp.group_uin,
|mm| {
mm.get(&grp.group_uin)
.map(|entry| entry.value().clone())
.unwrap_or_else(|| {
tracing::warn!(
"No group members found for group: {}",
grp.group_uin
);
Vec::new()
})
},
false,
)
.await
.unwrap_or_else(|e| {
tracing::error!("Failed to fetch group members: {:?}", e);
Vec::new()
});
let lookup_uin = if chain.friend_uin == 0 {
**handle.context.key_store.uin.load()
} else {
chain.friend_uin
};
grp.group_member_info = members.into_iter().find(|member| member.uin == lookup_uin);
if chain.uid.is_empty()
&& let Some(member) = &grp.group_member_info
{
chain.uid = member.uid.clone();
}
chain
}

// TODO: optimization
MessageType::Friend(ref mut friend_elem) => {
let friends = handle
.fetch_maybe_cached_friends(
Some(chain.friend_uin),
|fm| fm.iter().map(|entry| entry.value().clone()).collect(),
false,
)
.await
.unwrap_or_else(|e| {
tracing::error!("Failed to fetch friends: {:?}", e);
Vec::new()
});
if let Some(friend) = friends
.into_iter()
.find(|friend| friend.uin == chain.friend_uin)
{
friend_elem.friend_info = Some(friend.clone());
if chain.uid.is_empty() {
chain.uid = friend.uid.clone();
}
}
chain
}
_ => chain,
}
}
3 changes: 3 additions & 0 deletions mania/src/core/context.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use crate::ClientConfig;
use crate::core::crypto::consts::ECDH_256_PEER_LOGIN_KEY;
use crate::core::crypto::{Ecdh, P256};
use crate::core::key_store::KeyStore;
use crate::core::session::Session;
use crate::core::sign::SignProvider;
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use std::{fs, io};
use uuid::Uuid;

Expand All @@ -22,6 +24,7 @@ pub struct Context {
pub(crate) sign_provider: Box<dyn SignProvider>,
pub(crate) crypto: Crypto,
pub(crate) session: Session,
pub(crate) config: Arc<ClientConfig>,
}

pub struct Crypto {
Expand Down
1 change: 1 addition & 0 deletions mania/src/core/event/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ pub mod multi_msg_download;
pub mod push_msg;
pub mod record_c2c_download;
pub mod record_group_download;
pub mod send_message;
pub mod video_c2c_download;
pub mod video_group_download;
4 changes: 2 additions & 2 deletions mania/src/core/event/message/multi_msg_download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl ClientEvent for MultiMsgDownloadEvent {
Ok(BinaryPacket(packet.encode_to_vec().into()))
}

fn parse(packet: Bytes, _: &Context) -> CEParseResult {
fn parse(packet: Bytes, ctx: &Context) -> CEParseResult {
let packet = RecvLongMsgResp::decode(packet)?;
let inflate = packet
.result
Expand All @@ -55,7 +55,7 @@ impl ClientEvent for MultiMsgDownloadEvent {
.ok_or_else(|| EventError::OtherError("Failed to find action_data".to_string()))?
.msg_body
.into_iter()
.map(MessagePacker::parse_fake_chain)
.map(|body| MessagePacker::parse_fake_chain(body, ctx))
.collect::<Result<Vec<MessageChain>, String>>()
.map_err(EventError::OtherError)?;
Ok(ClientResult::single(Box::new(dda!(
Expand Down
18 changes: 12 additions & 6 deletions mania/src/core/event/message/push_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,23 @@ impl ClientEvent for PushMessageEvent {
| PkgType::TempMessage
| PkgType::PrivateRecordMessage => {
chain = Some(
MessagePacker::parse_chain(packet.message.ok_or_else(|| {
EventError::OtherError("PushMsgBody is None".to_string())
})?)
MessagePacker::parse_chain(
packet.message.ok_or_else(|| {
EventError::OtherError("PushMsgBody is None".to_string())
})?,
ctx,
)
.map_err(|e| EventError::OtherError(format!("parse_chain failed: {}", e)))?,
);
}
PkgType::PrivateFileMessage => {
chain = Some(
MessagePacker::parse_private_file(packet.message.ok_or_else(|| {
EventError::OtherError("PushMsgBody is None".to_string())
})?)
MessagePacker::parse_private_file(
packet.message.ok_or_else(|| {
EventError::OtherError("PushMsgBody is None".to_string())
})?,
ctx,
)
.map_err(|e| {
EventError::OtherError(format!("parse_file_chain failed: {}", e))
})?,
Expand Down
Loading

0 comments on commit 57a0127

Please sign in to comment.