use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
use serde::{ Deserialize, Serialize };
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct FavFolderUpper {
pub mid: u64,
pub name: String,
pub face: String,
pub followed: bool,
pub vip_type: u8,
#[serde(rename = "vip_statue")]
pub vip_status: u8,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct FavFolderCntInfo {
pub collect: u64,
pub play: u64,
pub thumb_up: u64,
pub share: u64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct FavFolderInfo {
pub id: u64,
pub fid: u64,
pub mid: u64,
pub attr: u32,
pub title: String,
pub cover: String,
pub upper: FavFolderUpper,
pub cover_type: u8,
pub cnt_info: FavFolderCntInfo,
#[serde(rename = "type")]
pub type_name: u32,
pub intro: String,
pub ctime: u64,
pub mtime: u64,
pub state: u8,
pub fav_state: u8,
pub like_state: u8,
pub media_count: u32,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CreatedFolderItem {
pub id: u64,
pub fid: u64,
pub mid: u64,
pub attr: u32,
pub title: String,
pub fav_state: u8,
pub media_count: u32,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CreatedFolderListData {
pub count: u32,
pub list: Vec<CreatedFolderItem>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CollectedFolderUpper {
pub mid: u64,
pub name: String,
pub face: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CollectedFolderItem {
pub id: u64,
pub fid: u64,
pub mid: u64,
pub attr: u32,
pub title: String,
pub cover: String,
pub upper: CollectedFolderUpper,
pub cover_type: u8,
pub intro: String,
pub ctime: u64,
pub mtime: u64,
pub state: u8,
pub fav_state: u8,
pub media_count: u32,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CollectedFolderListData {
pub count: u32,
pub list: Vec<CollectedFolderItem>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ResourceInfoUpper {
pub mid: u64,
pub name: String,
pub face: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ResourceInfoCntInfo {
pub collect: u64,
pub play: u64,
pub danmaku: u64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ResourceInfoItem {
pub id: u64,
#[serde(rename = "type")]
pub type_name: u8,
pub title: String,
pub cover: String,
pub intro: String,
pub page: Option<u32>,
pub duration: u32,
pub upper: ResourceInfoUpper,
pub attr: u8,
pub cnt_info: ResourceInfoCntInfo,
pub link: String,
pub ctime: u64,
pub pubtime: u64,
pub fav_time: u64,
pub bv_id: Option<String>,
pub bvid: Option<String>,
pub season: Option<serde_json::Value>,
}
impl BpiClient {
pub async fn fav_folder_info(
&self,
media_id: u64
) -> Result<BpiResponse<FavFolderInfo>, BpiError> {
self
.get("https://api.bilibili.com/x/v3/fav/folder/info")
.query(&[("media_id", media_id)])
.send_bpi("获取收藏夹元数据").await
}
pub async fn fav_created_list(
&self,
up_mid: u64,
typ: Option<u8>,
rid: Option<u64>
) -> Result<BpiResponse<CreatedFolderListData>, BpiError> {
let mut request = self
.get("https://api.bilibili.com/x/v3/fav/folder/created/list-all")
.query(&[("up_mid", up_mid.to_string())]);
if let Some(t) = typ {
request = request.query(&[("type", t)]);
}
if let Some(r) = rid {
request = request.query(&[("rid", r)]);
}
request
.query(&[("web_location", "333.1387")])
.send_bpi("获取指定用户创建的所有收藏夹信息").await
}
pub async fn fav_collected_list(
&self,
up_mid: u64,
pn: u32,
ps: u32
) -> Result<BpiResponse<CollectedFolderListData>, BpiError> {
self
.get("https://api.bilibili.com/x/v3/fav/folder/collected/list")
.query(
&[
("up_mid", up_mid.to_string()),
("pn", pn.to_string()),
("ps", ps.to_string()),
("platform", "web".to_string()),
]
)
.send_bpi("查询用户收藏的视频收藏夹").await
}
pub async fn fav_resource_infos(
&self,
resources: &str
) -> Result<BpiResponse<Vec<ResourceInfoItem>>, BpiError> {
self
.get("https://api.bilibili.com/x/v3/fav/resource/infos")
.query(
&[
("resources", resources),
("platform", "web"),
]
)
.send_bpi("批量获取指定收藏id的内容").await
}
}
#[cfg(test)]
mod tests {
use super::*;
use tracing::info;
#[tokio::test]
async fn test_get_fav_folder_info() {
let bpi = BpiClient::new();
let media_id = 3717139570;
let resp = bpi.fav_folder_info(media_id).await;
info!("{:?}", resp);
assert!(resp.is_ok());
let resp_data = resp.unwrap();
info!("code: {}", resp_data.code);
if let Some(data) = resp_data.data {
info!("folder title: {}", data.title);
info!("folder media_count: {}", data.media_count);
info!("upper info: {:?}", data.upper);
}
}
#[tokio::test]
async fn test_get_fav_created_list() {
let bpi = BpiClient::new();
let up_mid = 4279370;
let resp = bpi.fav_created_list(up_mid, None, None).await;
info!("{:?}", resp);
assert!(resp.is_ok());
let resp_data = resp.unwrap();
info!("code: {}", resp_data.code);
if let Some(data) = resp_data.data {
info!("created folders count: {}", data.count);
info!("first folder info: {:?}", data.list.first());
}
}
#[tokio::test]
async fn test_get_fav_collected_list() {
let bpi = BpiClient::new();
let up_mid = 4279370;
let resp = bpi.fav_collected_list(up_mid, 1, 20).await;
info!("{:?}", resp);
assert!(resp.is_ok());
let resp_data = resp.unwrap();
info!("code: {}", resp_data.code);
if let Some(data) = resp_data.data {
info!("collected folders count: {}", data.count);
info!("first collected folder info: {:?}", data.list.first());
}
}
#[tokio::test]
async fn test_get_fav_resource_infos() {
let bpi = BpiClient::new();
let resources = "115087859779103:2";
let resp = bpi.fav_resource_infos(resources).await;
info!("{:?}", resp);
assert!(resp.is_ok());
let resp_data = resp.unwrap();
info!("code: {}", resp_data.code);
if let Some(data) = resp_data.data {
info!("retrieved {} resources", data.len());
info!("first resource info: {:?}", data.first());
}
}
}