1use crate::article::models::ArticleStats;
6use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
7use serde::{ Deserialize, Serialize };
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct ArticleInfoData {
12 pub like: i32,
14 pub attention: bool,
16 pub favorite: bool,
18 pub coin: i32,
20 pub stats: ArticleStats,
22 pub title: String,
24 pub banner_url: String,
26 pub mid: i64,
28 pub author_name: String,
30 pub is_author: bool,
32 pub image_urls: Vec<String>,
34 pub origin_image_urls: Vec<String>,
36 pub shareable: bool,
38 pub show_later_watch: bool,
40 pub show_small_window: bool,
42 pub in_list: bool,
44 pub pre: i64,
46 pub next: i64,
48 pub share_channels: Vec<ShareChannel>,
50 pub r#type: i32,
52 #[serde(default)]
54 pub video_url: String,
55 #[serde(default)]
57 pub location: String,
58 #[serde(default)]
60 pub disable_share: bool,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct ShareChannel {
66 pub name: String,
68 pub picture: String,
70 pub share_channel: String,
72}
73
74impl BpiClient {
75 pub async fn article_info(&self, id: i64) -> Result<BpiResponse<ArticleInfoData>, BpiError> {
85 self
86 .get("https://api.bilibili.com/x/article/viewinfo")
87 .query(&[("id", id.to_string())])
88 .send_bpi("获取专栏文章基本信息").await
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 const TEST_CVID: i64 = 2;
97
98 #[tokio::test]
99 async fn test_article_info() -> Result<(), Box<BpiError>> {
100 let bpi = BpiClient::new();
101
102 let cvid = TEST_CVID;
103
104 let result = bpi.article_info(cvid).await?;
105
106 let data = result.data.unwrap();
107 assert!(!data.title.is_empty());
108 assert!(!data.author_name.is_empty());
109 assert!(data.mid > 0);
110
111 Ok(())
112 }
113
114 #[tokio::test]
115 async fn test_article_stats() -> Result<(), Box<BpiError>> {
116 let bpi = BpiClient::new();
117
118 let result = bpi.article_info(TEST_CVID).await?;
119
120 let data = result.data.unwrap();
121 let stats = &data.stats;
122 assert!(stats.view >= 0);
123 assert!(stats.favorite >= 0);
124 assert!(stats.like >= 0);
125 assert!(stats.reply >= 0);
126
127 Ok(())
128 }
129}