Skip to content

Commit a83f4b5

Browse files
committed
[bilibili.space][Telegram][QQ] Handle live reservations
1 parent ac07665 commit a83f4b5

File tree

7 files changed

+103
-1
lines changed

7 files changed

+103
-1
lines changed

src/platform/bilibili/source/space.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ mod data {
162162
pub struct ModuleDynamic {
163163
pub desc: Option<RichText>,
164164
pub major: Option<ModuleDynamicMajor>,
165+
pub additional: Option<ModuleDynamicAdditional>,
165166
}
166167

167168
//
@@ -590,6 +591,54 @@ mod data {
590591
// pub width: u64
591592
// pub size: u64
592593
}
594+
595+
//
596+
597+
#[derive(Debug, Deserialize)]
598+
#[serde(tag = "type")]
599+
pub enum ModuleDynamicAdditional {
600+
#[serde(rename = "ADDITIONAL_TYPE_RESERVE")]
601+
Reserve { reserve: ModuleDynamicReserve },
602+
#[serde(untagged)]
603+
Unknown(json::Value),
604+
}
605+
606+
impl ModuleDynamicAdditional {
607+
pub fn to_content(&self) -> Option<PostContent> {
608+
match self {
609+
Self::Reserve { reserve } => {
610+
let mut content = PostContent::plain(&reserve.title);
611+
if let Some(desc1) = &reserve.desc1 {
612+
content = content.with_plain("\n").with_plain(&desc1.text);
613+
}
614+
// Ignore `desc2``
615+
if let Some(desc3) = &reserve.desc3 {
616+
warn!("bilibili reservation desc3 is not null", kv: { desc3:? });
617+
}
618+
Some(content)
619+
}
620+
Self::Unknown(data) => {
621+
warn!("unknown bilibili additional variant", kv: { data: });
622+
None
623+
}
624+
}
625+
}
626+
}
627+
628+
#[rustfmt::skip] // TODO: https://github.com/rust-lang/rustfmt/issues/6755
629+
#[derive(Debug, Deserialize)]
630+
pub struct ModuleDynamicReserve {
631+
pub title: String,
632+
pub desc1: Option<ReserveDescription>, // "YY-DD HH:MM 直播" (UTC+8?)
633+
pub desc2: Option<ReserveDescription>, // "XX人预约"
634+
pub desc3: Option<ReserveDescription>, // null
635+
// pub reserve_total: u64,
636+
}
637+
638+
#[derive(Debug, Deserialize)]
639+
pub struct ReserveDescription {
640+
pub text: String,
641+
}
593642
}
594643

595644
pub struct Fetcher {
@@ -725,6 +774,13 @@ fn parse_response(resp: data::SpaceHistory, blocked: &mut BlockedPostIds) -> any
725774
(None, None) => bail!("item no content. item: {item:?}"),
726775
};
727776

