Skip to content

Commit

Permalink
feat & refactor: impl cache logic, some events & minor refactor
Browse files Browse the repository at this point in the history
- feat: impl cache mod
- feat: impl parse event `GroupRequestJoin`
- feat: impl internal event `FetchFilteredGroupRequestsEvent`, `FetchGroupRequestsEvent`, `FetchUserInfoEvent`
- feat: impl op `cache_ops`, `resolve_stranger_uid2uin`, `fetch_group_requests`
- refactor: message logic
- refactor: client config parse
  • Loading branch information
pk5ls20 committed Feb 11, 2025
1 parent 8c1dcb0 commit 590f436
Show file tree
Hide file tree
Showing 26 changed files with 902 additions and 154 deletions.
46 changes: 23 additions & 23 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,29 @@

## Features List

| Protocol | Support | Login | Support | Messages | Support | Operations | Support | Events | Support |
|----------|:-------:|----------------------------|:-------:|:--------------|:-------:|:------------------|:-------:|:--------------------|:-------:|
| Windows | 🔴 | QrCode | 🟢 | BounceFace | 🔴 | Poke | 🔴 | ~~Captcha~~ | 🔴 |
| macOS | 🔴 | ~~Password~~ | 🔴 | Face | 🟡 [^1] | Recall | 🔴 | BotOnline | 🟢 |
| Linux | 🟢 | EasyLogin | 🟡 | File | 🟡[^1] | Leave Group | 🔴 | BotOffline | 🟢 |
| | | UnusualDevice<br/>Password | 🔴 | Forward | 🟢 | Set Special Title | 🔴 | Message | 🟢 |
| | | UnusualDevice<br/>Easy | 🔴 | ~~GreyTip~~ | 🔴 | Kick Member | 🔴 | Poke | 🟢 |
| | | ~~NewDeviceVerify~~ | 🔴 | GroupReaction | 🔴 | Mute Member | 🔴 | MessageRecall | 🔴 |
| | | | | Image | 🟢 | Set Admin | 🔴 | GroupMemberDecrease | 🔴 |
| | | | | Json | 🟢 | Friend Request | 🔴 | GroupMemberIncrease | 🔴 |
| | | | | KeyBoard | 🔴 | Group Request | 🔴 | GroupPromoteAdmin | 🔴 |
| | | | | LightApp | 🟢 | ~~Voice Call~~ | 🔴 | GroupInvite | 🔴 |
| | | | | LongMsg | 🟡[^1] | Client Key | 🔴 | GroupRequestJoin | 🔴 |
| | | | | Markdown | 🔴 | Cookies | 🔴 | FriendRequest | 🔴 |
| | | | | MarketFace | 🟡[^1] | Send Message | 🔴 | ~~FriendTyping~~ | 🔴 |
| | | | | Mention | 🟢 | | | ~~FriendVoiceCall~~ | 🔴 |
| | | | | MultiMsg | 🟡[^1] | | | | |
| | | | | Poke | 🔴 | | | | |
| | | | | Record | 🟢 | | | | |
| | | | | SpecialPoke | 🔴 | | | | |
| | | | | Text | 🟢 | | | | |
| | | | | Video | 🟢 | | | | |
| | | | | Xml | 🟢 | | | | |
| Protocol | Support | Login | Support | Messages | Support | Operations | Support | Events | Support |
|----------|:-------:|--------------------------------|:-------:|:--------------|:-------:|:------------------|:-------:|:--------------------|:-------:|
| Windows | 🔴 | QrCode | 🟢 | BounceFace | 🔴 | Poke | 🔴 | ~~Captcha~~ | 🔴 |
| macOS | 🔴 | ~~Password~~ | 🔴 | Face | 🟡 [^1] | Recall | 🔴 | BotOnline | 🟢 |
| Linux | 🟢 | EasyLogin | 🟡 | File | 🟡[^1] | Leave Group | 🔴 | BotOffline | 🟢 |
| | | ~~UnusualDevice<br/>Password~~ | 🔴 | Forward | 🟢 | Set Special Title | 🔴 | Message | 🟢 |
| | | ~~UnusualDevice<br/>Easy~~ | 🔴 | ~~GreyTip~~ | 🔴 | Kick Member | 🔴 | Poke | 🟢 |
| | | ~~NewDeviceVerify~~ | 🔴 | GroupReaction | 🔴 | Mute Member | 🔴 | MessageRecall | 🔴 |
| | | | | Image | 🟢 | Set Admin | 🔴 | GroupMemberDecrease | 🔴 |
| | | | | Json | 🟢 | Friend Request | 🔴 | GroupMemberIncrease | 🔴 |
| | | | | KeyBoard | 🔴 | Group Request | 🔴 | GroupPromoteAdmin | 🔴 |
| | | | | LightApp | 🟢 | ~~Voice Call~~ | 🔴 | GroupInvite | 🔴 |
| | | | | LongMsg | 🟡[^1] | Client Key | 🔴 | GroupRequestJoin | 🟢 |
| | | | | Markdown | 🔴 | Cookies | 🔴 | FriendRequest | 🔴 |
| | | | | MarketFace | 🟡[^1] | Send Message | 🔴 | ~~FriendTyping~~ | 🔴 |
| | | | | Mention | 🟢 | | | ~~FriendVoiceCall~~ | 🔴 |
| | | | | MultiMsg | 🟡[^1] | | | | |
| | | | | Poke | 🔴 | | | | |
| | | | | Record | 🟢 | | | | |
| | | | | SpecialPoke | 🔴 | | | | |
| | | | | Text | 🟢 | | | | |
| | | | | Video | 🟢 | | | | |
| | | | | Xml | 🟢 | | | | |

