bpi_rs/dynamic/
all.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{BilibiliRequest, BpiClient, BpiError, BpiResponse};
4
5#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6pub struct DynamicAllData {
7    pub has_more: bool,
8    pub items: Vec<DynamicItem>,
9    pub offset: String,
10    pub update_baseline: String,
11    pub update_num: i64,
12}
13
14#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
15pub struct DynamicItem {
16    pub basic: Basic,
17    pub id_str: String,
18    pub modules: serde_json::Value,
19    #[serde(rename = "type")]
20    pub type_field: String,
21    pub visible: bool,
22}
23
24#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
25pub struct Basic {
26    pub comment_id_str: String,
27    pub comment_type: i64,
28    pub like_icon: serde_json::Value,
29    pub rid_str: String,
30    pub is_only_fans: Option<bool>,
31    pub jump_url: Option<String>,
32}
33
34/// 检测新动态响应数据
35#[derive(Debug, Clone, Deserialize)]
36pub struct DynamicUpdateData {
37    /// 新动态的数量
38    pub update_num: u64,
39}
40
41impl BpiClient {
42    /// 获取全部动态列表
43    /// GET https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all
44    ///
45    /// 文档: https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/dynamic
46    ///
47    /// 参数
48    ///
49    /// | 名称 | 类型 | 说明 |
50    /// | ---- | ---- | ---- |
51    /// | `host_mid` | Option<&str> | UP 主 UID |
52    /// | `offset` | Option<&str> | 分页偏移量 |
53    /// | `update_baseline` | Option<&str> | 更新基线,用于获取新动态 |
54    pub async fn dynamic_all(
55        &self,
56        host_mid: Option<&str>,
57        offset: Option<&str>,
58        update_baseline: Option<&str>,
59    ) -> Result<BpiResponse<DynamicAllData>, BpiError> {
60        let mut req = self
61          .get("https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all")
62          .query(&[("features", "itemOpusStyle,listOnlyfans,opusBigCover,onlyfansVote,decorationCard,onlyfansAssetsV2,forwardListHidden,ugcDelete"), ("web_location", "333.1365")]);
63
64        if let Some(mid) = host_mid {
65            req = req.query(&[("host_mid", mid)]);
66        }
67        if let Some(off) = offset {
68            req = req.query(&[("offset", off)]);
69        }
70        if let Some(baseline) = update_baseline {
71            req = req.query(&[("update_baseline", baseline)]);
72        }
73
74        req.send_bpi("获取全部动态列表").await
75    }
76
77    /// 检测是否有新动态
78    /// GET https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all/update
79    ///
80    /// 文档: https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/dynamic
81    ///
82    /// 参数
83    ///
84    /// | 名称 | 类型 | 说明 |
85    /// | ---- | ---- | ---- |
86    /// | `update_baseline` | &str | 上次列表返回的 update_baseline |
87    /// | `type_str` | Option<&str> | 动态类型 |
88    pub async fn dynamic_check_new(
89        &self,
90        update_baseline: &str,
91        type_str: Option<&str>,
92    ) -> Result<BpiResponse<DynamicUpdateData>, BpiError> {
93        let mut req = self
94            .get("https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all/update")
95            .query(&[("update_baseline", update_baseline)]);
96
97        if let Some(typ) = type_str {
98            req = req.query(&[("type", typ)]);
99        }
100
101        req.send_bpi("检测新动态").await
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108    use tracing::info;
109
110    #[tokio::test]
111
112    async fn test_dynamic_get_all() -> Result<(), BpiError> {
113        let bpi = BpiClient::new();
114        let resp = bpi.dynamic_all(None, None, None).await?;
115        assert_eq!(resp.code, 0);
116
117        let data = resp.into_data()?;
118
119        info!("成功获取 {} 条动态", data.items.len());
120
121        Ok(())
122    }
123
124    #[tokio::test]
125
126    async fn test_dynamic_check_new() -> Result<(), BpiError> {
127        let bpi = BpiClient::new();
128        let update_baseline = "0";
129        let resp = bpi.dynamic_check_new(update_baseline, None).await?;
130        let data = resp.into_data().unwrap();
131
132        info!("成功检测到 {} 条新动态", data.update_num);
133
134        Ok(())
135    }
136}