1use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
5use serde::{ Deserialize, Serialize };
6
7#[derive(Debug, Clone, Deserialize, Serialize)]
11pub struct CreateSeriesResponseData {
12 pub series_id: u64,
14}
15
16impl BpiClient {
17 pub async fn collection_create_and_add_archives(
31 &self,
32 mid: u64,
33 name: &str,
34 keywords: Option<&str>,
35 description: Option<&str>,
36 aids: Option<&str>
37 ) -> Result<BpiResponse<CreateSeriesResponseData>, BpiError> {
38 let csrf = self.csrf()?;
39 let mut form = reqwest::multipart::Form
40 ::new()
41 .text("mid", mid.to_string())
42 .text("name", name.to_string());
43
44 if let Some(k) = keywords {
45 form = form.text("keywords", k.to_string());
46 }
47 if let Some(d) = description {
48 form = form.text("description", d.to_string());
49 }
50 if let Some(a) = aids {
51 form = form.text("aids", a.to_string());
52 }
53
54 self
55 .post("https://api.bilibili.com/x/series/series/createAndAddArchives")
56 .query(&[("csrf", csrf)])
57 .multipart(form)
58 .send_bpi("创建视频列表并添加视频").await
59 }
60
61 pub async fn collection_delete_series(
72 &self,
73 mid: u64,
74 series_id: u64
75 ) -> Result<BpiResponse<serde_json::Value>, BpiError> {
76 let csrf = self.csrf()?;
77
78 self
79 .post("https://api.bilibili.com/x/series/series/delete")
80 .query(
81 &[
82 ("csrf", csrf),
83 ("mid", mid.to_string()),
84 ("series_id", series_id.to_string()),
85 ("aids", "".to_string()),
86 ]
87 )
88 .send_bpi("删除视频列表").await
89 }
90
91 pub async fn collection_delete_archives_from_series(
103 &self,
104 mid: u64,
105 series_id: u64,
106 aids: &str
107 ) -> Result<BpiResponse<serde_json::Value>, BpiError> {
108 let csrf = self.csrf()?;
109
110 let params = [
111 ("mid", mid.to_string()),
112 ("series_id", series_id.to_string()),
113 ("aids", aids.to_string()),
114 ];
115
116 self
117 .post("https://api.bilibili.com/x/series/series/delArchives")
118 .query(&[("csrf", csrf)])
119 .form(¶ms)
120 .send_bpi("从视频列表中删除稿件").await
121 }
122
123 pub async fn collection_add_archives_to_series(
135 &self,
136 mid: u64,
137 series_id: u64,
138 aids: &str
139 ) -> Result<BpiResponse<serde_json::Value>, BpiError> {
140 let csrf = self.csrf()?;
141
142 let params = [
143 ("mid", mid.to_string()),
144 ("series_id", series_id.to_string()),
145 ("aids", aids.to_string()),
146 ];
147
148 self
149 .post("https://api.bilibili.com/x/series/series/addArchives")
150 .query(&[("csrf", csrf)])
151 .form(¶ms)
152 .send_bpi("添加稿件至视频列表").await
153 }
154
155 pub async fn collection_update_series(
171 &self,
172 mid: u64,
173 series_id: u64,
174 name: &str,
175 keywords: Option<&str>,
176 description: Option<&str>,
177 add_aids: Option<&str>,
178 del_aids: Option<&str>
179 ) -> Result<BpiResponse<serde_json::Value>, BpiError> {
180 let csrf = self.csrf()?;
181
182 let mut form = reqwest::multipart::Form
183 ::new()
184 .text("mid", mid.to_string())
185 .text("series_id", series_id.to_string())
186 .text("name", name.to_string());
187
188 if let Some(k) = keywords {
189 form = form.text("keywords", k.to_string());
190 }
191 if let Some(d) = description {
192 form = form.text("description", d.to_string());
193 }
194 if let Some(a) = add_aids {
195 form = form.text("add_aids", a.to_string());
196 }
197 if let Some(d) = del_aids {
198 form = form.text("del_aids", d.to_string());
199 }
200
201 self
202 .post("https://api.bilibili.com/x/series/series/update")
203 .query(&[("csrf", csrf)])
204 .multipart(form)
205 .send_bpi("编辑视频列表信息").await
206 }
207}
208
209#[cfg(test)]
212mod tests {
213 use super::*;
214 use tracing::info;
215
216 const TEST_MID: u64 = 4279370;
221 const TEST_SERIES_ID: u64 = 4954206;
223
224 const TEST_AID: &str = "772876546";
225
226 #[tokio::test]
227 async fn test_create_and_add_archives() -> Result<(), BpiError> {
228 let bpi = BpiClient::new();
229 let resp = bpi.collection_create_and_add_archives(
230 TEST_MID,
231 "Rust Bilibili API Test",
232 Some("rust,api"),
233 Some("这是一个用于 Rust Bilibili API 测试的视频列表"),
234 Some(TEST_AID)
235 ).await?;
236 let data = resp.into_data()?;
237
238 info!("创建的视频列表 ID: {:?}", data.series_id);
239 assert!(data.series_id > 0);
240
241 Ok(())
242 }
243
244 #[tokio::test]
245 async fn test_add_archives_to_series() -> Result<(), BpiError> {
246 let bpi = BpiClient::new();
247 let resp = bpi.collection_add_archives_to_series(TEST_MID, TEST_SERIES_ID, TEST_AID).await?;
248
249 info!("添加稿件至视频列表成功: {:?}", resp);
250
251 Ok(())
252 }
253
254 #[tokio::test]
255 async fn test_update_series() -> Result<(), BpiError> {
256 let bpi = BpiClient::new();
257 let resp = bpi.collection_update_series(
258 TEST_MID,
259 TEST_SERIES_ID,
260 "Rust Bilibili API Test Updated",
261 Some("rust,api,update"),
262 Some("更新后的简介"),
263 Some(TEST_AID),
264 None
265 ).await?;
266
267 info!("编辑视频列表成功: {:?}", resp);
268
269 Ok(())
270 }
271
272 #[tokio::test]
273 async fn test_delete_archives_from_series() -> Result<(), BpiError> {
274 let bpi = BpiClient::new();
275 let resp = bpi.collection_delete_archives_from_series(
276 TEST_MID,
277 TEST_SERIES_ID,
278 TEST_AID
279 ).await?;
280
281 info!("从视频列表中删除稿件成功: {:?}", resp);
282
283 Ok(())
284 }
285
286 #[tokio::test]
287 async fn test_delete_series() -> Result<(), BpiError> {
288 let bpi = BpiClient::new();
289 let resp = bpi.collection_delete_series(TEST_MID, TEST_SERIES_ID).await?;
291
292 info!("删除视频列表成功: {:?}", resp);
293
294 Ok(())
295 }
296}