1use super::models::{ ArticleAuthor, ArticleCategory, ArticleMedia, ArticleStats };
6use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
7use serde::{ Deserialize, Serialize };
8
9pub type CardResponse = BpiResponse<std::collections::HashMap<String, CardItem>>;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(untagged)]
15pub enum CardItem {
16 Video(VideoCard),
18 Article(ArticleCard),
20 Live(LiveCard),
22
23 Unknown(serde_json::Value),
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct VideoCard {
30 pub aid: i64,
32 pub bvid: String,
34 pub cid: i64,
36 pub copyright: i32,
38 pub pic: String,
40 pub ctime: i64,
42 pub desc: String,
44 pub dimension: VideoDimension,
46 pub duration: i64,
48 pub dynamic: String,
50 pub owner: VideoOwner,
52 pub pubdate: i64,
54 pub rights: VideoRights,
56 pub short_link_v2: String,
58 pub stat: VideoStat,
60 pub state: i32,
62 pub tid: i32,
64 pub title: String,
66 pub tname: String,
68 pub videos: i32,
70 pub vt_switch: bool,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct VideoDimension {
77 pub height: i32,
79 pub rotate: i32,
81 pub width: i32,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct VideoOwner {
88 pub face: String,
90 pub mid: i64,
92 pub name: String,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct VideoRights {
99 pub arc_pay: i32,
101 pub autoplay: i32,
103 pub bp: i32,
105 pub download: i32,
107 pub elec: i32,
109 pub hd5: i32,
111 pub is_cooperation: i32,
113 pub movie: i32,
115 pub no_background: i32,
117 pub no_reprint: i32,
119 pub pay: i32,
121 pub pay_free_watch: i32,
123 pub ugc_pay: i32,
125 pub ugc_pay_preview: i32,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct VideoStat {
132 pub aid: i64,
134 pub coin: i64,
136 pub danmaku: i64,
138 pub dislike: i64,
140 pub favorite: i64,
142 pub his_rank: i32,
144 pub like: i64,
146 pub now_rank: i32,
148 pub reply: i64,
150 pub share: i64,
152 pub view: i64,
154 pub vt: i32,
156 pub vv: i32,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct ArticleCard {
163 pub act_id: i64,
165 pub apply_time: String,
167 pub attributes: i32,
169 #[serde(rename = "authenMark")]
171 pub authen_mark: Option<serde_json::Value>,
172 pub author: ArticleAuthor,
174 pub banner_url: String,
176 pub categories: Vec<ArticleCategory>,
178 pub category: ArticleCategory,
180 pub check_state: i32,
182 pub check_time: String,
184 pub content_pic_list: Option<serde_json::Value>,
186 pub cover_avid: i64,
188 pub ctime: i64,
190 pub dispute: Option<serde_json::Value>,
192 pub dynamic: String,
194 pub id: i64,
196 pub image_urls: Vec<String>,
198 pub is_like: bool,
200 pub list: Option<ArticleList>,
202 pub media: ArticleMedia,
204 pub mtime: i64,
206 pub origin_image_urls: Vec<String>,
208 pub origin_template_id: i32,
210 pub original: i32,
212 pub private_pub: i32,
214 pub publish_time: i64,
216 pub reprint: i32,
218 pub state: i32,
220 pub stats: ArticleStats,
222 pub summary: String,
224 pub template_id: i32,
226 pub title: String,
228 pub top_video_info: Option<serde_json::Value>,
230 pub r#type: i32,
232 pub words: i64,
234}
235
236#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct AuthorVip {
239 pub avatar_subscript: i32,
241 pub due_date: i64,
243 pub label: VipLabel,
245 pub nickname_color: String,
247 pub status: i32,
249 pub theme_type: i32,
251 pub r#type: i32,
253 pub vip_pay_type: i32,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct VipLabel {
260 pub label_theme: String,
262 pub path: String,
264 pub text: String,
266}
267
268#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct ArticleList {
271 pub apply_time: String,
273 pub articles_count: i32,
275 pub check_time: String,
277 pub ctime: i64,
279 pub id: i64,
281 pub image_url: String,
283 pub mid: i64,
285 pub name: String,
287 pub publish_time: i64,
289 pub read: i64,
291 pub reason: String,
293 pub state: i32,
295 pub summary: String,
297 pub update_time: i64,
299 pub words: i64,
301}
302
303#[derive(Debug, Clone, Serialize, Deserialize)]
305pub struct LiveCard {
306 pub area_v2_name: String,
308 pub cover: String,
310 pub face: String,
312 pub live_status: i32,
314 pub online: i64,
316 pub pendent_ru: String,
318 pub pendent_ru_color: String,
320 pub pendent_ru_pic: String,
322 pub role: i32,
324 pub room_id: i64,
326 pub title: String,
328 pub uid: i64,
330 pub uname: String,
332}
333
334impl BpiClient {
335 pub async fn article_cards(&self, ids: &str) -> Result<CardResponse, BpiError> {
345 let params = vec![("ids", ids.to_string()), ("web_location", "333.1305".to_string())];
346
347 let params = self.get_wbi_sign2(params).await?;
348
349 let result: CardResponse = self
350 .get("https://api.bilibili.com/x/article/cards")
351 .with_bilibili_headers()
352 .query(¶ms)
353 .send_bpi("获取专栏显示卡片信息").await?;
354
355 Ok(result)
356 }
357}
358
359#[cfg(test)]
360mod tests {
361 use super::*;
362
363 #[tokio::test]
364 async fn test_get_article_cards() -> Result<(), Box<BpiError>> {
365 let bpi = BpiClient::new();
366
367 let ids = "av2,cv1,cv2";
368
369 let result = bpi.article_cards(ids).await?;
370 let data = result.into_data()?;
371 tracing::info!("{:#?}", data);
372
373 Ok(())
374 }
375}