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(
266 &self,
267 dynamic_id: &str,
268 offset: Option<&str>,
269 ) -> Result<BpiResponse<RepostDetailResponseData>, BpiError> {
270 let mut req = self
271 .get("https://api.vc.bilibili.com/dynamic_repost/v1/dynamic_repost/repost_detail")
272 .query(&[("dynamic_id", dynamic_id)]);
273
274 if let Some(o) = offset {
275 req = req.query(&[("offset", o)]);
276 }
277
278 req.send_bpi("获取动态转发列表").await
279 }
280
281 pub async fn dynamic_spec_item_likes(
299 &self,
300 dynamic_id: u64,
301 pn: Option<u64>,
302 ps: Option<u64>,
303 ) -> Result<BpiResponse<SpecItemLikesResponseData>, BpiError> {
304 let pn_val = pn.unwrap_or(1);
305 let ps_val = ps.unwrap_or(20);
306
307 let req = self
308 .get("https://api.vc.bilibili.com/dynamic_like/v1/dynamic_like/spec_item_likes")
309 .query(&[
310 ("dynamic_id", &dynamic_id.to_string()),
311 ("pn", &pn_val.to_string()),
312 ("ps", &ps_val.to_string()),
313 ]);
314
315 req.send_bpi("获取动态点赞列表").await
316 }
317
318 #[allow(dead_code)]
322 async fn get_drafts(&self) -> Result<BpiResponse<GetDraftsResponseData>, BpiError> {
323 let req = self.get("https://api.vc.bilibili.com/dynamic_draft/v1/dynamic_draft/get_drafts");
324
325 req.send_bpi("获取草稿列表").await
326 }
327}
328
329#[cfg(test)]
330mod tests {
331 use super::*;
332 use tracing::info;
333
334 #[tokio::test]
335
336 async fn test_get_repost_detail() -> Result<(), BpiError> {
337 let bpi = BpiClient::new();
338 let dynamic_id = "1099138163191840776";
340 let resp = bpi.dynamic_repost_detail(dynamic_id, None).await?;
341 let data = resp.into_data()?;
342
343 info!("动态转发列表测试结果: {:?}", data);
344 assert!(!data.items.iter().len() > 0);
345
346 Ok(())
347 }
348}