Skip to content
This repository was archived by the owner on Jan 18, 2026. It is now read-only.

Commit 709a8c3

Browse files
committed
feat & refactor: implement video element parsing, basic caching & misc refactors
- feat: implement video element parsing (group videos using fallback logic) - feat: add basic caching required for video parsing - refactor: prefer using ok_or_else over ok_or - refactor: propagate errors appropriately - refactor: rename example package multi-login to multi_login
1 parent 27904d2 commit 709a8c3

31 files changed

+944
-78
lines changed

examples/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ default = []
1919
tokio-tracing = ["console-subscriber"]
2020

2121
[[example]]
22-
name = "multi-login"
23-
path = "./multi-login.rs"
22+
name = "multi_login"
23+
path = "multi_login.rs"
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,12 @@ async fn main() {
6666
} else {
6767
tracing::info!("Session is still valid, trying to online...");
6868
}
69-
if let Err(e) = operator.online().await {
70-
panic!("Failed to set online status: {:?}", e);
71-
}
69+
let _tx = match operator.online().await {
70+
Ok(tx) => tx,
71+
Err(e) => {
72+
panic!("Failed to set online status: {:?}", e);
73+
}
74+
};
7275
tracing::info!("Login successfully!");
7376
operator
7477
.update_key_store()

flake.nix

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,12 @@
121121
// {
122122
inherit cargoArtifacts;
123123
cargoExtraArgs = ''
124-
--example multi-login
124+
--example multi_login
125125
'';
126126
postInstall = ''
127127
mkdir -p $out/bin
128128
129-
cp ./target/release/examples/multi-login $out/bin/mania
129+
cp ./target/release/examples/multi_login $out/bin/mania
130130
'';
131131
}
132132
);

mania/src/core/business.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::pin::Pin;
1212
use std::sync::Arc;
1313
use std::time::Duration;
1414

15+
use crate::core::cache::Cache;
1516
use crate::core::context::Context;
1617
use crate::core::event::prelude::*;
1718
use crate::core::event::resolve_event;
@@ -98,6 +99,7 @@ impl Business {
9899
reconnecting: Mutex::new(()),
99100
pending_requests: DashMap::new(),
100101
context,
102+
cache: Arc::new(Cache::new()),
101103
});
102104

