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(
111 &self,
112 vmid: u64,
113 order_type: Option<&str>,
114 ps: Option<u32>,
115 pn: Option<u32>,
116 ) -> Result<BpiResponse<FollowingListResponseData>, BpiError> {
117 let mut req = self
118 .get("https://api.bilibili.com/x/relation/followings")
119 .with_bilibili_headers()
120 .query(&[("vmid", &vmid.to_string())]);
121
122 if let Some(o) = order_type {
123 req = req.query(&[("order_type", o)]);
124 }
125 if let Some(p) = ps {
126 req = req.query(&[("ps", &p.to_string())]);
127 }
128 if let Some(p) = pn {
129 req = req.query(&[("pn", &p.to_string())]);
130 }
131
132 req.send_bpi("查询用户关注明细").await
133 }
134}
135
136#[cfg(test)]
139mod tests {
140 use super::*;
141 use tracing::info;
142
143 const TEST_VMID: u64 = 293793435;
144
145 #[tokio::test]
146
147 async fn test_user_followings() -> Result<(), BpiError> {
148 let bpi = BpiClient::new();
149 let resp = bpi
150 .user_followings(TEST_VMID, None, Some(50), Some(1))
151 .await?;
152 let data = resp.into_data()?;
153
154 info!("用户关注明细: {:?}", data);
155 assert!(!data.list.is_empty());
156 assert_eq!(data.list.len(), 50);
157
158 Ok(())
159 }
160}