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