777+
let event = item
778+
.modules
779+
.dynamic
780+
.additional
781+
.as_ref()
782+
.and_then(|additional| additional.to_content());
783+
728784
let original = item
729785
.orig
730786
.as_ref()
@@ -773,6 +829,7 @@ fn parse_response(resp: data::SpaceHistory, blocked: &mut BlockedPostIds) -> any
773829
Ok(Post {
774830
user: item.modules.author.clone().into(),
775831
content,
832+
event,
776833
urls: PostUrls::new(url),
777834
time,
778835
is_pinned,

src/platform/bilibili/source/video.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ fn parse_response(mid: u64, resp: data::SeriesArchives) -> anyhow::Result<Posts>
142142
avatar_url: None,
143143
},
144144
content: PostContent::plain(archive.title),
145+
event: None,
145146
urls: PostUrl::new_clickable(
146147
format!("https://www.bilibili.com/video/{}", archive.bvid),
147148
"查看视频",

src/platform/qq/notify/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@ impl Notifier {
306306
builder.ref_text(post.content.fallback());
307307
builder.ref_text("\n\n");
308308
}
309+
if let Some(event) = &post.event {
310+
builder.ref_text(event.fallback());
311+
builder.ref_text("\n\n");
312+
}
309313

310314
fn append_reposts_rec(
311315
builder: &mut onebot11::MessageBuilder,
@@ -315,6 +319,10 @@ impl Notifier {
315319
builder.ref_text(format!("{}: ", repost_from.post.user.nickname));
316320
append_media(builder, repost_from.post.attachments(false));
317321
builder.ref_text(repost_from.post.content.fallback());
322+
if let Some(event) = &repost_from.post.event {
323+
builder.ref_text("\n\n");
324+
builder.ref_text(event.fallback());
325+
}
318326
if let Some(repost_from) = &repost_from.post.repost_from {
319327
builder.ref_text("\n\n");
320328
append_reposts_rec(builder, repost_from);
@@ -330,6 +338,10 @@ impl Notifier {
330338
));
331339
append_media(&mut builder, post.attachments(false));
332340
builder.ref_text(post.content.fallback());
341+
if let Some(event) = &post.event {
342+
builder.ref_text("\n\n");
343+
builder.ref_text(event.fallback());
344+
}
333345
}
334346
}
335347
if self.params.base.option.ext.__post_text.is_none() {

src/platform/telegram/notify/mod.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,13 @@ impl Notifier {
499499
text.push_content(&post.content);
500500
text.push_plain("\n");
501501
}
502+
if let Some(event) = &post.event {
503+
text.push_quote(|text| {
504+
text.push_content(event);
505+
false
506+
});
507+
text.push_plain("\n");
508+
}
502509

503510
fn push_reposts_rec<'a>(text: &mut Text<'a>, repost_from: &'a RepostFrom) {
504511
text.push_quote(|text| {
@@ -517,6 +524,12 @@ impl Notifier {
517524
text.push_plain(": ");
518525
text.push_content(&repost_from.post.content);
519526

527+
if let Some(event) = &repost_from.post.event {
528+
text.push_plain("\n\n---\n");
529+
text.push_content(event);
530+
text.push_plain("\n---");
531+
}
532+
520533
false // TODO: Collapse if too long
521534
});
522535
if let Some(repost_from) = &repost_from.post.repost_from {
@@ -531,7 +544,14 @@ impl Notifier {
531544
text.push_link(&post.user.nickname, &post.user.profile_url);
532545
text.push_plain(": ");
533546
}
534-
text.push_content(&post.content)
547+
text.push_content(&post.content);
548+
if let Some(event) = &post.event {
549+
text.push_plain("\n");
550+
text.push_quote(|text| {
551+
text.push_content(event);
552+
false
553+
});
554+
}
535555
}
536556
}
537557

src/platform/twitter/source/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,7 @@ impl FetcherInner {
686686
content
687687
.unwrap_or_else(|| if repost_from.is_some() { "Retweet" } else { "" }.into()),
688688
),
689+
event: None,
689690
urls,
690691
time,
691692
is_pinned,

src/source/abstruct/post.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub struct PostPlatformUniqueId(String);
1212
pub struct Post {
1313
pub user: User,
1414
pub content: PostContent,
15+
pub event: Option<PostContent>, // e.g. live reservation
1516
pub(crate) urls: PostUrls,
1617
pub time: DateTime<Local>,
1718
pub is_pinned: bool,

src/source/abstruct/status.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ mod tests {
261261
StatusKind::Posts(Posts(vec![Post {
262262
user: mock_user(),
263263
content: PostContent::plain("content1"),
264+
event: None,
264265
urls: PostUrls::new(PostUrl::Identity("id1".into())),
265266
time: DateTime::UNIX_EPOCH.into(),
266267
is_pinned: false,
@@ -286,6 +287,7 @@ mod tests {
286287
Post {
287288
user: mock_user(),
288289
content: PostContent::plain("content1"),
290+
event: None,
289291
urls: PostUrls::new(PostUrl::Identity("id1".into())),
290292
time: DateTime::UNIX_EPOCH.into(),
291293
is_pinned: false,
@@ -296,6 +298,7 @@ mod tests {
296298
Post {
297299
user: mock_user(),
298300
content: PostContent::plain("content2"),
301+
event: None,
299302
urls: PostUrls::new(PostUrl::Identity("id2".into())),
300303
time: DateTime::UNIX_EPOCH.into(),
301304
is_pinned: false,
@@ -316,6 +319,7 @@ mod tests {
316319
Post {
317320
user: mock_user(),
318321
content: PostContent::plain("content1"),
322+
event: None,
319323
urls: PostUrls::new(PostUrl::Identity("id1".into())),
320324
time: DateTime::UNIX_EPOCH.into(),
321325
is_pinned: false,
@@ -326,6 +330,7 @@ mod tests {
326330
Post {
327331
user: mock_user(),
328332
content: PostContent::plain("content2"),
333+
event: None,
329334
urls: PostUrls::new(PostUrl::Identity("id2".into())),
330335
time: DateTime::UNIX_EPOCH.into(),
331336
is_pinned: false,
@@ -361,6 +366,7 @@ mod tests {
361366
StatusKind::Posts(Posts(vec![Post {
362367
user: mock_user(),
363368
content: PostContent::plain("content3"),
369+
event: None,
364370
urls: PostUrls::new(PostUrl::Identity("id3".into())),
365371
time: DateTime::UNIX_EPOCH.into(),
366372
is_pinned: false,
@@ -383,6 +389,7 @@ mod tests {
383389
Post {
384390
user: mock_user(),
385391
content: PostContent::plain("content1"),
392+
event: None,
386393
urls: PostUrls::new(PostUrl::Identity("id1".into())),
387394
time: DateTime::UNIX_EPOCH.into(),
388395
is_pinned: false,
@@ -393,6 +400,7 @@ mod tests {
393400
Post {
394401
user: mock_user(),
395402
content: PostContent::plain("content2"),
403+
event: None,
396404
urls: PostUrls::new(PostUrl::Identity("id2".into())),
397405
time: DateTime::UNIX_EPOCH.into(),
398406
is_pinned: false,
@@ -403,6 +411,7 @@ mod tests {
403411
Post {
404412
user: mock_user(),
405413
content: PostContent::plain("content3"),
414+
event: None,
406415
urls: PostUrls::new(PostUrl::Identity("id3".into())),
407416
time: DateTime::UNIX_EPOCH.into(),
408417
is_pinned: false,
@@ -458,6 +467,7 @@ mod tests {
458467
StatusKind::Posts(Posts(vec![Post {
459468
user: mock_user(),
460469
content: PostContent::plain("content1"),
470+
event: None,
461471
urls: PostUrls::new(PostUrl::Identity("id1".into())),
462472
time: DateTime::UNIX_EPOCH.into(),
463473
is_pinned: false,

0 commit comments

Comments
 (0)