Skip to main content

bpi_rs/dynamic/
basic_info.rs

1use crate::models::Vip;
2use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
3use serde::{ Deserialize, Serialize };
4use serde_json::Value;
5// 以下结构体为API文档中未完全列出的部分,根据描述进行了推断和简化。
6// 如果您有完整的文档,请替换这些结构体。
7
8/// 动态转发列表中的转发项
9#[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/// 动态点赞列表中的点赞项
186#[derive(Debug, Clone, Deserialize, Serialize)]
187pub struct LikeItem {
188    // 由于API文档未详细列出字段,这里作为占位符。
189    // 请根据实际API响应填充此结构体。
190}
191
192/// 纯文本动态内容
193#[derive(Debug, Clone, Deserialize, Serialize)]
194pub struct PlainTextRequest {
195    // 假设纯文本动态内容有一个名为 `content` 的字段。
196    pub content: String,
197    // 其他字段...
198}
199
200/// 获取草稿列表中的单项
201#[derive(Debug, Clone, Deserialize, Serialize)]
202pub struct Draft {
203    /// 草稿id
204    pub draft_id: String,
205    /// 定时发送的秒级时间戳
206    pub publish_time: u64,
207    /// 动态类型
208    #[serde(rename = "type")]
209    pub type_num: u8,
210    /// 自己的mid
211    pub uid: u64,
212    /// 自己的用户信息
213    pub user_profile: UserProfile,
214    /// 动态内容
215    pub request: String,
216}
217
218/// 动态转发列表响应数据结构体
219#[derive(Debug, Clone, Deserialize, Serialize)]
220pub struct RepostDetailResponseData {
221    /// 是否还有下一页
222    pub has_more: Option<bool>,
223    /// 总计
224    pub total: u64,
225    /// 转发列表
226    pub items: Vec<RepostItem>,
227}
228
229/// 动态点赞列表响应数据结构体
230#[derive(Debug, Clone, Deserialize, Serialize)]
231pub struct SpecItemLikesResponseData {
232    /// 点赞信息列表主体
233    pub item_likes: Vec<LikeItem>,
234    /// 是否还有下一页
235    pub has_more: bool,
236    /// 总计点赞数
237    pub total_count: u64,
238    /// 作用尚不明确
239    pub gt: u64,
240}
241
242/// 获取草稿列表响应数据结构体
243#[derive(Debug, Clone, Deserialize, Serialize)]
244pub struct GetDraftsResponseData {
245    /// 草稿列表
246    pub drafts: Vec<Draft>,
247}
248
249impl BpiClient {
250    /// 动态转发列表
251    ///
252    /// 获取指定动态的转发列表。
253    ///
254    /// # 参数
255    /// * `dynamic_id` - 动态ID
256    /// * `offset` - 偏移量,非必要
257    /// # 文档
258    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/dynamic)
259    ///
260    /// # 参数
261    ///
262    /// | 名称 | 类型 | 说明 |
263    /// | ---- | ---- | ---- |
264    /// | `dynamic_id` | &str | 动态 ID |
265    /// | `offset` | `Option<&str>` | 偏移量 |
266    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    /// 动态点赞列表
283    ///
284    /// 获取指定动态的点赞列表。赞列表总计超过25K部分继续获取可能被限制
285    ///
286    /// # 参数
287    /// * `dynamic_id` - 动态ID
288    /// * `pn` - 页码,非必要,默认1
289    /// * `ps` - 每页数量,非必要,默认20
290    /// # 文档
291    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/dynamic)
292    ///
293    /// # 参数
294    ///
295    /// | 名称 | 类型 | 说明 |
296    /// | ---- | ---- | ---- |
297    /// | `dynamic_id` | u64 | 动态 ID |
298    /// | `pn` | `Option<u64>` | 页码,默认 1 |
299    /// | `ps` | `Option<u64>` | 页大小,默认 20 |
300    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    /// 获取草稿列表 (已失效?)
323    ///
324    /// 获取用户已保存的动态草稿列表。需要登录认证。
325    #[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        // 替换为有效的动态ID进行测试
342        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}