bpi_rs/live/
gift.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{BilibiliRequest, BpiClient, BpiError, BpiResponse};
4
5// ================= 数据结构 =================
6
7#[derive(Debug, Serialize, Clone, Deserialize)]
8pub struct GiftItem {
9    /// 礼物id
10    pub id: i64,
11    /// 礼物名字
12    pub name: String,
13    /// 价格(该值/1000的单位为元)
14    pub price: i64,
15    /// 类型
16    pub r#type: i32,
17    /// 货币类型(一般为gold,即电池)
18    pub coin_type: String,
19    /// 特效类型
20    pub effect: i32,
21    /// 礼物展示的时间
22    pub stay_time: i32,
23    /// 礼物动画帧数
24    pub animation_frame_num: i32,
25    /// 礼物描述
26    pub desc: String,
27    /// 礼物图片
28    pub img_basic: String,
29    /// 礼物gif动画
30    pub gif: String,
31}
32
33#[derive(Debug, Serialize, Clone, Deserialize)]
34pub struct GiftConfig {
35    /// 礼物列表
36    pub list: Vec<GiftItem>,
37}
38
39#[derive(Debug, Serialize, Clone, Deserialize)]
40pub struct GiftBaseConfig {
41    /// 基础配置
42    pub base_config: GiftConfig,
43}
44
45#[derive(Debug, Serialize, Clone, Deserialize)]
46pub struct RoomGiftData {
47    /// 礼物配置
48    pub gift_config: GiftBaseConfig,
49}
50
51pub type RoomGiftResponse = BpiResponse<RoomGiftData>;
52
53#[derive(Debug, Serialize, Clone, Deserialize)]
54pub struct BlindGiftItem {
55    /// 爆出的礼物id
56    pub gift_id: i64,
57    /// 爆出的礼物价格
58    pub price: i64,
59    /// 礼物名字
60    pub gift_name: String,
61    /// 礼物图片
62    pub gift_img: String,
63    /// 概率
64    pub chance: String,
65}
66
67#[derive(Debug, Serialize, Clone, Deserialize)]
68pub struct BlindGiftData {
69    /// 描述
70    pub note_text: String,
71    /// 盲盒价格
72    pub blind_price: i64,
73    /// 盲盒名字
74    pub blind_gift_name: String,
75    /// 盲盒礼物列表
76    pub gifts: Vec<BlindGiftItem>,
77}
78
79pub type BlindGiftResponse = BpiResponse<BlindGiftData>;
80
81// ================= 实现 =================
82
83impl BpiClient {
84    /// 获取直播间内礼物
85    ///
86    /// area_parent_id: 直播分区
87    /// area_id: 直播子分区
88
89    /// 文档: https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/live
90    ///
91    /// 参数
92    ///
93    /// | 名称 | 类型 | 说明 |
94    /// | ---- | ---- | ---- |
95    /// | `room_id` | i64 | 直播间 ID |
96    /// | `area_parent_id` | Option<i32> | 分区 ID |
97    /// | `area_id` | Option<i32> | 子分区 ID |
98    pub async fn live_room_gift_list(
99        &self,
100        room_id: i64,
101        area_parent_id: Option<i32>,
102        area_id: Option<i32>,
103    ) -> Result<RoomGiftResponse, BpiError> {
104        let mut params: Vec<(&str, String)> = vec![
105            ("room_id", room_id.to_string()),
106            ("platform", "web".to_string()),
107        ];
108
109        if let Some(area_parent_id) = area_parent_id {
110            params.push(("area_parent_id", area_parent_id.to_string()));
111        }
112
113        if let Some(area_id) = area_id {
114            params.push(("area_id", area_id.to_string()));
115        }
116
117        let resp: RoomGiftResponse = self
118            .get("https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/roomGiftList")
119            .query(&params)
120            .send_bpi("获取直播间礼物列表")
121            .await?;
122
123        Ok(resp)
124    }
125
126    /// 获取盲盒概率
127    ///
128
129    /// 文档: https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/live
130    ///
131    /// 参数
132    ///
133    /// | 名称 | 类型 | 说明 |
134    /// | ---- | ---- | ---- |
135    /// | `gift_id` | i64 | 盲盒礼物 ID |
136    pub async fn live_blind_gift_info(&self, gift_id: i64) -> Result<BlindGiftResponse, BpiError> {
137        let params = [("gift_id", gift_id.to_string())];
138
139        let resp: BlindGiftResponse = self
140            .get("https://api.live.bilibili.com/xlive/general-interface/v1/blindFirstWin/getInfo")
141            .query(&params)
142            .send_bpi("获取盲盒概率")
143            .await?;
144
145        Ok(resp)
146    }
147}
148
149#[cfg(test)]
150mod tests {
151    use super::*;
152
153    #[tokio::test]
154    async fn test_get_room_gift_list() -> Result<(), Box<BpiError>> {
155        let bpi = BpiClient::new();
156        let resp = bpi.live_room_gift_list(23174842, None, None).await?;
157
158        let data = resp.data.unwrap();
159        assert!(data.gift_config.base_config.list.len() > 0);
160        Ok(())
161    }
162
163    #[tokio::test]
164    async fn test_get_blind_gift_info() -> Result<(), Box<BpiError>> {
165        let bpi = BpiClient::new();
166        let resp = bpi.live_blind_gift_info(32251).await?;
167
168        let data = resp.data.unwrap();
169        assert!(data.gifts.len() > 0);
170        Ok(())
171    }
172}