[^1]: Only implemented event parsing

Expand Down
9 changes: 6 additions & 3 deletions mania/src/core/business.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ use std::pin::Pin;
use std::sync::Arc;
use std::time::Duration;

use crate::core::cache::Cache;
use crate::ClientConfig;
pub use crate::core::cache::Cache;
use crate::core::connect::optimum_server;
use crate::core::context::Context;
use crate::core::event::prelude::*;
use crate::core::event::{CEParse, resolve_event};
Expand Down Expand Up @@ -110,7 +112,8 @@ pub struct Business {
}

impl Business {
pub async fn new(addr: SocketAddr, context: Arc<Context>) -> BusinessResult<Self> {
pub async fn new(config: Arc<ClientConfig>, context: Arc<Context>) -> BusinessResult<Self> {
let addr = optimum_server(config.get_optimum_server, config.use_ipv6_network).await?;
let (sender, receiver) = socket::connect(addr).await?;
let event_dispatcher = EventDispatcher::new();
let event_listener = EventListener::new(&event_dispatcher);
Expand All @@ -119,7 +122,7 @@ impl Business {
reconnecting: Mutex::new(()),
pending_requests: DashMap::new(),
context,
cache: Arc::new(Cache::new()),
cache: Arc::new(Cache::new(config.cache_mode)), // TODO: construct from context
event_dispatcher,
event_listener,
});
Expand Down
138 changes: 95 additions & 43 deletions mania/src/core/business/messaging_logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ 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::group::group_poke::GroupPokeEvent;
use crate::event::group::{GroupEvent, group_message};
use crate::event::group::{GroupEvent, group_join_request, group_message};
use crate::event::system::{SystemEvent, temp_message};
use crate::message::chain::{MessageChain, MessageType};
use crate::message::entity::Entity;
Expand All @@ -31,66 +31,118 @@ async fn messaging_logic_incoming(
event: &mut dyn ServerEvent,
handle: Arc<BusinessHandle>,
) -> &dyn ServerEvent {
match event {
_ if let Some(msg) = event.as_any_mut().downcast_mut::<PushMessageEvent>() => {
{
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);
// TODO: MessageFilter.Filter(push.Chain);
// TODO?: sb tx! Collection.Invoker.PostEvent(new GroupInvitationEvent(groupUin, chain.FriendUin, sequence));
match &chain.typ {
MessageType::Group(_) => {
handle
.event_dispatcher
.group
.send(Some(GroupEvent::GroupMessage(
group_message::GroupMessageEvent { chain },
)))
.expect("Failed to send group_message event");
if let Err(e) =
handle
.event_dispatcher
.group
.send(Some(GroupEvent::GroupMessage(
group_message::GroupMessageEvent { chain },
)))
{
tracing::error!("Failed to send group_message event: {:?}", e);
}
}
MessageType::Friend(_) => {
handle
.event_dispatcher
.friend
.send(Some(FriendEvent::FriendMessageEvent(
friend_message::FriendMessageEvent { chain },
)))
.expect("Failed to send friend_message event");
if let Err(e) = handle.event_dispatcher.friend.send(Some(
FriendEvent::FriendMessageEvent(friend_message::FriendMessageEvent {
chain,
}),
)) {
tracing::error!("Failed to send friend_message event: {:?}", e);
}
}
MessageType::Temp => {
handle
.event_dispatcher
.system
.send(Some(SystemEvent::TempMessageEvent(
temp_message::TempMessageEvent { chain },
)))
.expect("Failed to send temp_message event");
if let Err(e) = handle.event_dispatcher.system.send(Some(
SystemEvent::TempMessageEvent(temp_message::TempMessageEvent { chain }),
)) {
tracing::error!("Failed to send temp_message event: {:?}", e);
}
}
_ => {}
}
} else {
tracing::warn!("Empty message chain in PushMessageEvent");
}
return event;
}
_ if let Some(event) = event
}
{
if let Some(req) = event
.as_any_mut()
.downcast_mut::<GroupSysRequestJoinEvent>() =>
.downcast_mut::<GroupSysRequestJoinEvent>()
{
tracing::debug!("Handling GroupSysRequestJoinEvent: {:?}", event); // TODO: dispatch
let target_uin = match handle.resolve_stranger_uid2uin(&req.target_uid).await {
Ok(uin) => uin,
Err(e) => {
tracing::error!(
"Failed to resolve stranger uid for {}: {:?}",
req.target_uid,
e
);
return event;
}
};
let requests = match handle.fetch_group_requests().await {
Ok(r) => r,
Err(e) => {
tracing::error!("Failed to fetch group requests: {:?}", e);
return event;
}
};
if let Some(r) = requests
.iter()
.find(|r| r.group_uin == req.group_uin && r.target_member_uin == target_uin)
{
if let Err(e) =
handle
.event_dispatcher
.group
.send(Some(GroupEvent::GroupJoinRequest(
group_join_request::GroupJoinRequestEvent {
group_uin: req.group_uin,
target_uin,
target_nickname: r.target_member_card.to_owned(),
invitor_uin: r.invitor_member_uin.unwrap_or_default(),
answer: r.comment.to_owned().unwrap_or_default(),
request_seq: r.sequence,
},
)))
{
tracing::error!("Failed to send group join request event: {:?}", e);
}
} else {
tracing::warn!("No group join request found for target: {}", target_uin);
}
return event;
}
}
{
if let Some(poke) = event.as_any_mut().downcast_mut::<GroupSysPokeEvent>() {
if let Err(e) = handle
.event_dispatcher
.group
.send(Some(GroupEvent::GroupPoke(GroupPokeEvent {
group_uin: poke.group_uin,
operator_uin: poke.operator_uin,
target_uin: poke.target_uin,
action: poke.action.to_owned(),
suffix: poke.suffix.to_owned(),
action_img_url: poke.action_img_url.to_owned(),
})))
{
tracing::error!("Failed to send group poke event: {:?}", e);
}
return event;
}
_ if let Some(event) = event.as_any_mut().downcast_mut::<GroupSysPokeEvent>() => handle
.event_dispatcher
.group
.send(Some(GroupEvent::GroupPoke(GroupPokeEvent {
group_uin: event.group_uin,
operator_uin: event.operator_uin,
target_uin: event.target_uin,
action: event.action.to_owned(),
suffix: event.suffix.to_owned(),
action_img_url: event.action_img_url.to_owned(),
})))
.expect("Failed to send group event"),
_ => {}
}
event
}
Expand Down Expand Up @@ -229,9 +281,9 @@ async fn resolve_incoming_chain(chain: &mut MessageChain, handle: Arc<BusinessHa
let download_result = match &chain.typ {
MessageType::Group(grp) => {
let uid = handle
.resolve_uid(Some(grp.group_uin), chain.friend_uin)
.await;
let uid = uid.unwrap_or_default();
.uin2uid(chain.friend_uin, Some(grp.group_uin))
.await
.unwrap_or_default();
match handle
.download_video(
&uid,
Expand Down
60 changes: 52 additions & 8 deletions mania/src/core/cache.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,64 @@
use crate::entity::bot_friend::BotFriend;
use crate::entity::bot_group_member::BotGroupMember;
use dashmap::DashMap;
use tokio::sync::RwLock;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CacheMode {
Full,
Half,
None,
}

pub struct Cache {
pub uin2uid: DashMap<u32, String>,
pub cached_friends: RwLock<Vec<BotFriend>>,
pub cached_group_members: DashMap<u32, Vec<BotGroupMember>>,
pub(crate) cache_mode: CacheMode,
pub(crate) uin2uid: Option<DashMap<u32, String>>,
pub(crate) uid2uin: Option<DashMap<String, u32>>,
pub(crate) cached_friends: Option<DashMap<u32, BotFriend>>,
pub(crate) cached_group_members: Option<DashMap<u32, Vec<BotGroupMember>>>,
}

impl Cache {
pub fn new() -> Self {
pub fn new(cache_mode: CacheMode) -> Self {
match cache_mode {
CacheMode::Full => Self::full(),
CacheMode::Half => Self::half(),
CacheMode::None => Self::none(),
}
}

fn full() -> Self {
Self {
uin2uid: DashMap::new(),
cached_friends: RwLock::new(Vec::new()),
cached_group_members: DashMap::new(),
cache_mode: CacheMode::Full,
uin2uid: Some(DashMap::new()),
uid2uin: Some(DashMap::new()),
cached_friends: Some(DashMap::new()),
cached_group_members: Some(DashMap::new()),
}
}

fn half() -> Self {
Self {
cache_mode: CacheMode::Half,
uin2uid: None,
uid2uin: None,
cached_friends: Some(DashMap::new()),
cached_group_members: Some(DashMap::new()),
}
}

fn none() -> Self {
Self {
cache_mode: CacheMode::None,
uin2uid: None,
uid2uin: None,
cached_friends: None,
cached_group_members: None,
}
}

pub(crate) fn insert_uin_uid(&self, uin: u32, uid: String) {
// SAFETY: we can ensure that the DashMap is not None
self.uin2uid.as_ref().unwrap().insert(uin, uid.clone());
self.uid2uin.as_ref().unwrap().insert(uid, uin);
}
}
9 changes: 4 additions & 5 deletions mania/src/core/context.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::{fs, io};
use uuid::Uuid;

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::{fs, io};
use uuid::Uuid;

#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
pub enum Protocol {
Expand Down
1 change: 1 addition & 0 deletions mania/src/core/entity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod fetch_group_requests;
15 changes: 15 additions & 0 deletions mania/src/core/entity/fetch_group_requests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#[derive(Debug, Default)]
pub struct FetchGroupRequests {
pub group_uin: u32,
pub invitor_member_uid: Option<String>,
pub invitor_member_card: Option<String>,
pub target_member_uid: String,
pub target_member_card: String,
pub operator_uid: Option<String>,
pub operator_name: Option<String>,
pub sequence: u64,
pub state: u32,
pub event_type: u32,
pub comment: Option<String>,
pub is_filtered: bool,
}
Loading

0 comments on commit 590f436

Please sign in to comment.