refactor: 为 serde_json::Value 实现 trait,避免重复代码 (#82)

This commit is contained in:
ᴀᴍᴛᴏᴀᴇʀ
2024-04-27 00:45:09 +08:00
committed by GitHub
parent 0958893574
commit db62f5527a
4 changed files with 43 additions and 74 deletions

View File

@@ -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::<serde_json::Value>()
.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::<serde_json::Value>().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::<serde_json::Value>().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::<serde_json::Value>()
.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(())
}
}

View File

@@ -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::<serde_json::Value>()
.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<Value> {
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::<serde_json::Value>()
.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()
}
// 拿到收藏夹的所有权,返回一个收藏夹下的视频流

View File

@@ -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<Self::Output>;
}
impl Validate for serde_json::Value {
type Output = serde_json::Value;
fn validate(self) -> Result<Self::Output> {
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)
}
}

View File

@@ -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::<serde_json::Value>()
.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::<serde_json::Value>()
.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::<serde_json::Value>()
.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()))
}
}