use super::models::{ ArticleAuthor, ArticleCategory, ArticleMedia, ArticleStats };
use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
use serde::{ Deserialize, Serialize };
pub type ArticleViewResponse = BpiResponse<ArticleViewData>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArticleViewData {
pub act_id: i64,
pub apply_time: String,
pub attributes: Option<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: String,
pub content_pic_list: Option<serde_json::Value>,
pub cover_avid: i64,
pub ctime: i64,
pub dispute: Option<serde_json::Value>,
pub dyn_id_str: String,
pub dynamic: Option<String>,
pub id: i64,
pub image_urls: Vec<String>,
pub is_like: bool,
pub keywords: String,
pub list: Option<ArticleList>,
pub media: ArticleMedia,
pub mtime: i64,
pub opus: Option<ArticleOpus>,
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 tags: Vec<ArticleTag>,
pub template_id: i32,
pub title: String,
pub top_video_info: Option<serde_json::Value>,
pub total_art_num: i64,
pub r#type: i32,
pub version_id: i64,
pub words: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthorVip {
pub r#type: i32,
pub status: i32,
pub due_date: i64,
pub vip_pay_type: i32,
pub theme_type: i32,
pub label: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArticleList {
pub id: i64,
pub name: String,
pub image_url: String,
pub update_time: i64,
pub ctime: i64,
pub publish_time: i64,
pub summary: String,
pub words: i64,
pub read: i64,
pub articles_count: i32,
pub state: i32,
pub reason: String,
pub apply_time: String,
pub check_time: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArticleTag {
pub tid: i32,
pub name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArticleOpus {
pub ops: Vec<OpusOperation>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpusOperation {
pub attribute: Option<OpusAttribute>,
pub insert: OpusInsert,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpusAttribute {
pub align: Option<String>,
pub blockquote: Option<bool>,
pub bold: Option<bool>,
pub class: Option<String>,
pub color: Option<String>,
pub header: Option<i32>,
pub strike: Option<bool>,
pub link: Option<String>,
pub italic: Option<bool>,
pub list: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OpusInsert {
Text(String),
Rich(OpusRichInsert),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpusRichInsert {
pub native_image: Option<OpusImage>,
pub cut_off: Option<OpusCutOff>,
pub video_card: Option<OpusVideoCard>,
pub article_card: Option<OpusArticleCard>,
pub vote_card: Option<OpusVoteCard>,
pub live_card: Option<OpusLiveCard>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpusImage {
pub alt: String,
pub url: String,
pub width: i32,
pub height: i32,
pub size: i64,
pub status: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpusCutOff {
pub r#type: String,
pub url: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpusVideoCard {
pub alt: String,
pub height: i32,
pub id: String,
pub size: Option<serde_json::Value>,
pub status: String,
pub tid: f64,
pub url: String,
pub width: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpusArticleCard {
pub alt: String,
pub height: i32,
pub id: String,
pub size: Option<serde_json::Value>,
pub status: String,
pub tid: i32,
pub url: String,
pub width: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpusVoteCard {
pub alt: String,
pub height: i32,
pub id: String,
pub size: Option<serde_json::Value>,
pub status: String,
pub tid: i32,
pub url: String,
pub width: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpusLiveCard {
pub alt: String,
pub height: i32,
pub id: String,
pub size: Option<serde_json::Value>,
pub status: String,
pub tid: i32,
pub url: String,
pub width: i32,
}
impl BpiClient {
pub async fn article_view(&self, id: i64) -> Result<ArticleViewResponse, BpiError> {
let params = vec![("id", id.to_string()), ("gaia_source", "main_web".to_string())];
let params = self.get_wbi_sign2(params).await?;
let result: ArticleViewResponse = self
.get("https://api.bilibili.com/x/article/view")
.query(¶ms)
.send_bpi("获取专栏正文内容").await?;
Ok(result)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_article_view() -> Result<(), Box<BpiError>> {
let bpi = BpiClient::new();
let cvid = 2;
let result = bpi.article_view(cvid).await?;
let data = result.data.unwrap();
assert!(!data.title.is_empty());
assert!(!data.content.is_empty());
assert!(!data.author.name.is_empty());
Ok(())
}
}