1use crate::models::Vip;
2use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
3use serde::{ Deserialize, Serialize };
4use serde_json::Value;
5#[derive(Debug, Clone, Deserialize, Serialize)]
10pub struct RepostItem {
11 pub desc: Desc,
12 pub card: String,
13 pub extend_json: String,
14 pub display: Display,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct Desc {
19 pub uid: i64,
20 #[serde(rename = "type")]
21 pub type_field: i64,
22 pub rid: i64,
23 pub acl: i64,
24 pub view: i64,
25 pub repost: i64,
26 pub comment: i64,
27 pub like: i64,
28 pub is_liked: i64,
29 pub dynamic_id: i64,
30 pub timestamp: i64,
31 pub pre_dy_id: i64,
32 pub orig_dy_id: i64,
33 pub orig_type: i64,
34 pub user_profile: UserProfile,
35 pub spec_type: i64,
36 pub uid_type: i64,
37 pub stype: i64,
38 pub r_type: i64,
39 pub inner_id: i64,
40 pub status: i64,
41 pub dynamic_id_str: String,
42 pub pre_dy_id_str: String,
43 pub orig_dy_id_str: String,
44 pub rid_str: String,
45 pub origin: Origin,
46 pub bvid: String,
47 pub previous: Value,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct UserProfile {
52 pub info: Info,
53 pub card: Card,
54 pub vip: Vip,
55 pub pendant: Pendant,
56 pub rank: String,
57 pub sign: String,
58 pub level_info: LevelInfo,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct Info {
63 pub uid: i64,
64 pub uname: String,
65 pub face: String,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct Card {
70 pub official_verify: OfficialVerify,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct OfficialVerify {
75 #[serde(rename = "type")]
76 pub type_field: i64,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct Label {
81 pub path: String,
82 pub text: String,
83 pub label_theme: String,
84 pub text_color: String,
85 pub bg_style: i64,
86 pub bg_color: String,
87 pub border_color: String,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct Pendant {
92 pub pid: i64,
93 pub name: String,
94 pub image: String,
95 pub expire: i64,
96 pub image_enhance: String,
97 pub image_enhance_frame: String,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct LevelInfo {
102 pub current_level: i64,
103 pub current_min: i64,
104 pub current_exp: i64,
105 pub next_exp: String,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct Origin {
110 pub uid: i64,
111 #[serde(rename = "type")]
112 pub type_field: i64,
113 pub rid: i64,
114 pub acl: i64,
115 pub view: i64,
116 pub repost: i64,
117 pub comment: i64,
118 pub like: i64,
119 pub is_liked: i64,
120 pub dynamic_id: i64,
121 pub timestamp: i64,
122 pub pre_dy_id: i64,
123 pub orig_dy_id: i64,
124 pub orig_type: i64,
125 pub user_profile: Value,
126 pub spec_type: i64,
127 pub uid_type: i64,
128 pub stype: i64,
129 pub r_type: i64,
130 pub inner_id: i64,
131 pub status: i64,
132 pub dynamic_id_str: String,
133 pub pre_dy_id_str: String,
134 pub orig_dy_id_str: String,
135 pub rid_str: String,
136 pub origin: Value,
137 pub bvid: String,
138 pub previous: Value,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct Display {
143 pub origin: Origin2,
144 pub usr_action_txt: String,
145 pub relation: Relation2,
146 pub live_info: Value,
147 pub emoji_info: EmojiInfo2,
148 pub highlight: Value,
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct Origin2 {
153 pub origin: Value,
154 pub usr_action_txt: String,
155 pub relation: Relation,
156 pub live_info: Value,
157 pub emoji_info: EmojiInfo,
158 pub highlight: Value,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct Relation {
163 pub status: i64,
164 pub is_follow: i64,
165 pub is_followed: i64,
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct EmojiInfo {
170 pub emoji_details: Value,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct Relation2 {
175 pub status: i64,
176 pub is_follow: i64,
177 pub is_followed: i64,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct EmojiInfo2 {
182 pub emoji_details: Value,
183}
184
185#[derive(Debug, Clone, Deserialize, Serialize)]
187pub struct LikeItem {
188 }
191
192#[derive(Debug, Clone, Deserialize, Serialize)]
194pub struct PlainTextRequest {
195 pub content: String,
197 }
199
200#[derive(Debug, Clone, Deserialize, Serialize)]
202pub struct Draft {
203 pub draft_id: String,
205 pub publish_time: u64,
207 #[serde(rename = "type")]
209 pub type_num: u8,
210 pub uid: u64,
212 pub user_profile: UserProfile,
214 pub request: String,
216}
217
218#[derive(Debug, Clone, Deserialize, Serialize)]
220pub struct RepostDetailResponseData {
221 pub has_more: Option<bool>,
223 pub total: u64,
225 pub items: Vec<RepostItem>,
227}
228
229#[derive(Debug, Clone, Deserialize, Serialize)]
231pub struct SpecItemLikesResponseData {
232 pub item_likes: Vec<LikeItem>,
234 pub has_more: bool,
236 pub total_count: u64,
238 pub gt: u64,
240}
241
242#[derive(Debug, Clone, Deserialize, Serialize)]
244pub struct GetDraftsResponseData {
245 pub drafts: Vec<Draft>,
247}
248
249impl BpiClient {
250 pub async fn dynamic_repost_detail(
267 &self,
268 dynamic_id: &str,
269 offset: Option<&str>
270 ) -> Result<BpiResponse<RepostDetailResponseData>, BpiError> {
271 let mut req = self
272 .get("https://api.vc.bilibili.com/dynamic_repost/v1/dynamic_repost/repost_detail")
273 .query(&[("dynamic_id", dynamic_id)]);
274
275 if let Some(o) = offset {
276 req = req.query(&[("offset", o)]);
277 }
278
279 req.send_bpi("获取动态转发列表").await
280 }
281
282 pub async fn dynamic_spec_item_likes(
301 &self,
302 dynamic_id: u64,
303 pn: Option<u64>,
304 ps: Option<u64>
305 ) -> Result<BpiResponse<SpecItemLikesResponseData>, BpiError> {
306 let pn_val = pn.unwrap_or(1);
307 let ps_val = ps.unwrap_or(20);
308
309 let req = self
310 .get("https://api.vc.bilibili.com/dynamic_like/v1/dynamic_like/spec_item_likes")
311 .query(
312 &[
313 ("dynamic_id", &dynamic_id.to_string()),
314 ("pn", &pn_val.to_string()),
315 ("ps", &ps_val.to_string()),
316 ]
317 );
318
319 req.send_bpi("获取动态点赞列表").await
320 }
321
322 #[allow(dead_code)]
326 async fn get_drafts(&self) -> Result<BpiResponse<GetDraftsResponseData>, BpiError> {
327 let req = self.get("https://api.vc.bilibili.com/dynamic_draft/v1/dynamic_draft/get_drafts");
328
329 req.send_bpi("获取草稿列表").await
330 }
331}
332
333#[cfg(test)]
334mod tests {
335 use super::*;
336 use tracing::info;
337
338 #[tokio::test]
339 async fn test_get_repost_detail() -> Result<(), BpiError> {
340 let bpi = BpiClient::new();
341 let dynamic_id = "1099138163191840776";
343 let resp = bpi.dynamic_repost_detail(dynamic_id, None).await?;
344 let data = resp.into_data()?;
345
346 info!("动态转发列表测试结果: {:?}", data);
347 assert!(!data.items.iter().len() > 0);
348
349 Ok(())
350 }
351}