1use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
2use chrono::Utc;
3use reqwest::multipart::Form;
4use serde::{ Deserialize, Serialize };
5
6#[derive(Debug, Clone, Deserialize, Serialize)]
10pub struct SendDanmuData {
11 pub mode_info: Option<serde_json::Value>,
12 pub dm_v2: Option<serde_json::Value>,
13}
14
15impl BpiClient {
16 pub async fn live_send_danmu(
24 &self,
25 room_id: u64,
26 message: &str,
27 color: Option<u32>,
28 font_size: Option<u32>
29 ) -> Result<BpiResponse<SendDanmuData>, BpiError> {
30 let csrf = self.csrf()?;
31 let now = Utc::now().timestamp();
32
33 let mut form = Form::new()
35 .text("csrf", csrf.clone())
36 .text("roomid", room_id.to_string())
37 .text("msg", message.to_string())
38 .text("rnd", now.to_string())
39 .text("bubble", "0")
40 .text("mode", "1")
41 .text("statistics", r#"{"appId":100,"platform":5}"#)
42 .text("csrf_token", csrf); if let Some(c) = color {
45 form = form.text("color", c.to_string());
46 } else {
47 form = form.text("color", "16777215"); }
49
50 if let Some(s) = font_size {
51 form = form.text("fontsize", s.to_string());
52 } else {
53 form = form.text("fontsize", "25"); }
55
56 self
57 .post("https://api.live.bilibili.com/msg/send")
58 .multipart(form)
59 .send_bpi("发送直播弹幕").await
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 use tracing::info;
67
68 #[tokio::test]
69 async fn test_send_live_danmu() -> Result<(), BpiError> {
70 let bpi = BpiClient::new();
71 let room_id = 21733448;
73 let message = "牛";
74
75 let resp = bpi.live_send_danmu(room_id, &message, None, None).await?;
76 assert_eq!(resp.code, 0);
77 let data = resp.into_data()?;
78
79 info!("弹幕发送成功!返回数据: {:?}", data);
80
81 Ok(())
82 }
83}