103105
Ok(Self {
@@ -120,7 +122,7 @@ impl Business {
120122
let handle = self.handle.clone();
121123
tokio::spawn(async move {
122124
if let Err(e) = handle.dispatch_sso_packet(packet).await {
123-
tracing::error!("Error handling packet: {}", e);
125+
tracing::error!("Unhandled error occurred when handling packet: {}", e);
124126
// FIXME: Non-required reconnections, except for serious errors
125127
// self.reconnect().await;
126128
}
@@ -168,8 +170,9 @@ impl Business {
168170
pub struct BusinessHandle {
169171
sender: ArcSwap<PacketSender>,
170172
reconnecting: Mutex<()>,
171-
pending_requests: DashMap<u32, oneshot::Sender<Box<dyn ServerEvent>>>,
173+
pending_requests: DashMap<u32, oneshot::Sender<Result<Box<dyn ServerEvent>>>>,
172174
pub(crate) context: Arc<Context>,
175+
pub(crate) cache: Arc<Cache>,
173176
// TODO: (outer) event dispatcher, highway
174177
}
175178

@@ -197,18 +200,21 @@ impl BusinessHandle {
197200
packet: SsoPacket,
198201
) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
199202
let sequence = packet.sequence();
200-
let mut event = resolve_event(packet, &self.context).await?;
203+
let result: Result<Box<dyn ServerEvent>> = async {
204+
// TODO: refactor error type?
205+
let mut event = resolve_event(packet, &self.context)
206+
.await
207+
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
208+
dispatch_logic(&mut *event, self.clone(), LogicFlow::InComing).await;
209+
Ok(event)
210+
}
211+
.await;
201212
// Lagrange.Core.Internal.Context.BusinessContext.HandleIncomingEvent
202-
// 在 send_event 中的 handle incoming event 合并到这里来 (aka dispatch_logic)
203-
// GroupSysDecreaseEvent, ... -> Lagrange.Core.Internal.Context.Logic.Implementation.CachingLogic.Incoming
204-
// KickNTEvent -> Lagrange.Core.Internal.Context.Logic.Implementation.WtExchangeLogic.Incoming
205-
// PushMessageEvent, ... -> Lagrange.Core.Internal.Context.Logic.Implementation.MessagingLogic.Incoming
206-
dispatch_logic(&mut *event, self.clone(), LogicFlow::InComing).await;
207213
// TODO: timeout auto remove
208214
if let Some((_, tx)) = self.pending_requests.remove(&sequence) {
209-
tx.send(event).unwrap();
215+
tx.send(result).unwrap();
210216
} else {
211-
tracing::warn!("unhandled packet: {:?}", event);
217+
tracing::warn!("unhandled packet: {:?}", result);
212218
}
213219
Ok(())
214220
}
@@ -245,10 +251,9 @@ impl BusinessHandle {
245251
async fn send_packet(&self, packet: SsoPacket) -> Result<Box<dyn ServerEvent>> {
246252
tracing::debug!("sending packet: {:?}", packet);
247253
let sequence = packet.sequence();
248-
let (tx, rx) = oneshot::channel();
254+
let (tx, rx) = oneshot::channel::<Result<Box<dyn ServerEvent>>>();
249255
self.pending_requests.insert(sequence, tx);
250256
self.post_packet(packet).await?;
251-
let events = rx.await.expect("response not received");
252-
Ok(events)
257+
rx.await.expect("response not received")
253258
}
254259
}

mania/src/core/business/messaging_logic.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ async fn messaging_logic_incoming(
3535
for entity in &mut chain.entities {
3636
match *entity {
3737
Entity::Image(ref mut image) => {
38-
if !image.url.contains("&rkey=") {
38+
if image.url.contains("&rkey=") {
3939
continue;
4040
}
4141
let index_node = match image
@@ -176,6 +176,70 @@ async fn messaging_logic_incoming(
176176
}
177177
}
178178
}
179+
Entity::Video(ref mut video) => {
180+
let file_name = video.file_name.as_ref();
181+
let empty_option = Some(String::new());
182+
let node = video.node.clone();
183+
let download_result = match &chain.typ {
184+
MessageType::Group(grp) => {
185+
// TODO: old impl (0x11e9_200?)
186+
let uid = handle
187+
.resolve_uid(Some(grp.group_uin), chain.friend_uin)
188+
.await;
189+
let uid = uid.unwrap_or_default();
190+
match handle
191+
.download_video(
192+
&uid,
193+
file_name,
194+
"",
195+
empty_option.clone(),
196+
node.clone(),
197+
true,
198+
)
199+
.await
200+
{
201+
Ok(url) => Ok(url),
202+
Err(e) => {
203+
tracing::warn!(
204+
"Failed to download group video: {:?}, using download_group_video fallback!",
205+
e
206+
);
207+
handle
208+
.download_group_video(
209+
grp.group_uin,
210+
file_name,
211+
"",
212+
empty_option,
213+
node.clone(),
214+
)
215+
.await
216+
}
217+
}
218+
}
219+
MessageType::Friend(_) | MessageType::Temp => {
220+
let self_uid = chain.uid.clone();
221+
handle
222+
.download_video(
223+
&self_uid,
224+
file_name,
225+
"",
226+
empty_option,
227+
node.clone(),
228+
false,
229+
)
230+
.await
231+
}
232+
_ => continue,
233+
};
234+
match download_result {
235+
Ok(url) => {
236+
video.video_url = url;
237+
}
238+
Err(e) => {
239+
tracing::error!("Failed to download video: {:?}", e);
240+
}
241+
}
242+
}
179243
_ => {}
180244
}
181245
}

mania/src/core/cache.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use crate::entity::bot_friend::BotFriend;
2+
use crate::entity::bot_group_member::BotGroupMember;
3+
use dashmap::DashMap;
4+
use tokio::sync::RwLock;
5+
6+
pub struct Cache {
7+
pub uin2uid: DashMap<u32, String>,
8+
pub cached_friends: RwLock<Vec<BotFriend>>,
9+
pub cached_group_members: DashMap<u32, Vec<BotGroupMember>>,
10+
}
11+
12+
impl Cache {
13+
pub fn new() -> Self {
14+
Self {
15+
uin2uid: DashMap::new(),
16+
cached_friends: RwLock::new(Vec::new()),
17+
cached_group_members: DashMap::new(),
18+
}
19+
}
20+
}

mania/src/core/event/message/file_c2c_download.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ impl ClientEvent for FileC2CDownloadEvent {
3838

3939
fn parse(packet: Bytes, _: &Context) -> Result<Box<dyn ServerEvent>, EventError> {
4040
let packet = OidbPacket::parse_into::<OidbSvcTrpcTcp0xE371200response>(packet)?;
41-
let body = packet.body.ok_or(EventError::OtherError(
42-
"Missing OidbSvcTrpcTcp0xE371200responseBody".to_string(),
43-
))?;
44-
let result = body.result.ok_or(EventError::OtherError(
45-
"Missing OidbSvcTrpcTcp0xE371200result".to_string(),
46-
))?;
41+
let body = packet.body.ok_or_else(|| {
42+
EventError::OtherError("Missing OidbSvcTrpcTcp0xE371200responseBody".to_string())
43+
})?;
44+
let result = body.result.ok_or_else(|| {
45+
EventError::OtherError("Missing OidbSvcTrpcTcp0xE371200result".to_string())
46+
})?;
4747
let file_url = format!(
4848
"https://{}:{}{}&isthumb=0",
4949
result.sso_url, result.sso_port, result.url

mania/src/core/event/message/file_group_download.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ impl ClientEvent for FileGroupDownloadEvent {
2626

2727
fn parse(packet: Bytes, _: &Context) -> Result<Box<dyn ServerEvent>, EventError> {
2828
let packet = OidbPacket::parse_into::<OidbSvcTrpcTcp0x6D6Response>(packet)?;
29-
let download = packet.download.ok_or(EventError::OtherError(
30-
"Missing OidbSvcTrpcTcp0x6D62response".to_string(),
31-
))?;
29+
let download = packet.download.ok_or_else(|| {
30+
EventError::OtherError("Missing OidbSvcTrpcTcp0x6D62response".to_string())
31+
})?;
3232
match download.ret_code {
3333
0 => {
3434
let url = format!(

mania/src/core/event/message/image_c2c_download.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ impl ClientEvent for ImageC2CDownloadEvent {
4949
let packet = OidbPacket::parse_into::<Ntv2RichMediaResp>(packet)?;
5050
let body = packet
5151
.download
52-
.ok_or(EventError::OtherError("Missing DownloadResp".to_string()))?;
52+
.ok_or_else(|| EventError::OtherError("Missing DownloadResp".to_string()))?;
5353
let info = body
5454
.info
55-
.ok_or(EventError::OtherError("Missing DownloadInfo".to_string()))?;
55+
.ok_or_else(|| EventError::OtherError("Missing DownloadInfo".to_string()))?;
5656
let url = format!(
5757
"https://{}{}{}",
5858
info.domain, info.url_path, body.r_key_param

mania/src/core/event/message/image_group_download.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ impl ClientEvent for ImageGroupDownloadEvent {
4949
.expect("Failed to parse OidbPacket");
5050
let body = packet
5151
.download
52-
.ok_or(EventError::OtherError("Missing DownloadResp".to_string()))?;
52+
.ok_or_else(|| EventError::OtherError("Missing DownloadResp".to_string()))?;
5353
let info = body
5454
.info
55-
.ok_or(EventError::OtherError("Missing DownloadInfo".to_string()))?;
55+
.ok_or_else(|| EventError::OtherError("Missing DownloadInfo".to_string()))?;
5656
let url = format!(
5757
"https://{}{}{}",
5858
info.domain, info.url_path, body.r_key_param

0 commit comments

Comments
 (0)