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(
71 &self,
72 aid: Option<u64>,
73 bvid: Option<&str>,
74 cid: u64,
75 up_mid: u64,
76 ) -> Result<BpiResponse<AiSummaryResponseData>, BpiError> {
77 if aid.is_none() && bvid.is_none() {
78 return Err(BpiError::parse("必须提供 aid 或 bvid"));
79 }
80
81 let mut params = vec![("cid", cid.to_string()), ("up_mid", up_mid.to_string())];
82
83 if let Some(a) = aid {
84 params.push(("aid", a.to_string()));
85 }
86
87 if let Some(b) = bvid {
88 params.push(("bvid", b.to_string()));
89 }
90
91 let wbi_params = self.get_wbi_sign2(params).await?;
92
93 let req = self
94 .get("https://api.bilibili.com/x/web-interface/view/conclusion/get")
95 .query(&wbi_params);
96
97 req.send_bpi("获取视频 AI 总结内容").await
98 }
99}
100
101#[cfg(test)]
104mod tests {
105 use super::*;
106 use tracing::info;
107
108 const TEST_AID: u64 = 10001;
109
110 const TEST_CID: u64 = 16546;
111 const TEST_UP_MID: u64 = 34893;
112
113 #[tokio::test]
114
115 async fn test_video_ai_summary_by_aid() -> Result<(), BpiError> {
116 let bpi = BpiClient::new();
117 let resp = bpi
118 .video_ai_summary(Some(TEST_AID), None, TEST_CID, TEST_UP_MID)
119 .await?;
120 let data = resp.into_data()?;
121
122 info!("视频 AI 总结: {:?}", data);
123
124 if data.code == 0 {
125 assert!(data.model_result.is_some());
126 }
127
128 Ok(())
129 }
130}