use super::models::{ ArticleAuthor, ArticleCategory, ArticleMedia, ArticleStats };
use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
use serde::{ Deserialize, Serialize };
pub type CardResponse = BpiResponse<std::collections::HashMap<String, CardItem>>;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum CardItem {
Video(VideoCard),
Article(ArticleCard),
Live(LiveCard),
Unknown(serde_json::Value),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoCard {
pub aid: i64,
pub bvid: String,
pub cid: i64,
pub copyright: i32,
pub pic: String,
pub ctime: i64,
pub desc: String,
pub dimension: VideoDimension,
pub duration: i64,
pub dynamic: String,
pub owner: VideoOwner,
pub pubdate: i64,
pub rights: VideoRights,
pub short_link_v2: String,
pub stat: VideoStat,
pub state: i32,
pub tid: i32,
pub title: String,
pub tname: String,
pub videos: i32,
pub vt_switch: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoDimension {
pub height: i32,
pub rotate: i32,
pub width: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoOwner {
pub face: String,
pub mid: i64,
pub name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoRights {
pub arc_pay: i32,
pub autoplay: i32,
pub bp: i32,
pub download: i32,
pub elec: i32,
pub hd5: i32,
pub is_cooperation: i32,
pub movie: i32,
pub no_background: i32,
pub no_reprint: i32,
pub pay: i32,
pub pay_free_watch: i32,
pub ugc_pay: i32,
pub ugc_pay_preview: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoStat {
pub aid: i64,
pub coin: i64,
pub danmaku: i64,
pub dislike: i64,
pub favorite: i64,
pub his_rank: i32,
pub like: i64,
pub now_rank: i32,
pub reply: i64,
pub share: i64,
pub view: i64,
pub vt: i32,
pub vv: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArticleCard {
pub act_id: i64,
pub apply_time: String,
pub attributes: i32,
#[serde(rename = "authenMark")]
pub authen_mark: Option<serde_json::Value>,
pub author: ArticleAuthor,
pub banner_url: String,
pub categories: Vec<ArticleCategory>,
pub category: ArticleCategory,
pub check_state: i32,
pub check_time: String,
pub content_pic_list: Option<serde_json::Value>,
pub cover_avid: i64,
pub ctime: i64,
pub dispute: Option<serde_json::Value>,
pub dynamic: String,
pub id: i64,
pub image_urls: Vec<String>,
pub is_like: bool,
pub list: Option<ArticleList>,
pub media: ArticleMedia,
pub mtime: i64,
pub origin_image_urls: Vec<String>,
pub origin_template_id: i32,
pub original: i32,
pub private_pub: i32,
pub publish_time: i64,
pub reprint: i32,
pub state: i32,
pub stats: ArticleStats,
pub summary: String,
pub template_id: i32,
pub title: String,
pub top_video_info: Option<serde_json::Value>,
pub r#type: i32,
pub words: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthorVip {
pub avatar_subscript: i32,
pub due_date: i64,
pub label: VipLabel,
pub nickname_color: String,
pub status: i32,
pub theme_type: i32,
pub r#type: i32,
pub vip_pay_type: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VipLabel {
pub label_theme: String,
pub path: String,
pub text: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArticleList {
pub apply_time: String,
pub articles_count: i32,
pub check_time: String,
pub ctime: i64,
pub id: i64,
pub image_url: String,
pub mid: i64,
pub name: String,
pub publish_time: i64,
pub read: i64,
pub reason: String,
pub state: i32,
pub summary: String,
pub update_time: i64,
pub words: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LiveCard {
pub area_v2_name: String,
pub cover: String,
pub face: String,
pub live_status: i32,
pub online: i64,
pub pendent_ru: String,
pub pendent_ru_color: String,
pub pendent_ru_pic: String,
pub role: i32,
pub room_id: i64,
pub title: String,
pub uid: i64,
pub uname: String,
}
impl BpiClient {
pub async fn article_cards(&self, ids: &str) -> Result<CardResponse, BpiError> {
let params = vec![("ids", ids.to_string()), ("web_location", "333.1305".to_string())];
let params = self.get_wbi_sign2(params).await?;
let result: CardResponse = self
.get("https://api.bilibili.com/x/article/cards")
.with_bilibili_headers()
.query(¶ms)
.send_bpi("获取专栏显示卡片信息").await?;
Ok(result)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_get_article_cards() -> Result<(), Box<BpiError>> {
let bpi = BpiClient::new();
let ids = "av2,cv1,cv2";
let result = bpi.article_cards(ids).await?;
let data = result.into_data()?;
tracing::info!("{:#?}", data);
Ok(())
}
}