1use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
5use serde::{ Deserialize, Serialize };
6
7#[derive(Debug, Clone, Deserialize, Serialize)]
11pub struct AiSummaryPartOutline {
12 pub timestamp: u64,
14 pub content: String,
16}
17
18#[derive(Debug, Clone, Deserialize, Serialize)]
20pub struct AiSummaryOutline {
21 pub title: String,
23 pub part_outline: Vec<AiSummaryPartOutline>,
25 pub timestamp: u64,
27}
28
29#[derive(Debug, Clone, Deserialize, Serialize)]
31pub struct AiSummaryModelResult {
32 pub result_type: u8,
34 pub summary: String,
36 pub outline: Option<Vec<AiSummaryOutline>>,
38}
39
40#[derive(Debug, Clone, Deserialize, Serialize)]
42pub struct AiSummaryResponseData {
43 pub code: i8,
45 pub model_result: Option<AiSummaryModelResult>,
47 pub stid: Option<String>,
49 pub status: Option<u8>,
50 pub like_num: u64,
52 pub dislike_num: u64,
54}
55
56impl BpiClient {
57 pub async fn video_ai_summary(
72 &self,
73 aid: Option<u64>,
74 bvid: Option<&str>,
75 cid: u64,
76 up_mid: u64
77 ) -> Result<BpiResponse<AiSummaryResponseData>, BpiError> {
78 if aid.is_none() && bvid.is_none() {
79 return Err(BpiError::parse("必须提供 aid 或 bvid"));
80 }
81
82 let mut params = vec![("cid", cid.to_string()), ("up_mid", up_mid.to_string())];
83
84 if let Some(a) = aid {
85 params.push(("aid", a.to_string()));
86 }
87
88 if let Some(b) = bvid {
89 params.push(("bvid", b.to_string()));
90 }
91
92 let wbi_params = self.get_wbi_sign2(params).await?;
93
94 let req = self
95 .get("https://api.bilibili.com/x/web-interface/view/conclusion/get")
96 .query(&wbi_params);
97
98 req.send_bpi("获取视频 AI 总结内容").await
99 }
100}
101
102#[cfg(test)]
105mod tests {
106 use super::*;
107 use tracing::info;
108
109 const TEST_AID: u64 = 10001;
110
111 const TEST_CID: u64 = 16546;
112 const TEST_UP_MID: u64 = 34893;
113
114 #[tokio::test]
115 async fn test_video_ai_summary_by_aid() -> Result<(), BpiError> {
116 let bpi = BpiClient::new();
117 let resp = bpi.video_ai_summary(Some(TEST_AID), None, TEST_CID, TEST_UP_MID).await?;
118 let data = resp.into_data()?;
119
120 info!("视频 AI 总结: {:?}", data);
121
122 if data.code == 0 {
123 assert!(data.model_result.is_some());
124 }
125
126 Ok(())
127 }
128}