use chrono::NaiveDate;
use serde::{ Deserialize, Serialize };
use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
#[derive(Debug, Clone, Serialize)]
pub struct SendElecMessageBody<'a> {
pub order_id: &'a str,
pub message: &'a str,
pub csrf: &'a str,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ElecRemarkPager {
pub current: u64,
pub size: u64,
pub total: u64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ElecRemarkRecord {
pub aid: u64,
pub bvid: String,
pub id: u64,
pub mid: u64,
pub reply_mid: u64,
pub elec_num: u64,
pub state: u8,
pub msg: String,
pub aname: String,
pub uname: String,
pub avator: String,
pub reply_name: String,
pub reply_avator: String,
pub reply_msg: String,
pub ctime: u64,
pub reply_time: u64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ElecRemarkList {
pub list: Vec<ElecRemarkRecord>,
pub pager: ElecRemarkPager,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ElecRemarkDetail {
pub aid: u64,
pub bvid: String,
pub id: u64,
pub mid: u64,
pub reply_mid: u64,
pub elec_num: u64,
pub state: u8,
pub msg: String,
pub aname: String,
pub uname: String,
pub avator: String,
pub reply_name: String,
pub reply_avator: String,
pub reply_msg: String,
pub ctime: u64,
pub reply_time: u64,
}
impl BpiClient {
pub async fn electric_message_send(
&self,
order_id: &str,
message: &str
) -> Result<BpiResponse<serde_json::Value>, BpiError> {
let csrf = self.csrf()?;
let body = [
("order_id", order_id),
("message", message),
("csrf", &csrf),
];
self
.post("https://api.bilibili.com/x/ugcpay/trade/elec/message")
.form(&body)
.send_bpi("发送充电留言").await
}
pub async fn electric_remark_list(
&self,
pn: Option<u64>,
ps: Option<u64>,
begin: Option<NaiveDate>,
end: Option<NaiveDate>
) -> Result<BpiResponse<ElecRemarkList>, BpiError> {
let mut req = self.get("https://member.bilibili.com/x/web/elec/remark/list");
if let Some(page) = pn {
req = req.query(&[("pn", page)]);
}
if let Some(size) = ps {
req = req.query(&[("ps", size)]);
}
if let Some(begin_date) = begin {
req = req.query(&[("begin", begin_date.format("%Y-%m-%d").to_string())]);
}
if let Some(end_date) = end {
req = req.query(&[("end", end_date.format("%Y-%m-%d").to_string())]);
}
req.send_bpi("查询收到的充电留言").await
}
pub async fn electric_remark_detail(
&self,
id: u64
) -> Result<BpiResponse<ElecRemarkDetail>, BpiError> {
self
.get("https://member.bilibili.com/x/web/elec/remark/detail")
.query(&[("id", id)])
.send_bpi("查询充电留言详情").await
}
pub async fn electric_remark_reply(
&self,
id: u64,
msg: &str
) -> Result<BpiResponse<u64>, BpiError> {
let csrf = self.csrf()?;
let body = [
("id", id.to_string()),
("msg", msg.to_string()),
("csrf", csrf.to_string()),
];
self
.post("https://member.bilibili.com/x/web/elec/remark/reply")
.form(&body)
.send_bpi("回复充电留言").await
}
}
#[cfg(test)]
mod tests {
use super::*;
use tracing::info;
#[tokio::test]
async fn test_send_elec_message() {
let bpi = BpiClient::new();
let resp = bpi.electric_message_send("ORDER_ID_HERE", "测试留言").await;
info!("响应: {:?}", resp);
assert!(resp.is_ok());
}
#[tokio::test]
async fn test_get_elec_remark_list() {
let bpi = BpiClient::new();
let resp = bpi.electric_remark_list(Some(1), Some(10), None, None).await;
info!("响应: {:?}", resp);
assert!(resp.is_ok());
if let Ok(response) = resp {
let data = response.data.unwrap();
info!("留言总记录数: {}", data.pager.total);
info!("当前页留言记录数: {}", data.list.len());
}
}
#[tokio::test]
async fn test_get_elec_remark_detail() {
let bpi = BpiClient::new();
let resp = bpi.electric_remark_detail(6507563).await;
info!("响应: {:?}", resp);
assert!(resp.is_ok());
}
#[tokio::test]
async fn test_reply_elec_remark() {
let bpi = BpiClient::new();
let resp = bpi.electric_remark_reply(6507563, "测试回复").await;
info!("响应: {:?}", resp);
assert!(resp.is_ok());
}
}