bpi_rs/live/
report.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{BilibiliRequest, BpiClient, BpiError, BpiResponse};
4use base64::{Engine as _, engine::general_purpose};
5
6// ================= 数据结构 =================
7
8#[derive(Debug, Serialize, Clone, Deserialize)]
9pub struct HeartBeatData {
10    /// 下次心跳间隔
11    pub next_interval: i32,
12}
13
14pub type HeartBeatResponse = BpiResponse<HeartBeatData>;
15
16// ================= 实现 =================
17
18impl BpiClient {
19    /// 直播心跳 (Web端)
20    ///
21    /// 对应: https://live-trace.bilibili.com/xlive/rdata-interface/v1/heartbeat/webHeartBeat
22    /// 文档: https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/live
23    pub async fn live_web_heart_beat(
24        &self,
25        room_id: i64,
26        next_interval: Option<i32>,
27        platform: Option<&str>,
28    ) -> Result<HeartBeatResponse, BpiError> {
29        // 构建心跳数据
30        let interval = next_interval.unwrap_or(60);
31        let heart_beat_data = format!("{interval}|{room_id}|1|0");
32
33        // Base64编码
34        let encoded_hb = general_purpose::STANDARD.encode(heart_beat_data);
35
36        let mut params: Vec<(&str, String)> = vec![("hb", encoded_hb)];
37
38        if let Some(platform) = platform {
39            params.push(("pf", platform.to_string()));
40        } else {
41            params.push(("pf", "web".to_string()));
42        }
43
44        let resp: HeartBeatResponse = self
45            .get("https://live-trace.bilibili.com/xlive/rdata-interface/v1/heartbeat/webHeartBeat")
46            .query(&params)
47            .send_bpi("直播心跳上报")
48            .await?;
49
50        Ok(resp)
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[tokio::test]
59    async fn test_web_heart_beat() -> Result<(), Box<BpiError>> {
60        let bpi = BpiClient::new();
61        let resp = bpi.live_web_heart_beat(23174842, None, None).await?;
62
63        let data = resp.data.unwrap();
64
65        assert!(data.next_interval > 0);
66        Ok(())
67    }
68}