use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
use serde::{ Deserialize, Serialize };
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct OfficialVerify {
#[serde(rename = "type")]
pub verify_type: i8,
pub desc: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct VipLabel {
pub path: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct VipInfo {
#[serde(rename = "vipType")]
pub vip_type: u8,
#[serde(rename = "vipDueDate")]
pub vip_due_date: u64,
#[serde(rename = "dueRemark")]
pub due_remark: String,
#[serde(rename = "accessStatus")]
pub access_status: u8,
#[serde(rename = "vipStatus")]
pub vip_status: u8,
#[serde(rename = "vipStatusWarn")]
pub vip_status_warn: String,
#[serde(rename = "themeType")]
pub theme_type: u8,
pub label: VipLabel,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RelationListItem {
pub mid: u64,
pub attribute: u8,
pub mtime: u64,
pub tag: Option<Vec<u64>>,
pub special: u8,
pub contract_info: Option<serde_json::Value>,
pub uname: String,
pub face: String,
pub sign: String,
pub face_nft: u8,
pub official_verify: OfficialVerify,
pub vip: VipInfo,
#[serde(rename = "name_render")]
pub name_render: Option<serde_json::Value>,
#[serde(rename = "nft_icon")]
pub nft_icon: Option<String>,
pub rec_reason: Option<String>,
#[serde(rename = "track_id")]
pub track_id: Option<String>,
#[serde(rename = "follow_time")]
pub follow_time: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct FollowingListResponseData {
pub list: Vec<RelationListItem>,
pub re_version: u32,
pub total: u64,
}
impl BpiClient {
pub async fn user_followings(
&self,
vmid: u64,
order_type: Option<&str>,
ps: Option<u32>,
pn: Option<u32>
) -> Result<BpiResponse<FollowingListResponseData>, BpiError> {
let mut req = self
.get("https://api.bilibili.com/x/relation/followings")
.with_bilibili_headers()
.query(&[("vmid", &vmid.to_string())]);
if let Some(o) = order_type {
req = req.query(&[("order_type", o)]);
}
if let Some(p) = ps {
req = req.query(&[("ps", &p.to_string())]);
}
if let Some(p) = pn {
req = req.query(&[("pn", &p.to_string())]);
}
req.send_bpi("查询用户关注明细").await
}
}
#[cfg(test)]
mod tests {
use super::*;
use tracing::info;
const TEST_VMID: u64 = 293793435;
#[tokio::test]
async fn test_user_followings() -> Result<(), BpiError> {
let bpi = BpiClient::new();
let resp = bpi.user_followings(TEST_VMID, None, Some(50), Some(1)).await?;
let data = resp.into_data()?;
info!("用户关注明细: {:?}", data);
assert!(!data.list.is_empty());
assert_eq!(data.list.len(), 50);
Ok(())
}
}