From 8510aa318ec70ebd873e5ea1f0539479e7389cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=80=E1=B4=8D=E1=B4=9B=E1=B4=8F=E1=B4=80=E1=B4=87?= =?UTF-8?q?=CA=80?= Date: Mon, 2 Jun 2025 00:15:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=88=91=E7=9A=84=E6=94=B6=E8=97=8F=E5=A4=B9=E3=80=81=E6=94=B6?= =?UTF-8?q?=E8=97=8F=E7=9A=84=E8=A7=86=E9=A2=91=E5=90=88=E9=9B=86=E4=B8=8E?= =?UTF-8?q?=E5=85=B3=E6=B3=A8=E7=9A=84=20up=20=E4=B8=BB=20(#349)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/bili_sync/src/bilibili/me.rs | 119 ++++++++++++++++++++++++++ crates/bili_sync/src/bilibili/mod.rs | 3 +- crates/bili_sync/src/config/global.rs | 39 +-------- crates/bili_sync/src/config/mod.rs | 16 ++-- crates/bili_sync/src/utils/nfo.rs | 1 + 5 files changed, 135 insertions(+), 43 deletions(-) create mode 100644 crates/bili_sync/src/bilibili/me.rs diff --git a/crates/bili_sync/src/bilibili/me.rs b/crates/bili_sync/src/bilibili/me.rs new file mode 100644 index 0000000..852956e --- /dev/null +++ b/crates/bili_sync/src/bilibili/me.rs @@ -0,0 +1,119 @@ +#![allow(unused)] + +use anyhow::Result; +use reqwest::Method; + +use crate::bilibili::{BiliClient, Validate}; +use crate::config::CONFIG; +pub struct Me<'a> { + client: &'a BiliClient, + mid: String, +} + +impl<'a> Me<'a> { + pub fn new(client: &'a BiliClient) -> Self { + Self { + client, + mid: Self::my_id(), + } + } + + pub async fn get_created_favorites(&self) -> Result>> { + let mut resp = self + .client + .request(Method::GET, "https://api.bilibili.com/x/v3/fav/folder/created/list-all") + .await + .query(&[("up_mid", &self.mid)]) + .send() + .await? + .error_for_status()? + .json::() + .await? + .validate()?; + Ok(serde_json::from_value(resp["data"]["list"].take())?) + } + + pub async fn get_followed_collections(&self, page: i32) -> Result { + let mut resp = self + .client + .request(Method::GET, "https://api.bilibili.com/x/v3/fav/folder/collected/list") + .await + .query(&[ + ("up_mid", self.mid.as_ref()), + ("pn", page.to_string().as_ref()), + ("ps", "20"), + ("platform", "web"), + ]) + .send() + .await? + .error_for_status()? + .json::() + .await? + .validate()?; + Ok(serde_json::from_value(resp["data"].take())?) + } + + pub async fn get_followed_uppers(&self, page: i32) -> Result { + let mut resp = self + .client + .request(Method::GET, "https://api.bilibili.com/x/relation/followings") + .await + .query(&[ + ("vmid", self.mid.as_ref()), + ("pn", page.to_string().as_ref()), + ("ps", "20"), + ]) + .send() + .await? + .error_for_status()? + .json::() + .await? + .validate()?; + Ok(serde_json::from_value(resp["data"].take())?) + } + + fn my_id() -> String { + CONFIG + .credential + .load() + .as_deref() + .map(|c| c.dedeuserid.clone()) + .unwrap() + } +} + +#[derive(Debug, serde::Deserialize)] +pub struct FavoriteItem { + pub title: String, + pub media_count: i64, + pub fid: i64, + pub mid: i64, +} + +#[derive(Debug, serde::Deserialize)] +pub struct CollectionItem { + pub id: i64, + pub mid: i64, + pub state: i32, + pub title: String, +} + +#[derive(Debug, serde::Deserialize)] +pub struct Collections { + pub count: i64, + pub list: Option>, +} + +#[derive(Debug, serde::Deserialize)] +pub struct FollowedUppers { + pub total: i64, + pub list: Vec, +} + +#[derive(Debug, serde::Deserialize)] +pub struct FollowedUpper { + pub mid: i64, + pub uname: String, + pub face: String, + pub sign: String, +} diff --git a/crates/bili_sync/src/bilibili/mod.rs b/crates/bili_sync/src/bilibili/mod.rs index 306a8b7..eb9cf5c 100644 --- a/crates/bili_sync/src/bilibili/mod.rs +++ b/crates/bili_sync/src/bilibili/mod.rs @@ -1,7 +1,5 @@ use std::sync::Arc; -#[cfg(test)] -pub use analyzer::VideoCodecs; pub use analyzer::{BestStream, FilterOption}; use anyhow::{Result, bail, ensure}; use arc_swap::ArcSwapOption; @@ -26,6 +24,7 @@ mod credential; mod danmaku; mod error; mod favorite_list; +mod me; mod submission; mod subtitle; mod video; diff --git a/crates/bili_sync/src/config/global.rs b/crates/bili_sync/src/config/global.rs index 8679630..cbb287b 100644 --- a/crates/bili_sync/src/config/global.rs +++ b/crates/bili_sync/src/config/global.rs @@ -38,10 +38,12 @@ pub static ARGS: Lazy = Lazy::new(Args::parse); pub static CONFIG_DIR: Lazy = Lazy::new(|| dirs::config_dir().expect("No config path found").join("bili-sync")); -#[cfg(not(test))] fn load_config() -> Config { + if cfg!(test) { + return Config::load(&CONFIG_DIR.join("test_config.toml")).unwrap_or(Config::test_default()); + } info!("开始加载配置文件.."); - let config = Config::load().unwrap_or_else(|err| { + let config = Config::load(&CONFIG_DIR.join("config.toml")).unwrap_or_else(|err| { if err .downcast_ref::() .is_none_or(|e| e.kind() != std::io::ErrorKind::NotFound) @@ -58,36 +60,3 @@ fn load_config() -> Config { info!("配置文件检查通过"); config } - -#[cfg(test)] -fn load_config() -> Config { - use crate::bilibili::{FilterOption, VideoCodecs}; - - let credential = match ( - std::env::var("TEST_SESSDATA"), - std::env::var("TEST_BILI_JCT"), - std::env::var("TEST_BUVID3"), - std::env::var("TEST_DEDEUSERID"), - std::env::var("TEST_AC_TIME_VALUE"), - ) { - (Ok(sessdata), Ok(bili_jct), Ok(buvid3), Ok(dedeuserid), Ok(ac_time_value)) => { - Some(std::sync::Arc::new(crate::bilibili::Credential { - sessdata, - bili_jct, - buvid3, - dedeuserid, - ac_time_value, - })) - } - _ => None, - }; - Config { - credential: arc_swap::ArcSwapOption::from(credential), - cdn_sorting: true, - filter_option: FilterOption { - codecs: vec![VideoCodecs::HEV, VideoCodecs::AV1, VideoCodecs::AVC], - ..Default::default() - }, - ..Default::default() - } -} diff --git a/crates/bili_sync/src/config/mod.rs b/crates/bili_sync/src/config/mod.rs index 60d7956..6cb0ea0 100644 --- a/crates/bili_sync/src/config/mod.rs +++ b/crates/bili_sync/src/config/mod.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; use std::collections::HashMap; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::Arc; use anyhow::Result; @@ -105,10 +105,8 @@ impl Config { Ok(()) } - #[cfg(not(test))] - fn load() -> Result { - let config_path = CONFIG_DIR.join("config.toml"); - let config_content = std::fs::read_to_string(config_path)?; + fn load(path: &Path) -> Result { + let config_content = std::fs::read_to_string(path)?; Ok(toml::from_str(&config_content)?) } @@ -129,7 +127,6 @@ impl Config { params } - #[cfg(not(test))] pub fn check(&self) { let mut ok = true; let video_sources = self.as_video_sources(); @@ -184,4 +181,11 @@ impl Config { ); } } + + pub(super) fn test_default() -> Self { + Self { + cdn_sorting: true, + ..Default::default() + } + } } diff --git a/crates/bili_sync/src/utils/nfo.rs b/crates/bili_sync/src/utils/nfo.rs index 8e1191f..58b38e1 100644 --- a/crates/bili_sync/src/utils/nfo.rs +++ b/crates/bili_sync/src/utils/nfo.rs @@ -8,6 +8,7 @@ use tokio::io::{AsyncWriteExt, BufWriter}; use crate::config::{CONFIG, NFOTimeType}; +#[allow(clippy::upper_case_acronyms)] pub enum NFO<'a> { Movie(Movie<'a>), TVShow(TVShow<'a>),