bpi_rs/user/relation/
following.rs1use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
5use serde::{ Deserialize, Serialize };
6
7#[derive(Debug, Clone, Deserialize, Serialize)]
11pub struct OfficialVerify {
12 #[serde(rename = "type")]
14 pub verify_type: i8,
15 pub desc: String,
17}
18
19#[derive(Debug, Clone, Deserialize, Serialize)]
21pub struct VipLabel {
22 pub path: String,
23}
24
25#[derive(Debug, Clone, Deserialize, Serialize)]
27pub struct VipInfo {
28 #[serde(rename = "vipType")]
30 pub vip_type: u8,
31 #[serde(rename = "vipDueDate")]
33 pub vip_due_date: u64,
34 #[serde(rename = "dueRemark")]
35 pub due_remark: String,
36 #[serde(rename = "accessStatus")]
37 pub access_status: u8,
38 #[serde(rename = "vipStatus")]
40 pub vip_status: u8,
41 #[serde(rename = "vipStatusWarn")]
42 pub vip_status_warn: String,
43 #[serde(rename = "themeType")]
44 pub theme_type: u8,
45 pub label: VipLabel,
46}
47
48#[derive(Debug, Clone, Deserialize, Serialize)]
50pub struct RelationListItem {
51 pub mid: u64,
53 pub attribute: u8,
55 pub mtime: u64,
57 pub tag: Option<Vec<u64>>,
59 pub special: u8,
61 pub contract_info: Option<serde_json::Value>,
62 pub uname: String,
64 pub face: String,
66 pub sign: String,
68 pub face_nft: u8,
70 pub official_verify: OfficialVerify,
72 pub vip: VipInfo,
74 #[serde(rename = "name_render")]
75 pub name_render: Option<serde_json::Value>,
76 #[serde(rename = "nft_icon")]
77 pub nft_icon: Option<String>,
78 pub rec_reason: Option<String>,
80 #[serde(rename = "track_id")]
81 pub track_id: Option<String>,
82 #[serde(rename = "follow_time")]
83 pub follow_time: Option<String>,
84}
85
86#[derive(Debug, Clone, Deserialize, Serialize)]
88pub struct FollowingListResponseData {
89 pub list: Vec<RelationListItem>,
91 pub re_version: u32,
92 pub total: u64,
94}
95
96impl BpiClient {
99 pub async fn user_followings(
112 &self,
113 vmid: u64,
114 order_type: Option<&str>,
115 ps: Option<u32>,
116 pn: Option<u32>
117 ) -> Result<BpiResponse<FollowingListResponseData>, BpiError> {
118 let mut req = self
119 .get("https://api.bilibili.com/x/relation/followings")
120 .with_bilibili_headers()
121 .query(&[("vmid", &vmid.to_string())]);
122
123 if let Some(o) = order_type {
124 req = req.query(&[("order_type", o)]);
125 }
126 if let Some(p) = ps {
127 req = req.query(&[("ps", &p.to_string())]);
128 }
129 if let Some(p) = pn {
130 req = req.query(&[("pn", &p.to_string())]);
131 }
132
133 req.send_bpi("查询用户关注明细").await
134 }
135}
136
137#[cfg(test)]
140mod tests {
141 use super::*;
142 use tracing::info;
143
144 const TEST_VMID: u64 = 293793435;
145
146 #[tokio::test]
147 async fn test_user_followings() -> Result<(), BpiError> {
148 let bpi = BpiClient::new();
149 let resp = bpi.user_followings(TEST_VMID, None, Some(50), Some(1)).await?;
150 let data = resp.into_data()?;
151
152 info!("用户关注明细: {:?}", data);
153 assert!(!data.list.is_empty());
154 assert_eq!(data.list.len(), 50);
155
156 Ok(())
157 }
158}