chore: 全盘使用 anyhow::Result

This commit is contained in:
amtoaer
2024-04-01 21:53:11 +08:00
parent 45708e91e8
commit d72551254f
12 changed files with 33 additions and 37 deletions
+4 -5
View File
@@ -1,10 +1,9 @@
use std::sync::Arc; use std::sync::Arc;
use anyhow::{anyhow, bail, Result};
use log::error; use log::error;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::Result;
pub struct PageAnalyzer { pub struct PageAnalyzer {
info: serde_json::Value, info: serde_json::Value,
} }
@@ -161,14 +160,14 @@ impl PageAnalyzer {
.as_array() .as_array()
.ok_or_else(|| -> Result<serde_json::Value> { .ok_or_else(|| -> Result<serde_json::Value> {
error!("video data is not an array: {:?}", self.info); error!("video data is not an array: {:?}", self.info);
Err("invalid video data".into()) Err(anyhow!("invalid video data"))
}) })
.unwrap_or(&Vec::new()) .unwrap_or(&Vec::new())
.iter() .iter()
{ {
let video_stream_url = video_data["baseUrl"].as_str().unwrap().to_string(); let video_stream_url = video_data["baseUrl"].as_str().unwrap().to_string();
let video_stream_quality = VideoQuality::from_repr(video_data["id"].as_u64().unwrap() as usize) let video_stream_quality = VideoQuality::from_repr(video_data["id"].as_u64().unwrap() as usize)
.ok_or("invalid video stream quality")?; .ok_or(anyhow!("invalid video stream quality"))?;
if (video_stream_quality == VideoQuality::QualityHdr && filter_option.no_hdr) if (video_stream_quality == VideoQuality::QualityHdr && filter_option.no_hdr)
|| (video_stream_quality == VideoQuality::QualityDolby && filter_option.no_dolby_video) || (video_stream_quality == VideoQuality::QualityDolby && filter_option.no_dolby_video)
|| (video_stream_quality != VideoQuality::QualityDolby || (video_stream_quality != VideoQuality::QualityDolby
@@ -306,7 +305,7 @@ impl PageAnalyzer {
_ => unreachable!(), _ => unreachable!(),
}); });
if video_streams.is_empty() { if video_streams.is_empty() {
return Err("no stream found".into()); bail!("no video stream found");
} }
Ok(BestStream::VideoAudio { Ok(BestStream::VideoAudio {
video: video_streams.remove(video_streams.len() - 1), video: video_streams.remove(video_streams.len() - 1),
+1 -1
View File
@@ -1,8 +1,8 @@
use anyhow::Result;
use reqwest::{header, Method}; use reqwest::{header, Method};
use crate::bilibili::Credential; use crate::bilibili::Credential;
use crate::config::CONFIG; use crate::config::CONFIG;
use crate::Result;
// 一个对 reqwest::Client 的简单封装,用于 Bilibili 请求 // 一个对 reqwest::Client 的简单封装,用于 Bilibili 请求
pub struct Client(reqwest::Client); pub struct Client(reqwest::Client);
+8 -8
View File
@@ -1,5 +1,6 @@
use std::collections::HashSet; use std::collections::HashSet;
use anyhow::{anyhow, bail, Result};
use cookie::Cookie; use cookie::Cookie;
use regex::Regex; use regex::Regex;
use reqwest::{header, Method}; use reqwest::{header, Method};
@@ -9,7 +10,6 @@ use rsa::{Oaep, RsaPublicKey};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::bilibili::Client; use crate::bilibili::Client;
use crate::Result;
#[derive(Default, Debug, Clone, Serialize, Deserialize)] #[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Credential { pub struct Credential {
@@ -43,7 +43,7 @@ impl Credential {
.await? .await?
.json::<serde_json::Value>() .json::<serde_json::Value>()
.await?; .await?;
res["data"]["refresh"].as_bool().ok_or("check refresh failed".into()) res["data"]["refresh"].as_bool().ok_or(anyhow!("check refresh failed"))
} }
pub async fn refresh(&mut self, client: &Client) -> Result<()> { pub async fn refresh(&mut self, client: &Client) -> Result<()> {
@@ -85,8 +85,8 @@ JNrRuoEUXpabUzGB8QIDAQAB
.await?; .await?;
if !res.status().is_success() { if !res.status().is_success() {
return match res.status().as_u16() { return match res.status().as_u16() {
404 => Err("correspond path is wrong or expired".into()), 404 => Err(anyhow!("correspond path is wrong or expired")),
_ => Err("get csrf failed".into()), _ => Err(anyhow!("get csrf failed")),
}; };
} }
regex_find(r#"<div id="1-name">(.+?)</div>"#, res.text().await?.as_str()) regex_find(r#"<div id="1-name">(.+?)</div>"#, res.text().await?.as_str())
@@ -122,7 +122,7 @@ JNrRuoEUXpabUzGB8QIDAQAB
.filter(|x| required_cookies.contains(x.name())) .filter(|x| required_cookies.contains(x.name()))
.collect(); .collect();
if cookies.len() != required_cookies.len() { if cookies.len() != required_cookies.len() {
return Err("not all required cookies found".into()); bail!("not all required cookies found");
} }
for cookie in cookies { for cookie in cookies {
match cookie.name() { match cookie.name() {
@@ -134,7 +134,7 @@ JNrRuoEUXpabUzGB8QIDAQAB
} }
let json = res.json::<serde_json::Value>().await?; let json = res.json::<serde_json::Value>().await?;
if !json["data"]["refresh_token"].is_string() { if !json["data"]["refresh_token"].is_string() {
return Err("refresh_token not found".into()); bail!("refresh_token not found");
} }
credential.ac_time_value = json["data"]["refresh_token"].as_str().unwrap().to_string(); credential.ac_time_value = json["data"]["refresh_token"].as_str().unwrap().to_string();
Ok(credential) Ok(credential)
@@ -157,7 +157,7 @@ JNrRuoEUXpabUzGB8QIDAQAB
.json::<serde_json::Value>() .json::<serde_json::Value>()
.await?; .await?;
if res["code"] != 0 { if res["code"] != 0 {
return Err(format!("confirm refresh failed: {}", res["message"]).into()); bail!("confirm refresh failed: {}", res["message"]);
} }
Ok(()) Ok(())
} }
@@ -168,7 +168,7 @@ 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("pattern not match")? .ok_or(anyhow!("pattern not match"))?
.get(1) .get(1)
.unwrap() .unwrap()
.as_str() .as_str()
+2 -2
View File
@@ -1,3 +1,4 @@
use anyhow::{bail, Result};
use async_stream::stream; use async_stream::stream;
use chrono::serde::ts_seconds; use chrono::serde::ts_seconds;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
@@ -5,7 +6,6 @@ use futures_core::stream::Stream;
use serde_json::Value; use serde_json::Value;
use crate::bilibili::BiliClient; use crate::bilibili::BiliClient;
use crate::Result;
pub struct FavoriteList<'a> { pub struct FavoriteList<'a> {
client: &'a BiliClient, client: &'a BiliClient,
fid: String, fid: String,
@@ -75,7 +75,7 @@ impl<'a> FavoriteList<'a> {
.json::<serde_json::Value>() .json::<serde_json::Value>()
.await?; .await?;
if res["code"] != 0 { if res["code"] != 0 {
return Err(format!("get favorite videos failed: {}", res["message"]).into()); bail!("get favorite videos failed: {}", res["message"]);
} }
Ok(res) Ok(res)
} }
+2 -2
View File
@@ -1,8 +1,8 @@
use anyhow::{bail, Result};
use reqwest::Method; use reqwest::Method;
use crate::bilibili::analyzer::PageAnalyzer; use crate::bilibili::analyzer::PageAnalyzer;
use crate::bilibili::client::BiliClient; use crate::bilibili::client::BiliClient;
use crate::Result;
static MASK_CODE: u64 = 2251799813685247; static MASK_CODE: u64 = 2251799813685247;
static XOR_CODE: u64 = 23442827791579; static XOR_CODE: u64 = 23442827791579;
@@ -89,7 +89,7 @@ impl<'a> Video<'a> {
.json::<serde_json::Value>() .json::<serde_json::Value>()
.await?; .await?;
if res["code"] != 0 { if res["code"] != 0 {
return Err(format!("get page analyzer failed: {}", res["message"]).into()); bail!("get page analyzer failed: {}", res["message"]);
} }
Ok(PageAnalyzer::new(res["data"].take())) Ok(PageAnalyzer::new(res["data"].take()))
} }
+3 -3
View File
@@ -2,12 +2,12 @@ use std::collections::HashMap;
use std::path::Path; use std::path::Path;
use std::sync::Mutex; use std::sync::Mutex;
use anyhow::{anyhow, Result};
use log::warn; use log::warn;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::bilibili::{Credential, FilterOption}; use crate::bilibili::{Credential, FilterOption};
use crate::Result;
pub static CONFIG: Lazy<Mutex<Config>> = Lazy::new(|| { pub static CONFIG: Lazy<Mutex<Config>> = Lazy::new(|| {
let config = Config::new(); let config = Config::new();
@@ -75,7 +75,7 @@ impl Config {
fn load() -> Result<Self> { fn load() -> Result<Self> {
let config_path = dirs::config_dir() let config_path = dirs::config_dir()
.ok_or("No config path found")? .ok_or(anyhow!("No config path found"))?
.join("bili-sync") .join("bili-sync")
.join("config.toml"); .join("config.toml");
let config_content = std::fs::read_to_string(config_path)?; let config_content = std::fs::read_to_string(config_path)?;
@@ -84,7 +84,7 @@ impl Config {
pub fn save(&self) -> Result<()> { pub fn save(&self) -> Result<()> {
let config_path = dirs::config_dir() let config_path = dirs::config_dir()
.ok_or("No config path found")? .ok_or(anyhow!("No config path found"))?
.join("bili-sync") .join("bili-sync")
.join("config.toml"); .join("config.toml");
if let Some(parent) = config_path.parent() { if let Some(parent) = config_path.parent() {
+2 -2
View File
@@ -2,6 +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, Result};
use dirs::config_dir; use dirs::config_dir;
use entity::{favorite, page, video}; use entity::{favorite, page, video};
use filenamify::filenamify; use filenamify::filenamify;
@@ -21,7 +22,6 @@ use super::utils::{unhandled_videos_pages, ModelWrapper, NFOMode, NFOSerializer,
use crate::bilibili::{BestStream, BiliClient, FavoriteList, FilterOption, PageInfo, Video}; use crate::bilibili::{BestStream, BiliClient, FavoriteList, FilterOption, PageInfo, Video};
use crate::core::utils::{create_video_pages, create_videos, exist_labels, filter_videos, handle_favorite_info}; use crate::core::utils::{create_video_pages, create_videos, exist_labels, filter_videos, handle_favorite_info};
use crate::downloader::Downloader; use crate::downloader::Downloader;
use crate::Result;
/// 处理某个收藏夹,首先刷新收藏夹信息,然后下载收藏夹中未下载成功的视频 /// 处理某个收藏夹,首先刷新收藏夹信息,然后下载收藏夹中未下载成功的视频
pub async fn process_favorite( pub async fn process_favorite(
@@ -234,7 +234,7 @@ pub async fn dispatch_download_page(
&video_model.bvid, page_model.pid, &page_status &video_model.bvid, page_model.pid, &page_status
); );
if final_result.is_ok() && page_status.should_run().iter().any(|x| *x) { if final_result.is_ok() && page_status.should_run().iter().any(|x| *x) {
final_result = Err("Some page item download failed".into()); final_result = Err(anyhow!("Some page item download failed"));
} }
} }
Err(e) => { Err(e) => {
+5 -3
View File
@@ -1,6 +1,6 @@
use core::fmt; use core::fmt;
use crate::Result; use anyhow::Result;
static STATUS_MAX_RETRY: u32 = 0b100; static STATUS_MAX_RETRY: u32 = 0b100;
static STATUS_OK: u32 = 0b111; static STATUS_OK: u32 = 0b111;
@@ -203,6 +203,8 @@ impl From<PageStatus> for u32 {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use anyhow::anyhow;
use super::*; use super::*;
#[test] #[test]
@@ -210,11 +212,11 @@ mod test {
let mut status = Status::new(0); let mut status = Status::new(0);
assert_eq!(status.should_run(3), vec![true, true, true]); assert_eq!(status.should_run(3), vec![true, true, true]);
for count in 1..=3 { for count in 1..=3 {
status.update_status(&[Err("".into()), Ok(()), Ok(())]); status.update_status(&[Err(anyhow!("")), Ok(()), Ok(())]);
assert_eq!(status.should_run(3), vec![true, false, false]); assert_eq!(status.should_run(3), vec![true, false, false]);
assert_eq!(u32::from(status.clone()), 0b111_111_000 + count); assert_eq!(u32::from(status.clone()), 0b111_111_000 + count);
} }
status.update_status(&[Err("".into()), Ok(()), Ok(())]); status.update_status(&[Err(anyhow!("")), Ok(()), Ok(())]);
assert_eq!(status.should_run(3), vec![false, false, false]); assert_eq!(status.should_run(3), vec![false, false, false]);
assert_eq!(u32::from(status), 0b111_111_100 | Status::handled()); assert_eq!(u32::from(status), 0b111_111_100 | Status::handled());
} }
+1 -1
View File
@@ -1,6 +1,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::path::Path; use std::path::Path;
use anyhow::Result;
use entity::*; use entity::*;
use filenamify::filenamify; use filenamify::filenamify;
use migration::OnConflict; use migration::OnConflict;
@@ -17,7 +18,6 @@ use tokio::io::AsyncWriteExt;
use super::status::Status; use super::status::Status;
use crate::bilibili::{FavoriteListInfo, PageInfo, VideoInfo}; use crate::bilibili::{FavoriteListInfo, PageInfo, VideoInfo};
use crate::config::CONFIG; use crate::config::CONFIG;
use crate::Result;
pub static TEMPLATE: Lazy<handlebars::Handlebars> = Lazy::new(|| { pub static TEMPLATE: Lazy<handlebars::Handlebars> = Lazy::new(|| {
let mut handlebars = handlebars::Handlebars::new(); let mut handlebars = handlebars::Handlebars::new();
+2 -3
View File
@@ -1,10 +1,9 @@
use anyhow::{anyhow, Result};
use migration::{Migrator, MigratorTrait}; use migration::{Migrator, MigratorTrait};
use sea_orm::{Database, DatabaseConnection}; use sea_orm::{Database, DatabaseConnection};
use tokio::fs; use tokio::fs;
use crate::Result;
pub async fn database_connection() -> Result<DatabaseConnection> { pub async fn database_connection() -> Result<DatabaseConnection> {
let config_dir = dirs::config_dir().ok_or("No config path found")?; let config_dir = dirs::config_dir().ok_or(anyhow!("No config path found"))?;
let target = config_dir.join("bili-sync").join("data.sqlite"); let target = config_dir.join("bili-sync").join("data.sqlite");
if let Some(parent) = target.parent() { if let Some(parent) = target.parent() {
fs::create_dir_all(parent).await?; fs::create_dir_all(parent).await?;
+3 -3
View File
@@ -1,12 +1,12 @@
use std::path::Path; use std::path::Path;
use anyhow::{anyhow, Result};
use futures_util::StreamExt; use futures_util::StreamExt;
use reqwest::Method; use reqwest::Method;
use tokio::fs::{self, File}; use tokio::fs::{self, File};
use tokio::io; use tokio::io;
use crate::bilibili::Client; use crate::bilibili::Client;
use crate::Result;
pub struct Downloader { pub struct Downloader {
client: Client, client: Client,
} }
@@ -46,8 +46,8 @@ impl Downloader {
.await?; .await?;
if !output.status.success() { if !output.status.success() {
return match String::from_utf8(output.stderr) { return match String::from_utf8(output.stderr) {
Ok(err) => Err(err.into()), Ok(err) => Err(anyhow!(err)),
_ => Err("ffmpeg error".into()), _ => Err(anyhow!("ffmpeg error")),
}; };
} }
let _ = fs::remove_file(video_path).await; let _ = fs::remove_file(video_path).await;
-4
View File
@@ -1,9 +1,5 @@
use std::error;
pub mod bilibili; pub mod bilibili;
pub mod config; pub mod config;
pub mod core; pub mod core;
pub mod database; pub mod database;
pub mod downloader; pub mod downloader;
type Result<T> = std::result::Result<T, Box<dyn error::Error>>;