Skip to main content

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    /// # 文档
90    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/live)
91    ///
92    /// # 参数
93    ///
94    /// | 名称 | 类型 | 说明 |
95    /// | ---- | ---- | ---- |
96    /// | `room_id` | i64 | 直播间 ID |
97    /// | `area_parent_id` | `Option<i32>` | 分区 ID |
98    /// | `area_id` | `Option<i32>` | 子分区 ID |
99    pub async fn live_room_gift_list(
100        &self,
101        room_id: i64,
102        area_parent_id: Option<i32>,
103        area_id: Option<i32>
104    ) -> Result<RoomGiftResponse, BpiError> {
105        let mut params: Vec<(&str, String)> = vec![
106            ("room_id", room_id.to_string()),
107            ("platform", "web".to_string())
108        ];
109
110        if let Some(area_parent_id) = area_parent_id {
111            params.push(("area_parent_id", area_parent_id.to_string()));
112        }
113
114        if let Some(area_id) = area_id {
115            params.push(("area_id", area_id.to_string()));
116        }
117
118        let resp: RoomGiftResponse = self
119            .get("https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/roomGiftList")
120            .query(&params)
121            .send_bpi("获取直播间礼物列表").await?;
122
123        Ok(resp)
124    }
125
126    /// 获取盲盒概率
127    ///
128
129    /// # 文档
130    /// [查看API文档](https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/live)
131    ///
132    /// # 参数
133    ///
134    /// | 名称 | 类型 | 说明 |
135    /// | ---- | ---- | ---- |
136    /// | `gift_id` | i64 | 盲盒礼物 ID |
137    pub async fn live_blind_gift_info(&self, gift_id: i64) -> Result<BlindGiftResponse, BpiError> {
138        let params = [("gift_id", gift_id.to_string())];
139
140        let resp: BlindGiftResponse = self
141            .get("https://api.live.bilibili.com/xlive/general-interface/v1/blindFirstWin/getInfo")
142            .query(&params)
143            .send_bpi("获取盲盒概率").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}