Skip to main content

bpi_rs/fav/
info.rs

1use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
2use serde::{ Deserialize, Serialize };
3
4// --- 获取收藏夹元数据 ---
5
6/// 收藏夹元数据的创建者信息
7#[derive(Debug, Clone, Deserialize, Serialize)]
8pub struct FavFolderUpper {
9    pub mid: u64,
10    pub name: String,
11    pub face: String,
12    pub followed: bool,
13    pub vip_type: u8,
14    /// 阿b拼写错误
15    #[serde(rename = "vip_statue")]
16    pub vip_status: u8,
17}
18
19/// 收藏夹元数据的状态数
20#[derive(Debug, Clone, Deserialize, Serialize)]
21pub struct FavFolderCntInfo {
22    pub collect: u64,
23    pub play: u64,
24    pub thumb_up: u64,
25    pub share: u64,
26}
27
28/// 收藏夹元数据
29#[derive(Debug, Clone, Deserialize, Serialize)]
30pub struct FavFolderInfo {
31    pub id: u64,
32    pub fid: u64,
33    pub mid: u64,
34    pub attr: u32,
35    pub title: String,
36    pub cover: String,
37    pub upper: FavFolderUpper,
38    pub cover_type: u8,
39    pub cnt_info: FavFolderCntInfo,
40    #[serde(rename = "type")]
41    pub type_name: u32,
42    pub intro: String,
43    pub ctime: u64,
44    pub mtime: u64,
45    pub state: u8,
46    pub fav_state: u8,
47    pub like_state: u8,
48    pub media_count: u32,
49}
50
51// --- 获取指定用户创建的所有收藏夹信息 ---
52
53/// 用户创建的收藏夹列表项
54#[derive(Debug, Clone, Deserialize, Serialize)]
55pub struct CreatedFolderItem {
56    pub id: u64,
57    pub fid: u64,
58    pub mid: u64,
59    pub attr: u32,
60    pub title: String,
61    pub fav_state: u8,
62    pub media_count: u32,
63}
64
65/// 用户创建的收藏夹信息数据
66#[derive(Debug, Clone, Deserialize, Serialize)]
67pub struct CreatedFolderListData {
68    pub count: u32,
69    pub list: Vec<CreatedFolderItem>,
70}
71
72// --- 查询用户收藏的视频收藏夹 ---
73
74/// 用户收藏的视频收藏夹列表项的创建人信息
75#[derive(Debug, Clone, Deserialize, Serialize)]
76pub struct CollectedFolderUpper {
77    pub mid: u64,
78    pub name: String,
79    pub face: String,
80}
81
82/// 用户收藏的视频收藏夹列表项
83#[derive(Debug, Clone, Deserialize, Serialize)]
84pub struct CollectedFolderItem {
85    pub id: u64,
86    pub fid: u64,
87    pub mid: u64,
88    pub attr: u32,
89    pub title: String,
90    pub cover: String,
91    pub upper: CollectedFolderUpper,
92    pub cover_type: u8,
93    pub intro: String,
94    pub ctime: u64,
95    pub mtime: u64,
96    pub state: u8,
97    pub fav_state: u8,
98    pub media_count: u32,
99}
100
101/// 用户收藏的视频收藏夹列表数据
102#[derive(Debug, Clone, Deserialize, Serialize)]
103pub struct CollectedFolderListData {
104    pub count: u32,
105    pub list: Vec<CollectedFolderItem>,
106}
107
108// --- 批量获取指定收藏id的内容 ---
109
110/// 内容信息列表中的UP主信息
111#[derive(Debug, Clone, Deserialize, Serialize)]
112pub struct ResourceInfoUpper {
113    pub mid: u64,
114    pub name: String,
115    pub face: String,
116}
117
118/// 内容信息列表中的状态数
119#[derive(Debug, Clone, Deserialize, Serialize)]
120pub struct ResourceInfoCntInfo {
121    pub collect: u64,
122    pub play: u64,
123    pub danmaku: u64,
124}
125
126/// 批量获取的内容信息列表项
127#[derive(Debug, Clone, Deserialize, Serialize)]
128pub struct ResourceInfoItem {
129    pub id: u64,
130    #[serde(rename = "type")]
131    pub type_name: u8,
132    pub title: String,
133    pub cover: String,
134    pub intro: String,
135    pub page: Option<u32>,
136    pub duration: u32,
137    pub upper: ResourceInfoUpper,
138    pub attr: u8,
139    pub cnt_info: ResourceInfoCntInfo,
140    pub link: String,
141    pub ctime: u64,
142    pub pubtime: u64,
143    pub fav_time: u64,
144    pub bv_id: Option<String>,
145    pub bvid: Option<String>,
146    pub season: Option<serde_json::Value>,
147}
148
149impl BpiClient {
150    /// 获取收藏夹元数据
151    ///
152    /// # 文档
153    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/fav)
154    ///
155    /// # 参数
156    ///
157    /// | 名称 | 类型 | 说明 |
158    /// | ---- | ---- | ---- |
159    /// | `media_id` | u64 | 收藏夹 media_id |
160    pub async fn fav_folder_info(
161        &self,
162        media_id: u64
163    ) -> Result<BpiResponse<FavFolderInfo>, BpiError> {
164        self
165            .get("https://api.bilibili.com/x/v3/fav/folder/info")
166            .query(&[("media_id", media_id)])
167            .send_bpi("获取收藏夹元数据").await
168    }
169
170    /// 获取指定用户创建的所有收藏夹信息
171    ///
172    /// # 文档
173    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/fav)
174    ///
175    /// # 参数
176    ///
177    /// | 名称 | 类型 | 说明 |
178    /// | ---- | ---- | ---- |
179    /// | `up_mid` | u64 | 用户 mid |
180    /// | `typ` | `Option<u8>` | 类型过滤 |
181    /// | `rid` | `Option<u64>` | 关联资源 id |
182    pub async fn fav_created_list(
183        &self,
184        up_mid: u64,
185        typ: Option<u8>,
186        rid: Option<u64>
187    ) -> Result<BpiResponse<CreatedFolderListData>, BpiError> {
188        let mut request = self
189            .get("https://api.bilibili.com/x/v3/fav/folder/created/list-all")
190            .query(&[("up_mid", up_mid.to_string())]);
191
192        if let Some(t) = typ {
193            request = request.query(&[("type", t)]);
194        }
195        if let Some(r) = rid {
196            request = request.query(&[("rid", r)]);
197        }
198
199        request
200            .query(&[("web_location", "333.1387")])
201            .send_bpi("获取指定用户创建的所有收藏夹信息").await
202    }
203
204    /// 查询用户收藏的视频收藏夹
205    ///
206    /// # 文档
207    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/fav)
208    ///
209    /// # 参数
210    ///
211    /// | 名称 | 类型 | 说明 |
212    /// | ---- | ---- | ---- |
213    /// | `up_mid` | u64 | 用户 mid |
214    /// | `pn` | u32 | 页码 |
215    /// | `ps` | u32 | 页大小 |
216    pub async fn fav_collected_list(
217        &self,
218        up_mid: u64,
219        pn: u32,
220        ps: u32
221    ) -> Result<BpiResponse<CollectedFolderListData>, BpiError> {
222        self
223            .get("https://api.bilibili.com/x/v3/fav/folder/collected/list")
224            .query(
225                &[
226                    ("up_mid", up_mid.to_string()),
227                    ("pn", pn.to_string()),
228                    ("ps", ps.to_string()),
229                    ("platform", "web".to_string()),
230                ]
231            )
232            .send_bpi("查询用户收藏的视频收藏夹").await
233    }
234
235    /// 批量获取指定收藏id的内容
236    /// `resources`: "{内容id}:{内容类型},..."
237    ///
238    /// # 文档
239    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/fav)
240    ///
241    /// # 参数
242    ///
243    /// | 名称 | 类型 | 说明 |
244    /// | ---- | ---- | ---- |
245    /// | `resources` | &str | 形如 "{内容id}:{内容类型},..." |
246    pub async fn fav_resource_infos(
247        &self,
248        resources: &str
249    ) -> Result<BpiResponse<Vec<ResourceInfoItem>>, BpiError> {
250        self
251            .get("https://api.bilibili.com/x/v3/fav/resource/infos")
252            .query(
253                &[
254                    ("resources", resources),
255                    ("platform", "web"),
256                ]
257            )
258            .send_bpi("批量获取指定收藏id的内容").await
259    }
260}
261
262#[cfg(test)]
263mod tests {
264    use super::*;
265    use tracing::info;
266
267    #[tokio::test]
268    async fn test_get_fav_folder_info() {
269        let bpi = BpiClient::new();
270        // 替换为一个公开收藏夹的media_id
271        let media_id = 3717139570;
272        let resp = bpi.fav_folder_info(media_id).await;
273
274        info!("{:?}", resp);
275        assert!(resp.is_ok());
276
277        let resp_data = resp.unwrap();
278        info!("code: {}", resp_data.code);
279        if let Some(data) = resp_data.data {
280            info!("folder title: {}", data.title);
281            info!("folder media_count: {}", data.media_count);
282            info!("upper info: {:?}", data.upper);
283        }
284    }
285
286    #[tokio::test]
287    async fn test_get_fav_created_list() {
288        let bpi = BpiClient::new();
289
290        let up_mid = 4279370;
291        let resp = bpi.fav_created_list(up_mid, None, None).await;
292
293        info!("{:?}", resp);
294        assert!(resp.is_ok());
295
296        let resp_data = resp.unwrap();
297        info!("code: {}", resp_data.code);
298        if let Some(data) = resp_data.data {
299            info!("created folders count: {}", data.count);
300            info!("first folder info: {:?}", data.list.first());
301        }
302    }
303
304    #[tokio::test]
305    async fn test_get_fav_collected_list() {
306        let bpi = BpiClient::new();
307
308        let up_mid = 4279370;
309        let resp = bpi.fav_collected_list(up_mid, 1, 20).await;
310
311        info!("{:?}", resp);
312        assert!(resp.is_ok());
313
314        let resp_data = resp.unwrap();
315        info!("code: {}", resp_data.code);
316        if let Some(data) = resp_data.data {
317            info!("collected folders count: {}", data.count);
318            info!("first collected folder info: {:?}", data.list.first());
319        }
320    }
321
322    #[tokio::test]
323    async fn test_get_fav_resource_infos() {
324        let bpi = BpiClient::new();
325        let resources = "115087859779103:2";
326        let resp = bpi.fav_resource_infos(resources).await;
327
328        info!("{:?}", resp);
329        assert!(resp.is_ok());
330
331        let resp_data = resp.unwrap();
332        info!("code: {}", resp_data.code);
333        if let Some(data) = resp_data.data {
334            info!("retrieved {} resources", data.len());
335            info!("first resource info: {:?}", data.first());
336        }
337    }
338}