use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
use serde::{ Deserialize, Serialize };
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ActivityListData {
pub list: Vec<ActivityItem>,
pub num: i32,
pub size: i32,
pub total: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ActivityItem {
pub id: i32,
pub state: i32,
pub stime: i64,
pub etime: i64,
pub ctime: i64,
pub mtime: i64,
pub name: String,
pub h5_url: String,
pub h5_cover: String,
pub page_name: String,
pub plat: i32,
pub desc: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct ActivityListParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub plat: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mold: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub http: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pn: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ps: Option<i32>,
}
impl Default for ActivityListParams {
fn default() -> Self {
Self {
plat: Some("1,3".to_string()),
mold: Some(0),
http: Some(3),
pn: Some(1),
ps: Some(15),
}
}
}
impl BpiClient {
pub async fn activity_list(
&self,
plat: Option<&str>,
mold: Option<i32>,
http: Option<i32>,
pn: Option<i32>,
ps: Option<i32>
) -> Result<BpiResponse<ActivityListData>, BpiError> {
let params = ActivityListParams {
plat: plat.map(|s| s.to_string()).or_else(|| Some("1,3".to_string())),
mold: mold.or(Some(0)),
http: http.or(Some(3)),
pn: pn.or(Some(1)),
ps: ps.or(Some(15)),
};
let result = self
.get("https://api.bilibili.com/x/activity/page/list")
.query(¶ms)
.send_bpi("获取活动列表").await?;
Ok(result)
}
pub async fn activity_list_default(&self) -> Result<BpiResponse<ActivityListData>, BpiError> {
self.activity_list(Some("1,3"), None, None, Some(1), Some(15)).await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_get_activity_list() -> Result<(), Box<BpiError>> {
let bpi = BpiClient::new();
let result = bpi.activity_list(Some("1,3"), None, None, Some(1), Some(4)).await?;
let data = result.into_data()?;
tracing::info!("{:#?}", data);
assert!(!data.list.is_empty());
assert_eq!(data.num, 1);
assert_eq!(data.size, 4);
assert!(data.total > 0);
Ok(())
}
#[tokio::test]
async fn test_get_activity_list_simple() -> Result<(), Box<BpiError>> {
let bpi = BpiClient::new();
let result = bpi.activity_list_default().await?;
let data = result.into_data()?;
tracing::info!("{:#?}", data);
assert!(!data.list.is_empty());
assert_eq!(data.num, 1);
assert_eq!(data.size, 15);
Ok(())
}
#[tokio::test]
async fn test_activity_item_fields() -> Result<(), Box<BpiError>> {
let bpi = BpiClient::new();
let result = bpi.activity_list(Some("1,3"), None, None, Some(1), Some(1)).await?;
let data = result.into_data()?;
tracing::info!("{:#?}", data);
if let Some(activity) = data.list.first() {
assert!(activity.id > 0);
assert_eq!(activity.state, 1);
assert!(!activity.name.is_empty());
assert!(!activity.page_name.is_empty());
}
Ok(())
}
}