refactor: 使用 context 代替 ok_or 和 ok_or_else

This commit is contained in:
amtoaer
2025-01-21 18:06:54 +08:00
parent 0f25923c52
commit 1a32e38dc3
10 changed files with 44 additions and 53 deletions
+2 -2
View File
@@ -2,7 +2,7 @@ use std::collections::HashSet;
use std::path::Path; use std::path::Path;
use std::pin::Pin; use std::pin::Pin;
use anyhow::{anyhow, Result}; use anyhow::{Context, Result};
use async_trait::async_trait; use async_trait::async_trait;
use bili_sync_entity::*; use bili_sync_entity::*;
use futures::Stream; use futures::Stream;
@@ -196,7 +196,7 @@ pub(super) async fn collection_from<'a>(
) )
.one(connection) .one(connection)
.await? .await?
.ok_or(anyhow!("collection not found"))?, .context("collection not found")?,
), ),
Box::pin(collection.into_simple_video_stream()), Box::pin(collection.into_simple_video_stream()),
)) ))
+2 -2
View File
@@ -2,7 +2,7 @@ use std::collections::HashSet;
use std::path::Path; use std::path::Path;
use std::pin::Pin; use std::pin::Pin;
use anyhow::{anyhow, Result}; use anyhow::{Context, Result};
use async_trait::async_trait; use async_trait::async_trait;
use bili_sync_entity::*; use bili_sync_entity::*;
use futures::Stream; use futures::Stream;
@@ -153,7 +153,7 @@ pub(super) async fn favorite_from<'a>(
.filter(favorite::Column::FId.eq(favorite_info.id)) .filter(favorite::Column::FId.eq(favorite_info.id))
.one(connection) .one(connection)
.await? .await?
.ok_or(anyhow!("favorite not found"))?, .context("favorite not found")?,
), ),
Box::pin(favorite.into_video_stream()), Box::pin(favorite.into_video_stream()),
)) ))
+2 -2
View File
@@ -2,7 +2,7 @@ use std::collections::HashSet;
use std::path::Path; use std::path::Path;
use std::pin::Pin; use std::pin::Pin;
use anyhow::{anyhow, Result}; use anyhow::{Context, Result};
use async_trait::async_trait; use async_trait::async_trait;
use bili_sync_entity::*; use bili_sync_entity::*;
use futures::Stream; use futures::Stream;
@@ -169,7 +169,7 @@ pub(super) async fn submission_from<'a>(
.filter(submission::Column::UpperId.eq(upper.mid)) .filter(submission::Column::UpperId.eq(upper.mid))
.one(connection) .one(connection)
.await? .await?
.ok_or(anyhow!("submission not found"))?, .context("submission not found")?,
), ),
Box::pin(submission.into_video_stream()), Box::pin(submission.into_video_stream()),
)) ))
+2 -2
View File
@@ -2,7 +2,7 @@ use std::collections::HashSet;
use std::path::Path; use std::path::Path;
use std::pin::Pin; use std::pin::Pin;
use anyhow::{anyhow, Result}; use anyhow::{Context, Result};
use async_trait::async_trait; use async_trait::async_trait;
use bili_sync_entity::*; use bili_sync_entity::*;
use futures::Stream; use futures::Stream;
@@ -151,7 +151,7 @@ pub(super) async fn watch_later_from<'a>(
.filter(watch_later::Column::Id.eq(1)) .filter(watch_later::Column::Id.eq(1))
.one(connection) .one(connection)
.await? .await?
.ok_or(anyhow!("watch_later not found"))?, .context("watch_later not found")?,
), ),
Box::pin(watch_later.into_video_stream()), Box::pin(watch_later.into_video_stream()),
)) ))
+10 -12
View File
@@ -1,4 +1,4 @@
use anyhow::{anyhow, bail, Result}; use anyhow::{bail, Context, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::bilibili::error::BiliError; use crate::bilibili::error::BiliError;
@@ -160,7 +160,7 @@ impl PageAnalyzer {
return Ok(vec![Stream::Flv( return Ok(vec![Stream::Flv(
self.info["durl"][0]["url"] self.info["durl"][0]["url"]
.as_str() .as_str()
.ok_or(anyhow!("invalid flv stream"))? .context("invalid flv stream")?
.to_string(), .to_string(),
)]); )]);
} }
@@ -168,7 +168,7 @@ impl PageAnalyzer {
return Ok(vec![Stream::Html5Mp4( return Ok(vec![Stream::Html5Mp4(
self.info["durl"][0]["url"] self.info["durl"][0]["url"]
.as_str() .as_str()
.ok_or(anyhow!("invalid html5 mp4 stream"))? .context("invalid html5 mp4 stream")?
.to_string(), .to_string(),
)]); )]);
} }
@@ -176,7 +176,7 @@ impl PageAnalyzer {
return Ok(vec![Stream::EpositeTryMp4( return Ok(vec![Stream::EpositeTryMp4(
self.info["durl"][0]["url"] self.info["durl"][0]["url"]
.as_str() .as_str()
.ok_or(anyhow!("invalid episode try mp4 stream"))? .context("invalid episode try mp4 stream")?
.to_string(), .to_string(),
)]); )]);
} }
@@ -193,7 +193,7 @@ impl PageAnalyzer {
) else { ) else {
continue; continue;
}; };
let quality = VideoQuality::from_repr(quality as usize).ok_or(anyhow!("invalid video stream quality"))?; let quality = VideoQuality::from_repr(quality as usize).context("invalid video stream quality")?;
// 从视频流的 codecs 字段中获取编码格式,此处并非精确匹配而是判断包含,比如 codecs 是 av1.42c01e,需要匹配为 av1 // 从视频流的 codecs 字段中获取编码格式,此处并非精确匹配而是判断包含,比如 codecs 是 av1.42c01e,需要匹配为 av1
let Some(codecs) = [VideoCodecs::HEV, VideoCodecs::AVC, VideoCodecs::AV1] let Some(codecs) = [VideoCodecs::HEV, VideoCodecs::AVC, VideoCodecs::AV1]
.into_iter() .into_iter()
@@ -221,8 +221,7 @@ impl PageAnalyzer {
let (Some(url), Some(quality)) = (audio["baseUrl"].as_str(), audio["id"].as_u64()) else { let (Some(url), Some(quality)) = (audio["baseUrl"].as_str(), audio["id"].as_u64()) else {
continue; continue;
}; };
let quality = let quality = AudioQuality::from_repr(quality as usize).context("invalid audio stream quality")?;
AudioQuality::from_repr(quality as usize).ok_or(anyhow!("invalid audio stream quality"))?;
if quality < filter_option.audio_min_quality || quality > filter_option.audio_max_quality { if quality < filter_option.audio_min_quality || quality > filter_option.audio_max_quality {
continue; continue;
} }
@@ -237,7 +236,7 @@ impl PageAnalyzer {
let (Some(url), Some(quality)) = (flac["baseUrl"].as_str(), flac["id"].as_u64()) else { let (Some(url), Some(quality)) = (flac["baseUrl"].as_str(), flac["id"].as_u64()) else {
bail!("invalid flac stream"); bail!("invalid flac stream");
}; };
let quality = AudioQuality::from_repr(quality as usize).ok_or(anyhow!("invalid flac stream quality"))?; let quality = AudioQuality::from_repr(quality as usize).context("invalid flac stream quality")?;
if quality >= filter_option.audio_min_quality && quality <= filter_option.audio_max_quality { if quality >= filter_option.audio_min_quality && quality <= filter_option.audio_max_quality {
streams.push(Stream::DashAudio { streams.push(Stream::DashAudio {
url: url.to_string(), url: url.to_string(),
@@ -250,8 +249,7 @@ impl PageAnalyzer {
let (Some(url), Some(quality)) = (dolby_audio["baseUrl"].as_str(), dolby_audio["id"].as_u64()) else { let (Some(url), Some(quality)) = (dolby_audio["baseUrl"].as_str(), dolby_audio["id"].as_u64()) else {
bail!("invalid dolby audio stream"); bail!("invalid dolby audio stream");
}; };
let quality = let quality = AudioQuality::from_repr(quality as usize).context("invalid dolby audio stream quality")?;
AudioQuality::from_repr(quality as usize).ok_or(anyhow!("invalid dolby audio stream quality"))?;
if quality >= filter_option.audio_min_quality && quality <= filter_option.audio_max_quality { if quality >= filter_option.audio_min_quality && quality <= filter_option.audio_max_quality {
streams.push(Stream::DashAudio { streams.push(Stream::DashAudio {
url: url.to_string(), url: url.to_string(),
@@ -267,7 +265,7 @@ impl PageAnalyzer {
if self.is_flv_stream() || self.is_html5_mp4_stream() || self.is_episode_try_mp4_stream() { if self.is_flv_stream() || self.is_html5_mp4_stream() || self.is_episode_try_mp4_stream() {
// 按照 streams 中的假设,符合这三种情况的流只有一个,直接取 // 按照 streams 中的假设,符合这三种情况的流只有一个,直接取
return Ok(BestStream::Mixed( return Ok(BestStream::Mixed(
streams.into_iter().next().ok_or(anyhow!("no stream found"))?, streams.into_iter().next().context("no stream found")?,
)); ));
} }
let (videos, audios): (Vec<Stream>, Vec<Stream>) = let (videos, audios): (Vec<Stream>, Vec<Stream>) =
@@ -297,7 +295,7 @@ impl PageAnalyzer {
} }
_ => unreachable!(), _ => unreachable!(),
}) })
.ok_or(anyhow!("no video stream found"))?, .context("no video stream found")?,
audio: Iterator::max_by(audios.into_iter(), |a, b| match (a, b) { audio: Iterator::max_by(audios.into_iter(), |a, b| match (a, b) {
(Stream::DashAudio { quality: a_quality, .. }, Stream::DashAudio { quality: b_quality, .. }) => { (Stream::DashAudio { quality: a_quality, .. }, Stream::DashAudio { quality: b_quality, .. }) => {
a_quality.cmp(b_quality) a_quality.cmp(b_quality)
+2 -4
View File
@@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use anyhow::{bail, Result}; use anyhow::{Context, Result};
use leaky_bucket::RateLimiter; use leaky_bucket::RateLimiter;
use reqwest::{header, Method}; use reqwest::{header, Method};
@@ -109,9 +109,7 @@ impl BiliClient {
/// 获取 wbi img,用于生成请求签名 /// 获取 wbi img,用于生成请求签名
pub async fn wbi_img(&self) -> Result<WbiImg> { pub async fn wbi_img(&self) -> Result<WbiImg> {
let credential = CONFIG.credential.load(); let credential = CONFIG.credential.load();
let Some(credential) = credential.as_deref() else { let credential = credential.as_deref().context("no credential found")?;
bail!("no credential found");
};
credential.wbi_img(&self.client).await credential.wbi_img(&self.client).await
} }
} }
+8 -7
View File
@@ -1,7 +1,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashSet; use std::collections::HashSet;
use anyhow::{anyhow, bail, Result}; use anyhow::{bail, ensure, Context, Result};
use cookie::Cookie; use cookie::Cookie;
use regex::Regex; use regex::Regex;
use reqwest::{header, Method}; use reqwest::{header, Method};
@@ -74,7 +74,7 @@ impl Credential {
.json::<serde_json::Value>() .json::<serde_json::Value>()
.await? .await?
.validate()?; .validate()?;
res["data"]["refresh"].as_bool().ok_or(anyhow!("check refresh failed")) res["data"]["refresh"].as_bool().context("check refresh failed")
} }
pub async fn refresh(&self, client: &Client) -> Result<Self> { pub async fn refresh(&self, client: &Client) -> Result<Self> {
@@ -152,9 +152,10 @@ JNrRuoEUXpabUzGB8QIDAQAB
.filter_map(|x| Cookie::parse(x).ok()) .filter_map(|x| Cookie::parse(x).ok())
.filter(|x| required_cookies.contains(x.name())) .filter(|x| required_cookies.contains(x.name()))
.collect(); .collect();
if cookies.len() != required_cookies.len() { ensure!(
bail!("not all required cookies found"); cookies.len() == required_cookies.len(),
} "not all required cookies found"
);
for cookie in cookies { for cookie in cookies {
match cookie.name() { match cookie.name() {
"SESSDATA" => credential.sessdata = cookie.value().to_string(), "SESSDATA" => credential.sessdata = cookie.value().to_string(),
@@ -197,9 +198,9 @@ fn regex_find(pattern: &str, doc: &str) -> Result<String> {
let re = Regex::new(pattern)?; let re = Regex::new(pattern)?;
Ok(re Ok(re
.captures(doc) .captures(doc)
.ok_or_else(|| anyhow!("no match found"))? .context("no match found")?
.get(1) .get(1)
.ok_or_else(|| anyhow!("no capture found"))? .context("no capture found")?
.as_str() .as_str()
.to_string()) .to_string())
} }
+2 -4
View File
@@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
pub use analyzer::{BestStream, FilterOption}; pub use analyzer::{BestStream, FilterOption};
use anyhow::{bail, Result}; use anyhow::{bail, ensure, Result};
use arc_swap::ArcSwapOption; use arc_swap::ArcSwapOption;
use chrono::serde::ts_seconds; use chrono::serde::ts_seconds;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
@@ -49,9 +49,7 @@ impl Validate for serde_json::Value {
(Some(code), Some(msg)) => (code, msg), (Some(code), Some(msg)) => (code, msg),
_ => bail!("no code or message found"), _ => bail!("no code or message found"),
}; };
if code != 0 { ensure!(code == 0, BiliError::RequestFailed(code, msg.to_owned()));
bail!(BiliError::RequestFailed(code, msg.to_owned()));
}
Ok(self) Ok(self)
} }
} }
+7 -8
View File
@@ -1,4 +1,4 @@
use anyhow::{bail, Result}; use anyhow::{ensure, Result};
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
use futures::TryStreamExt; use futures::TryStreamExt;
use prost::Message; use prost::Message;
@@ -130,13 +130,12 @@ impl<'a> Video<'a> {
.error_for_status()?; .error_for_status()?;
let headers = std::mem::take(res.headers_mut()); let headers = std::mem::take(res.headers_mut());
let content_type = headers.get("content-type"); let content_type = headers.get("content-type");
if content_type.is_none_or(|v| v != "application/octet-stream") { ensure!(
bail!( content_type.is_some_and(|v| v == "application/octet-stream"),
"unexpected content type: {:?}, body: {:?}", "unexpected content type: {:?}, body: {:?}",
content_type, content_type,
res.text().await res.text().await
); );
}
Ok(DmSegMobileReply::decode(res.bytes().await?)?.elems) Ok(DmSegMobileReply::decode(res.bytes().await?)?.elems)
} }
+7 -10
View File
@@ -2,7 +2,7 @@ use std::collections::HashMap;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::pin::Pin; use std::pin::Pin;
use anyhow::{anyhow, bail, Result}; use anyhow::{bail, Context, Result};
use bili_sync_entity::*; use bili_sync_entity::*;
use futures::stream::{FuturesOrdered, FuturesUnordered}; use futures::stream::{FuturesOrdered, FuturesUnordered};
use futures::{Future, Stream, StreamExt}; use futures::{Future, Stream, StreamExt};
@@ -151,18 +151,15 @@ pub async fn download_video_pages(
upper_path: &Path, upper_path: &Path,
upper_mutex: &(Mutex<()>, Mutex<()>), upper_mutex: &(Mutex<()>, Mutex<()>),
) -> Result<video::ActiveModel> { ) -> Result<video::ActiveModel> {
let permit = semaphore.acquire().await; let _permit = semaphore.acquire().await.context("acquire semaphore failed")?;
if let Err(e) = permit {
bail!(e);
}
let mut status = VideoStatus::new(video_model.download_status); let mut status = VideoStatus::new(video_model.download_status);
let seprate_status = status.should_run(); let seprate_status = status.should_run();
let base_path = Path::new(&video_model.path); let base_path = Path::new(&video_model.path);
let upper_id = video_model.upper_id.to_string(); let upper_id = video_model.upper_id.to_string();
let base_upper_path = upper_path let base_upper_path = upper_path
.join(upper_id.chars().next().ok_or(anyhow!("upper_id is empty"))?.to_string()) .join(upper_id.chars().next().context("upper_id is empty")?.to_string())
.join(upper_id); .join(upper_id);
let is_single_page = video_model.single_page.ok_or(anyhow!("single_page is null"))?; let is_single_page = video_model.single_page.context("single_page is null")?;
// 对于单页视频,page 的下载已经足够 // 对于单页视频,page 的下载已经足够
// 对于多页视频,page 下载仅包含了分集内容,需要额外补上视频的 poster 的 tvshow.nfo // 对于多页视频,page 下载仅包含了分集内容,需要额外补上视频的 poster 的 tvshow.nfo
let tasks: Vec<Pin<Box<dyn Future<Output = Result<()>>>>> = vec![ let tasks: Vec<Pin<Box<dyn Future<Output = Result<()>>>>> = vec![
@@ -308,7 +305,7 @@ pub async fn download_page(
} }
let mut status = PageStatus::new(page_model.download_status); let mut status = PageStatus::new(page_model.download_status);
let seprate_status = status.should_run(); let seprate_status = status.should_run();
let is_single_page = video_model.single_page.ok_or(anyhow!("single_page is null"))?; let is_single_page = video_model.single_page.context("single_page is null")?;
let base_path = Path::new(&video_model.path); let base_path = Path::new(&video_model.path);
let base_name = TEMPLATE.path_safe_render( let base_name = TEMPLATE.path_safe_render(
"page", "page",
@@ -428,7 +425,7 @@ pub async fn fetch_page_poster(
if !should_run { if !should_run {
return Ok(()); return Ok(());
} }
let single_page = video_model.single_page.ok_or(anyhow!("single_page is null"))?; let single_page = video_model.single_page.context("single_page is null")?;
let url = if single_page { let url = if single_page {
// 单页视频直接用视频的封面 // 单页视频直接用视频的封面
video_model.cover.as_str() video_model.cover.as_str()
@@ -516,7 +513,7 @@ pub async fn generate_page_nfo(
if !should_run { if !should_run {
return Ok(()); return Ok(());
} }
let single_page = video_model.single_page.ok_or(anyhow!("single_page is null"))?; let single_page = video_model.single_page.context("single_page is null")?;
let nfo_serializer = if single_page { let nfo_serializer = if single_page {
NFOSerializer(ModelWrapper::Video(video_model), NFOMode::MOVIE) NFOSerializer(ModelWrapper::Video(video_model), NFOMode::MOVIE)
} else { } else {