bpi_rs/dynamic/
nav.rs

1use crate::{BilibiliRequest, BpiClient, BpiError, BpiResponse};
2use serde::{Deserialize, Serialize};
3
4// --- 导航栏动态 API 结构体 ---
5
6/// 导航栏动态列表项的 UP 主信息
7#[derive(Debug, Clone, Deserialize, Serialize)]
8pub struct DynamicNavAuthor {
9    /// UP 主头像 URL
10    pub face: String,
11    /// UP 主 mid (UID)
12    pub mid: u64,
13    /// UP 主昵称
14    pub name: String,
15}
16
17/// 导航栏动态列表项
18#[derive(Debug, Clone, Deserialize, Serialize)]
19pub struct DynamicNavItem {
20    /// UP 主信息
21    pub author: DynamicNavAuthor,
22    /// 封面 URL
23    pub cover: String,
24    /// 动态 ID 字符串
25    pub id_str: String,
26    /// 发布时间(文字表述的相对时间)
27    pub pub_time: String,
28    /// 关联 ID,视频即 aid
29    pub rid: u64,
30    /// 标题
31    pub title: String,
32    /// 动态类型,8 表示视频
33    #[serde(rename = "type")]
34    pub type_num: u8,
35    /// 是否可见
36    pub visible: bool,
37}
38
39/// 导航栏动态列表响应数据
40#[derive(Debug, Clone, Deserialize, Serialize)]
41pub struct DynamicNavData {
42    /// 是否有更多数据
43    pub has_more: bool,
44    /// 动态数据数组
45    pub items: Vec<DynamicNavItem>,
46    /// 偏移量,用于翻页
47    pub offset: String,
48    /// 更新基线,用于获取新动态
49    pub update_baseline: String,
50    /// 本次获取到的新动态条数
51    pub update_num: u64,
52}
53
54impl BpiClient {
55    /// 获取导航栏动态列表
56    ///
57    /// 文档: https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/dynamic
58    ///
59    /// 参数
60    ///
61    /// | 名称 | 类型 | 说明 |
62    /// | ---- | ---- | ---- |
63    /// | `update_baseline` | Option<&str> | 更新基线,获取新动态时使用 |
64    /// | `offset` | Option<&str> | 分页偏移量,翻页时使用 |
65    pub async fn dynamic_nav_feed(
66        &self,
67        update_baseline: Option<&str>,
68        offset: Option<&str>,
69    ) -> Result<BpiResponse<DynamicNavData>, BpiError> {
70        let mut req = self.get("https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/nav");
71
72        if let Some(baseline) = update_baseline {
73            req = req.query(&[("update_baseline", baseline)]);
74        }
75
76        if let Some(off) = offset {
77            req = req.query(&[("offset", off)]);
78        }
79
80        req.send_bpi("获取导航栏动态列表").await
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87    use tracing::info;
88
89    #[tokio::test]
90
91    async fn test_get_dynamic_nav_feed() -> Result<(), BpiError> {
92        let bpi = BpiClient::new();
93        let resp = bpi.dynamic_nav_feed(None, None).await?;
94        let data = resp.into_data()?;
95
96        info!("获取到 {} 条动态", data.items.len());
97        info!("第一条动态ID: {}", data.items[0].id_str);
98
99        assert!(!data.items.is_empty());
100
101        Ok(())
102    }
103}