use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
use serde::{ Deserialize, Serialize };
use super::types::{
Comment, Config,
Control,
Cursor,
PageInfo,
Top,
Upper,
};
pub type CommentListResponse = BpiResponse<CommentListData>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommentListData {
pub page: Option<PageInfo>,
pub cursor: Option<Cursor>, pub replies: Option<Vec<Comment>>, pub top: Option<Top>, pub top_replies: Option<Vec<Comment>>,
pub effects: Option<serde_json::Value>,
pub assist: Option<u64>, pub blacklist: Option<u64>, pub vote: Option<u64>, pub config: Option<Config>, pub upper: Option<Upper>,
pub control: Option<Control>, pub note: Option<u32>,
pub cm_info: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Notice {
pub content: Option<String>,
pub id: Option<u64>,
pub link: Option<String>,
pub title: Option<String>,
}
type HotCommentResponse = BpiResponse<HotCommentData>;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct HotCommentData {
pub page: HotCommentPage,
pub replies: Vec<Comment>, }
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct HotCommentPage {
pub acount: i64, pub count: i64, pub num: i32, pub size: i32, }
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CountData {
count: u64,
}
impl BpiClient {
pub async fn comment_list(
&self,
r#type: i32,
oid: i64,
pn: Option<i32>,
ps: Option<i32>,
sort: Option<i32>,
nohot: Option<i32>
) -> Result<CommentListResponse, BpiError> {
let mut params = vec![("type", r#type.to_string()), ("oid", oid.to_string())];
if let Some(pn) = pn {
params.push(("pn", pn.to_string()));
}
if let Some(ps) = ps {
params.push(("ps", ps.to_string()));
}
if let Some(sort) = sort {
params.push(("sort", sort.to_string()));
}
if let Some(nohot) = nohot {
params.push(("nohot", nohot.to_string()));
}
self
.get("https://api.bilibili.com/x/v2/reply")
.query(¶ms)
.send_bpi("获取评论主列表").await
}
pub async fn comment_replies(
&self,
r#type: i32,
oid: i64,
root: i64,
pn: Option<i32>,
ps: Option<i32>
) -> Result<CommentListResponse, BpiError> {
let mut params = vec![
("type", r#type.to_string()),
("oid", oid.to_string()),
("root", root.to_string())
];
if let Some(pn) = pn {
params.push(("pn", pn.to_string()));
}
if let Some(ps) = ps {
params.push(("ps", ps.to_string()));
}
self
.get("https://api.bilibili.com/x/v2/reply/reply")
.query(¶ms)
.send_bpi("获取子评论列表").await
}
pub async fn comment_hot(
&self,
r#type: i32,
oid: i64,
root: i64,
pn: Option<i32>,
ps: Option<i32>
) -> Result<HotCommentResponse, BpiError> {
let mut params = vec![
("type", r#type.to_string()),
("oid", oid.to_string()),
("root", root.to_string())
];
if let Some(pn) = pn {
params.push(("pn", pn.to_string()));
}
if let Some(ps) = ps {
params.push(("ps", ps.to_string()));
}
self
.get("https://api.bilibili.com/x/v2/reply/hot")
.query(¶ms)
.send_bpi("获取评论区热评列表").await
}
pub async fn comment_count(
&self,
r#type: i32,
oid: i64
) -> Result<BpiResponse<CountData>, BpiError> {
let params = [
("type", r#type.to_string()),
("oid", oid.to_string()),
];
self
.get("https://api.bilibili.com/x/v2/reply/count")
.query(¶ms)
.send_bpi("获取评论区评论总数").await
}
}
#[cfg(test)]
mod tests {
use super::*;
use tracing::info;
const TEST_TYPE: i32 = 1;
const TEST_OID: i64 = 23199;
const TEST_ROOT_RPID: i64 = 2554491176;
#[tokio::test]
async fn test_comment_list() -> Result<(), Box<BpiError>> {
let bpi = BpiClient::new();
let result = bpi.comment_list(
TEST_TYPE,
TEST_OID,
Some(1),
Some(5),
Some(0),
Some(0)
).await?;
let data = result.into_data()?;
info!("总评论数: {}", data.replies.unwrap().len());
Ok(())
}
#[tokio::test]
async fn test_comment_replies() -> Result<(), Box<BpiError>> {
let bpi = BpiClient::new();
let result = bpi.comment_replies(
TEST_TYPE,
TEST_OID,
TEST_ROOT_RPID,
Some(1),
Some(5)
).await?;
let data = result.into_data()?;
info!("总评论数: {}", data.replies.unwrap().len());
Ok(())
}
#[tokio::test]
async fn test_comment_hot() -> Result<(), Box<BpiError>> {
let bpi = BpiClient::new();
let root_rpid = 654321;
let result = bpi.comment_hot(TEST_TYPE, TEST_OID, root_rpid, Some(1), Some(5)).await?;
let data = result.into_data()?;
info!("热评数量: {}", data.replies.len());
for comment in data.replies.iter() {
info!("热评内容: {}", comment.content.message);
}
Ok(())
}
#[tokio::test]
async fn test_comment_count() -> Result<(), Box<BpiError>> {
let bpi = BpiClient::new();
let result = bpi.comment_count(TEST_TYPE, TEST_OID).await?;
let data = result.into_data()?;
info!("评论总数: {}", data.count);
Ok(())
}
}