Skip to main content

bpi_rs/creativecenter/season/
list.rs

1//! 获取合集列表 API
2//!
3//! [参考文档](https://github.com/Yuelioi/bilibili-API-collect/tree/cfc5fddcc8a94b74d91970bb5b4eaeb349addc47/docs/creativecenter/season/list.md)
4
5use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
6use serde::{ Deserialize, Serialize };
7
8use super::models::{ Season, Section };
9
10/// 合集列表返回结构
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct SeasonListData {
13    pub seasons: Vec<SeasonItem>,
14    pub tip: serde_json::Value,
15    pub total: u32,
16    pub play_type: u32,
17}
18
19/// 单个合集条目
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct SeasonItem {
22    pub season: Season,
23    pub course: Option<serde_json::Value>,
24    pub checkin: Option<CheckInInfo>,
25    #[serde(rename = "seasonStat")]
26    pub season_stat: Option<SeasonStat>,
27    pub sections: Option<SectionsWrapper>,
28    pub part_episodes: Vec<PartEpisode>,
29}
30
31/// 合集审核信息
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct CheckInInfo {
34    pub status: i32,
35    pub status_reason: Option<String>,
36    pub season_status: i32,
37}
38
39/// 合集统计信息
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct SeasonStat {
42    pub view: u64,
43    pub danmaku: u64,
44    pub reply: u64,
45    pub fav: u64,
46    pub coin: u64,
47    pub share: u64,
48    #[serde(rename = "nowRank")]
49    pub now_rank: u32,
50    #[serde(rename = "hisRank")]
51    pub his_rank: u32,
52    pub like: u64,
53    pub subscription: u64,
54    pub vt: u32,
55}
56
57/// 小节包装器
58#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct SectionsWrapper {
60    pub sections: Vec<Section>,
61}
62
63/// 合集内视频条目
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct PartEpisode {
66    pub id: u64,
67    pub title: String,
68    pub aid: u64,
69    pub bvid: String,
70    pub cid: u64,
71    #[serde(rename = "seasonId")]
72    pub season_id: u64,
73    #[serde(rename = "sectionId")]
74    pub section_id: u64,
75    pub order: u32,
76    #[serde(rename = "videoTitle")]
77    pub video_title: Option<String>,
78    #[serde(rename = "archiveTitle")]
79    pub archive_title: Option<String>,
80    #[serde(rename = "archiveState")]
81    pub archive_state: i32,
82    #[serde(rename = "rejectReason")]
83    pub reject_reason: Option<String>,
84    pub state: i32,
85    pub cover: String,
86    pub is_free: i32,
87    pub aid_owner: bool,
88    #[serde(rename = "charging_pay")]
89    pub charging_pay: u32,
90}
91
92impl BpiClient {
93    /// 获取合集列表
94    ///
95    /// 获取当前用户创建的合集列表,支持分页和排序。
96    ///
97    /// # 参数
98    /// | 名称 | 类型 | 说明 |
99    /// | ---- | ---- | ---- |
100    /// | `pn` | u32 | 页码,默认 1 |
101    /// | `ps` | u32 | 每页数量,默认 30 |
102    /// | `order` | `Option<&str>` | 排序方式:ctime 或 mtime |
103    /// | `sort` | `Option<&str>` | 升降序:asc 或 desc |
104    ///
105    /// # 文档
106    /// [获取合集列表](https://github.com/Yuelioi/bilibili-API-collect/tree/cfc5fddcc8a94b74d91970bb5b4eaeb349addc47/docs/creativecenter/season/list.md#获取合集列表)
107    pub async fn season_list(
108        &self,
109        pn: u32,
110        ps: u32,
111        order: Option<&str>,
112        sort: Option<&str>
113    ) -> Result<BpiResponse<SeasonListData>, BpiError> {
114        let mut query: Vec<(&str, String)> = vec![("pn", pn.to_string()), ("ps", ps.to_string())];
115
116        if let Some(order_val) = order {
117            query.push(("order", order_val.to_string()));
118        }
119        if let Some(sort_val) = sort {
120            query.push(("sort", sort_val.to_string()));
121        }
122
123        self
124            .get("https://member.bilibili.com/x2/creative/web/seasons")
125            .query(&query)
126            .send_bpi("获取合集列表").await
127    }
128}
129
130#[cfg(test)]
131mod tests {
132    use super::*;
133
134    #[tokio::test]
135    async fn test_season_list() -> Result<(), Box<BpiError>> {
136        let bpi = BpiClient::new();
137        let data = bpi.season_list(1, 10, Some("ctime"), Some("desc")).await?.into_data()?;
138
139        tracing::info!("共 {} 个合集", data.total);
140        for s in data.seasons {
141            tracing::info!("合集: {} - {}", s.season.id, s.season.title);
142        }
143
144        Ok(())
145    }
146}