Skip to main content

bpi_rs/user/
status_number.rs

1//! B站用户关系、UP主状态、导航栏等相关接口
2//!
3//! [查看 API 文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/user)
4use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
5use serde::{ Deserialize, Serialize };
6
7// --- 响应数据结构体 ---
8
9/// 用户关系状态数响应数据
10#[derive(Debug, Clone, Deserialize, Serialize)]
11pub struct RelationStatResponseData {
12    /// 目标用户 mid
13    pub mid: u64,
14    /// 关注数
15    pub following: u64,
16    /// 悄悄关注数
17    pub whisper: u64,
18    /// 黑名单数
19    pub black: u64,
20    /// 粉丝数
21    pub follower: u64,
22}
23
24/// UP主状态数中的视频播放量
25#[derive(Debug, Clone, Deserialize, Serialize)]
26pub struct UpstatArchive {
27    /// 视频播放量
28    pub view: u64,
29}
30
31/// UP主状态数中的专栏阅读量
32#[derive(Debug, Clone, Deserialize, Serialize)]
33pub struct UpstatArticle {
34    /// 专栏阅读量
35    pub view: u64,
36}
37
38/// UP主状态数响应数据
39#[derive(Debug, Clone, Deserialize, Serialize)]
40pub struct UpstatResponseData {
41    /// 视频播放量
42    pub archive: UpstatArchive,
43    /// 专栏阅读量
44    pub article: UpstatArticle,
45    /// 获赞次数
46    pub likes: u64,
47}
48
49/// 用户导航栏状态数中的视频列表数
50#[derive(Debug, Clone, Deserialize, Serialize)]
51pub struct NavnumChannel {
52    /// 视频列表数
53    pub master: u64,
54    /// 视频列表数
55    pub guest: u64,
56}
57
58/// 用户导航栏状态数中的收藏夹数
59#[derive(Debug, Clone, Deserialize, Serialize)]
60pub struct NavnumFavourite {
61    /// 全部收藏夹数
62    pub master: u64,
63    /// 公开收藏夹数
64    pub guest: u64,
65}
66
67/// 用户导航栏状态数响应数据
68#[derive(Debug, Clone, Deserialize, Serialize)]
69pub struct NavnumResponseData {
70    /// 投稿视频数
71    pub video: u64,
72    /// 追番数
73    pub bangumi: u64,
74    /// 追剧数
75    pub cinema: u64,
76    /// 视频列表数
77    pub channel: NavnumChannel,
78    /// 收藏夹数
79    pub favourite: NavnumFavourite,
80    /// 关注 TAG 数
81    pub tag: u64,
82    /// 投稿专栏数
83    pub article: u64,
84    pub playlist: u64,
85    /// 投稿图文数
86    pub album: u64,
87    /// 投稿音频数
88    pub audio: u64,
89    /// 投稿课程数
90    pub pugv: u64,
91    /// 动态数
92    pub opus: u64,
93    /// 视频合集数
94    #[serde(rename = "season_num")]
95    pub season_num: u64,
96}
97
98/// 相簿投稿数响应数据
99#[derive(Debug, Clone, Deserialize, Serialize)]
100pub struct AlbumCountResponseData {
101    /// 相簿总数
102    pub all_count: u64,
103    /// 发布绘画数
104    pub draw_count: u64,
105    /// 发布摄影数
106    pub photo_count: u64,
107    /// 发布日常(图片动态)数
108    pub daily_count: u64,
109}
110
111// --- API 实现 ---
112
113impl BpiClient {
114    /// 获取用户关系状态数
115    ///
116    /// # 文档
117    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/user)
118    ///
119    /// # 参数
120    /// | 名称   | 类型   | 说明           |
121    /// | ------ | ------ | -------------- |
122    /// | `vmid` | u64    | 目标用户 mid   |
123    pub async fn user_relation_stat(
124        &self,
125        vmid: u64
126    ) -> Result<BpiResponse<RelationStatResponseData>, BpiError> {
127        self
128            .get("https://api.bilibili.com/x/relation/stat")
129            .query(&[("vmid", &vmid.to_string())])
130            .send_bpi("获取用户关系状态数").await
131    }
132
133    /// 获取UP主状态数
134    ///
135    /// # 文档
136    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/user)
137    ///
138    /// # 参数
139    /// | 名称   | 类型   | 说明           |
140    /// | ------ | ------ | -------------- |
141    /// | `mid`  | u64    | 目标用户 mid   |
142    pub async fn user_up_stat(
143        &self,
144        mid: u64
145    ) -> Result<BpiResponse<UpstatResponseData>, BpiError> {
146        self
147            .get("https://api.bilibili.com/x/space/upstat")
148            .query(&[("mid", &mid.to_string())])
149            .send_bpi("获取 UP 主状态数").await
150    }
151
152    /// 获取用户导航栏状态数
153    ///
154    /// # 文档
155    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/user)
156    ///
157    /// # 参数
158    /// | 名称   | 类型   | 说明           |
159    /// | ------ | ------ | -------------- |
160    /// | `mid`  | u64    | 目标用户 mid   |
161    pub async fn user_navnum(&self, mid: u64) -> Result<BpiResponse<NavnumResponseData>, BpiError> {
162        self
163            .get("https://api.bilibili.com/x/space/navnum")
164            .query(&[("mid", &mid.to_string())])
165            .send_bpi("获取用户导航栏状态数").await
166    }
167
168    /// 获取相簿投稿数
169    ///
170    /// # 文档
171    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/user)
172    ///
173    /// # 参数
174    /// | 名称   | 类型   | 说明           |
175    /// | ------ | ------ | -------------- |
176    /// | `uid`  | u64    | 目标用户 mid   |
177    pub async fn user_album_count(
178        &self,
179        uid: u64
180    ) -> Result<BpiResponse<AlbumCountResponseData>, BpiError> {
181        self
182            .get("https://api.vc.bilibili.com/link_draw/v1/doc/upload_count")
183            .query(&[("uid", &uid.to_string())])
184            .send_bpi("获取相簿投稿数").await
185    }
186}
187
188// --- 测试模块 ---
189
190#[cfg(test)]
191mod tests {
192    use super::*;
193    use tracing::info;
194
195    // 请在运行测试前设置环境变量 `BPI_COOKIE`,以包含 SESSDATA 等登录信息
196    // mid 根据实际情况修改
197    const TEST_MID: u64 = 332704117;
198    const TEST_UP_MID: u64 = 456664753;
199    const TEST_NAV_MID: u64 = 645769214;
200
201    #[tokio::test]
202    async fn test_get_relation_stat() -> Result<(), BpiError> {
203        let bpi = BpiClient::new();
204        let resp = bpi.user_relation_stat(TEST_MID).await?;
205        let data = resp.into_data()?;
206
207        info!("关系状态数: {:?}", data);
208        assert_eq!(data.mid, TEST_MID);
209
210        Ok(())
211    }
212
213    #[tokio::test]
214    async fn test_get_up_stat() -> Result<(), BpiError> {
215        let bpi = BpiClient::new();
216        let resp = bpi.user_up_stat(TEST_UP_MID).await?;
217        let data = resp.into_data()?;
218
219        info!("UP主状态数: {:?}", data);
220        assert!(data.likes > 0);
221
222        Ok(())
223    }
224
225    #[tokio::test]
226    async fn test_get_nav_num() -> Result<(), BpiError> {
227        let bpi = BpiClient::new();
228        let resp = bpi.user_navnum(TEST_NAV_MID).await?;
229        let data = resp.into_data()?;
230
231        info!("用户导航栏状态数: {:?}", data);
232        assert!(data.video > 0);
233
234        Ok(())
235    }
236
237    #[tokio::test]
238    async fn test_get_album_count() -> Result<(), BpiError> {
239        let bpi = BpiClient::new();
240        let resp = bpi.user_album_count(TEST_NAV_MID).await?;
241        let data = resp.into_data()?;
242
243        info!("相簿投稿数: {:?}", data);
244        assert!(data.all_count > 0);
245
246        Ok(())
247    }
248}