refactor: 为 serde_json::Value 实现 trait,避免重复代码 (#82)
This commit is contained in:
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
// 拿到收藏夹的所有权,返回一个收藏夹下的视频流
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user