From db62f5527acb94c10db8c11afaae269df0a90cd8 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: Sat, 27 Apr 2024 00:45:09 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=B8=BA=20serde=5Fjson::Value=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20trait=EF=BC=8C=E9=81=BF=E5=85=8D=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E4=BB=A3=E7=A0=81=20(#82)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bilibili/credential.rs | 34 +++++++--------------------------- src/bilibili/favorite_list.rs | 29 +++++++---------------------- src/bilibili/mod.rs | 22 ++++++++++++++++++++++ src/bilibili/video.rs | 32 +++++++------------------------- 4 files changed, 43 insertions(+), 74 deletions(-) diff --git a/src/bilibili/credential.rs b/src/bilibili/credential.rs index c0725ec..b6ad0de 100644 --- a/src/bilibili/credential.rs +++ b/src/bilibili/credential.rs @@ -9,8 +9,7 @@ use rsa::sha2::Sha256; use rsa::{Oaep, RsaPublicKey}; use serde::{Deserialize, Serialize}; -use crate::bilibili::error::BiliError; -use crate::bilibili::Client; +use crate::bilibili::{Client, Validate}; #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct Credential { @@ -34,14 +33,8 @@ impl Credential { .await? .error_for_status()? .json::() - .await?; - let (code, msg) = match (res["code"].as_i64(), res["message"].as_str()) { - (Some(code), Some(msg)) => (code, msg), - _ => bail!("no code or message found"), - }; - if code != 0 { - bail!(BiliError::RequestFailed(code, msg.to_owned())); - } + .await? + .validate()?; res["data"]["refresh"].as_bool().ok_or(anyhow!("check refresh failed")) } @@ -105,14 +98,7 @@ JNrRuoEUXpabUzGB8QIDAQAB .error_for_status()?; // 必须在 .json 前取出 headers,否则 res 会被消耗 let headers = std::mem::take(res.headers_mut()); - let res = res.json::().await?; - let (code, msg) = match (res["code"].as_i64(), res["message"].as_str()) { - (Some(code), Some(msg)) => (code, msg), - _ => bail!("no code or message found"), - }; - if code != 0 { - bail!(BiliError::RequestFailed(code, msg.to_owned())); - } + let res = res.json::().await?.validate()?; let set_cookies = headers.get_all(header::SET_COOKIE); let mut credential = Self { buvid3: self.buvid3.clone(), @@ -144,7 +130,7 @@ JNrRuoEUXpabUzGB8QIDAQAB } async fn confirm_refresh(&self, client: &Client, new_credential: &Credential) -> Result<()> { - let res = client + client .request( Method::POST, "https://passport.bilibili.com/x/passport-login/web/confirm/refresh", @@ -159,14 +145,8 @@ JNrRuoEUXpabUzGB8QIDAQAB .await? .error_for_status()? .json::() - .await?; - let (code, msg) = match (res["code"].as_i64(), res["message"].as_str()) { - (Some(code), Some(msg)) => (code, msg), - _ => bail!("no code or message found"), - }; - if code != 0 { - bail!(BiliError::RequestFailed(code, msg.to_owned())); - } + .await? + .validate()?; Ok(()) } } diff --git a/src/bilibili/favorite_list.rs b/src/bilibili/favorite_list.rs index 7fa907a..55e9c33 100644 --- a/src/bilibili/favorite_list.rs +++ b/src/bilibili/favorite_list.rs @@ -1,12 +1,11 @@ -use anyhow::{bail, Result}; +use anyhow::Result; use async_stream::stream; use chrono::serde::ts_seconds; use chrono::{DateTime, Utc}; use futures::Stream; use serde_json::Value; -use crate::bilibili::error::BiliError; -use crate::bilibili::BiliClient; +use crate::bilibili::{BiliClient, Validate}; pub struct FavoriteList<'a> { client: &'a BiliClient, fid: String, @@ -56,20 +55,13 @@ impl<'a> FavoriteList<'a> { .await? .error_for_status()? .json::() - .await?; - let (code, msg) = match (res["code"].as_i64(), res["message"].as_str()) { - (Some(code), Some(msg)) => (code, msg), - _ => bail!("no code or message found"), - }; - if code != 0 { - bail!(BiliError::RequestFailed(code, msg.to_owned())); - } + .await? + .validate()?; Ok(serde_json::from_value(res["data"].take())?) } async fn get_videos(&self, page: u32) -> Result { - let res = self - .client + self.client .request(reqwest::Method::GET, "https://api.bilibili.com/x/v3/fav/resource/list") .query(&[ ("media_id", self.fid.as_str()), @@ -83,15 +75,8 @@ impl<'a> FavoriteList<'a> { .await? .error_for_status()? .json::() - .await?; - let (code, msg) = match (res["code"].as_i64(), res["message"].as_str()) { - (Some(code), Some(msg)) => (code, msg), - _ => bail!("no code or message found"), - }; - if code != 0 { - bail!(BiliError::RequestFailed(code, msg.to_owned())); - } - Ok(res) + .await? + .validate() } // 拿到收藏夹的所有权,返回一个收藏夹下的视频流 diff --git a/src/bilibili/mod.rs b/src/bilibili/mod.rs index 5c78aa7..12d771c 100644 --- a/src/bilibili/mod.rs +++ b/src/bilibili/mod.rs @@ -1,4 +1,5 @@ pub use analyzer::{BestStream, FilterOption}; +use anyhow::{bail, Result}; pub use client::{BiliClient, Client}; pub use credential::Credential; pub use danmaku::DanmakuOption; @@ -13,3 +14,24 @@ mod danmaku; mod error; mod favorite_list; mod video; + +pub(crate) trait Validate { + type Output; + + fn validate(self) -> Result; +} + +impl Validate for serde_json::Value { + type Output = serde_json::Value; + + fn validate(self) -> Result { + let (code, msg) = match (self["code"].as_i64(), self["message"].as_str()) { + (Some(code), Some(msg)) => (code, msg), + _ => bail!("no code or message found"), + }; + if code != 0 { + bail!(BiliError::RequestFailed(code, msg.to_owned())); + } + Ok(self) + } +} diff --git a/src/bilibili/video.rs b/src/bilibili/video.rs index 94972ef..9110704 100644 --- a/src/bilibili/video.rs +++ b/src/bilibili/video.rs @@ -7,7 +7,7 @@ use reqwest::Method; use crate::bilibili::analyzer::PageAnalyzer; use crate::bilibili::client::BiliClient; use crate::bilibili::danmaku::{DanmakuElem, DanmakuWriter, DmSegMobileReply}; -use crate::bilibili::error::BiliError; +use crate::bilibili::Validate; static MASK_CODE: u64 = 2251799813685247; static XOR_CODE: u64 = 23442827791579; @@ -70,14 +70,8 @@ impl<'a> Video<'a> { .await? .error_for_status()? .json::() - .await?; - let (code, msg) = match (res["code"].as_i64(), res["message"].as_str()) { - (Some(code), Some(msg)) => (code, msg), - _ => bail!("no code or message found"), - }; - if code != 0 { - bail!(BiliError::RequestFailed(code, msg.to_owned())); - } + .await? + .validate()?; Ok(serde_json::from_value(res["data"].take())?) } @@ -90,14 +84,8 @@ impl<'a> Video<'a> { .await? .error_for_status()? .json::() - .await?; - let (code, msg) = match (res["code"].as_i64(), res["message"].as_str()) { - (Some(code), Some(msg)) => (code, msg), - _ => bail!("no code or message found"), - }; - if code != 0 { - bail!(BiliError::RequestFailed(code, msg.to_owned())); - } + .await? + .validate()?; Ok(serde_json::from_value(res["data"].take())?) } @@ -148,14 +136,8 @@ impl<'a> Video<'a> { .await? .error_for_status()? .json::() - .await?; - let (code, msg) = match (res["code"].as_i64(), res["message"].as_str()) { - (Some(code), Some(msg)) => (code, msg), - _ => bail!("no code or message found"), - }; - if code != 0 { - bail!(BiliError::RequestFailed(code, msg.to_owned())); - } + .await? + .validate()?; Ok(PageAnalyzer::new(res["data"].take())) } }