bpi_rs/creativecenter/season/
list.rs1use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
6use serde::{ Deserialize, Serialize };
7
8use super::models::{ Season, Section };
9
10#[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#[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#[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#[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#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct SectionsWrapper {
60 pub sections: Vec<Section>,
61}
62
63#[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 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}