diff --git a/crates/bili_sync/src/adapter/collection.rs b/crates/bili_sync/src/adapter/collection.rs index 4cbf7d6..3176083 100644 --- a/crates/bili_sync/src/adapter/collection.rs +++ b/crates/bili_sync/src/adapter/collection.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::path::Path; use std::pin::Pin; -use anyhow::Result; +use anyhow::{anyhow, Result}; use async_trait::async_trait; use bili_sync_entity::*; use futures::Stream; @@ -90,7 +90,7 @@ impl VideoListModel for collection::Model { // 将页标记和 tag 写入数据库 let mut video_active_model = self.video_model_by_info(&view_info, Some(video_model)); video_active_model.single_page = Set(Some(pages.len() == 1)); - video_active_model.tags = Set(Some(serde_json::to_value(tags).unwrap())); + video_active_model.tags = Set(Some(serde_json::to_value(tags)?)); video_active_model.save(&txn).await?; txn.commit().await?; } @@ -196,7 +196,7 @@ pub(super) async fn collection_from<'a>( ) .one(connection) .await? - .unwrap(), + .ok_or(anyhow!("collection not found"))?, ), Box::pin(collection.into_simple_video_stream()), )) diff --git a/crates/bili_sync/src/adapter/favorite.rs b/crates/bili_sync/src/adapter/favorite.rs index 5166c91..9bc0f61 100644 --- a/crates/bili_sync/src/adapter/favorite.rs +++ b/crates/bili_sync/src/adapter/favorite.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::path::Path; use std::pin::Pin; -use anyhow::Result; +use anyhow::{anyhow, Result}; use async_trait::async_trait; use bili_sync_entity::*; use futures::Stream; @@ -87,7 +87,7 @@ impl VideoListModel for favorite::Model { // 将页标记和 tag 写入数据库 let mut video_active_model: video::ActiveModel = video_model.into(); video_active_model.single_page = Set(Some(pages_info.len() == 1)); - video_active_model.tags = Set(Some(serde_json::to_value(tags).unwrap())); + video_active_model.tags = Set(Some(serde_json::to_value(tags)?)); video_active_model.save(&txn).await?; txn.commit().await?; } @@ -153,7 +153,7 @@ pub(super) async fn favorite_from<'a>( .filter(favorite::Column::FId.eq(favorite_info.id)) .one(connection) .await? - .unwrap(), + .ok_or(anyhow!("favorite not found"))?, ), Box::pin(favorite.into_video_stream()), )) diff --git a/crates/bili_sync/src/adapter/helper/mod.rs b/crates/bili_sync/src/adapter/helper/mod.rs index 56e23e2..620ee7c 100644 --- a/crates/bili_sync/src/adapter/helper/mod.rs +++ b/crates/bili_sync/src/adapter/helper/mod.rs @@ -65,7 +65,11 @@ pub(super) fn video_with_path( ) -> video::ActiveModel { if let Some(fmt_args) = &video_info.to_fmt_args() { video_model.path = Set(Path::new(base_path) - .join(TEMPLATE.path_safe_render("video", fmt_args).unwrap()) + .join( + TEMPLATE + .path_safe_render("video", fmt_args) + .expect("template render failed"), + ) .to_string_lossy() .to_string()); } diff --git a/crates/bili_sync/src/adapter/submission.rs b/crates/bili_sync/src/adapter/submission.rs index 8200b73..ebe6149 100644 --- a/crates/bili_sync/src/adapter/submission.rs +++ b/crates/bili_sync/src/adapter/submission.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::path::Path; use std::pin::Pin; -use anyhow::Result; +use anyhow::{anyhow, Result}; use async_trait::async_trait; use bili_sync_entity::*; use futures::Stream; @@ -91,7 +91,7 @@ impl VideoListModel for submission::Model { // 将页标记和 tag 写入数据库 let mut video_active_model = self.video_model_by_info(&view_info, Some(video_model)); video_active_model.single_page = Set(Some(pages.len() == 1)); - video_active_model.tags = Set(Some(serde_json::to_value(tags).unwrap())); + video_active_model.tags = Set(Some(serde_json::to_value(tags)?)); video_active_model.save(&txn).await?; txn.commit().await?; } @@ -169,7 +169,7 @@ pub(super) async fn submission_from<'a>( .filter(submission::Column::UpperId.eq(upper.mid)) .one(connection) .await? - .unwrap(), + .ok_or(anyhow!("submission not found"))?, ), Box::pin(submission.into_video_stream()), )) diff --git a/crates/bili_sync/src/adapter/watch_later.rs b/crates/bili_sync/src/adapter/watch_later.rs index b9eb084..195151c 100644 --- a/crates/bili_sync/src/adapter/watch_later.rs +++ b/crates/bili_sync/src/adapter/watch_later.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::path::Path; use std::pin::Pin; -use anyhow::Result; +use anyhow::{anyhow, Result}; use async_trait::async_trait; use bili_sync_entity::*; use futures::Stream; @@ -88,7 +88,7 @@ impl VideoListModel for watch_later::Model { // 将页标记和 tag 写入数据库 let mut video_active_model: video::ActiveModel = video_model.into(); video_active_model.single_page = Set(Some(pages_info.len() == 1)); - video_active_model.tags = Set(Some(serde_json::to_value(tags).unwrap())); + video_active_model.tags = Set(Some(serde_json::to_value(tags)?)); video_active_model.save(&txn).await?; txn.commit().await?; } @@ -151,7 +151,7 @@ pub(super) async fn watch_later_from<'a>( .filter(watch_later::Column::Id.eq(1)) .one(connection) .await? - .unwrap(), + .ok_or(anyhow!("watch_later not found"))?, ), Box::pin(watch_later.into_video_stream()), )) diff --git a/crates/bili_sync/src/bilibili/analyzer.rs b/crates/bili_sync/src/bilibili/analyzer.rs index b7bfacc..660fa9b 100644 --- a/crates/bili_sync/src/bilibili/analyzer.rs +++ b/crates/bili_sync/src/bilibili/analyzer.rs @@ -7,7 +7,7 @@ pub struct PageAnalyzer { info: serde_json::Value, } -#[derive(Debug, strum::FromRepr, PartialEq, PartialOrd, Serialize, Deserialize)] +#[derive(Debug, strum::FromRepr, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum VideoQuality { Quality360p = 16, Quality480p = 32, @@ -21,7 +21,7 @@ pub enum VideoQuality { Quality8k = 127, } -#[derive(Debug, Clone, Copy, strum::FromRepr, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, strum::FromRepr, PartialEq, Eq, Serialize, Deserialize)] pub enum AudioQuality { Quality64k = 30216, Quality132k = 30232, @@ -30,6 +30,18 @@ pub enum AudioQuality { Quality192k = 30280, } +impl Ord for AudioQuality { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_sort_key().cmp(&other.as_sort_key()) + } +} + +impl PartialOrd for AudioQuality { + fn partial_cmp(&self, other: &AudioQuality) -> Option { + Some(self.cmp(other)) + } +} + impl AudioQuality { #[inline] pub fn as_sort_key(&self) -> isize { @@ -41,12 +53,6 @@ impl AudioQuality { } } -impl PartialOrd for AudioQuality { - fn partial_cmp(&self, other: &AudioQuality) -> Option { - self.as_sort_key().partial_cmp(&other.as_sort_key()) - } -} - #[allow(clippy::upper_case_acronyms)] #[derive(Debug, strum::EnumString, strum::Display, strum::AsRefStr, PartialEq, PartialOrd, Serialize, Deserialize)] pub enum VideoCodecs { @@ -281,7 +287,7 @@ impl PageAnalyzer { }, ) => { if a_quality != b_quality { - return a_quality.partial_cmp(b_quality).unwrap(); + return a_quality.cmp(b_quality); }; filter_option .codecs @@ -294,7 +300,7 @@ impl PageAnalyzer { .ok_or(anyhow!("no video stream found"))?, audio: Iterator::max_by(audios.into_iter(), |a, b| match (a, b) { (Stream::DashAudio { quality: a_quality, .. }, Stream::DashAudio { quality: b_quality, .. }) => { - a_quality.partial_cmp(b_quality).unwrap() + a_quality.cmp(b_quality) } _ => unreachable!(), }), diff --git a/crates/bili_sync/src/bilibili/client.rs b/crates/bili_sync/src/bilibili/client.rs index 70b71d6..4ed4a34 100644 --- a/crates/bili_sync/src/bilibili/client.rs +++ b/crates/bili_sync/src/bilibili/client.rs @@ -34,7 +34,7 @@ impl Client { .connect_timeout(std::time::Duration::from_secs(10)) .read_timeout(std::time::Duration::from_secs(10)) .build() - .unwrap(), + .expect("failed to build reqwest client"), ) } diff --git a/crates/bili_sync/src/bilibili/collection.rs b/crates/bili_sync/src/bilibili/collection.rs index a8ec6de..20ac038 100644 --- a/crates/bili_sync/src/bilibili/collection.rs +++ b/crates/bili_sync/src/bilibili/collection.rs @@ -169,37 +169,49 @@ impl<'a> Collection<'a> { let mut videos = match self.get_videos(page).await { Ok(v) => v, Err(e) => { - error!("failed to get videos of collection {:?} page {}: {}", self.collection, page, e); + error!( + "failed to get videos of collection {:?} page {}: {}", + self.collection, page, e + ); break; - }, + } }; - if !videos["data"]["archives"].is_array() { - warn!("no videos found in collection {:?} page {}", self.collection, page); + let archives = &mut videos["data"]["archives"]; + if archives.as_array().is_none_or(|v| v.is_empty()) { + error!("no videos found in collection {:?} page {}", self.collection, page); break; } - let videos_info = match serde_json::from_value::>(videos["data"]["archives"].take()) { + let videos_info: Vec = match serde_json::from_value(archives.take()) { Ok(v) => v, Err(e) => { - error!("failed to parse videos of collection {:?} page {}: {}", self.collection, page, e); + error!( + "failed to parse videos of collection {:?} page {}: {}", + self.collection, page, e + ); break; - }, + } }; - for video_info in videos_info{ + for video_info in videos_info { yield video_info; } - let fields = match self.collection.collection_type{ + let page_info = &videos["data"]["page"]; + let fields = match self.collection.collection_type { CollectionType::Series => ["num", "size", "total"], CollectionType::Season => ["page_num", "page_size", "total"], }; - let fields = fields.into_iter().map(|f| videos["data"]["page"][f].as_i64()).collect::>>().map(|v| (v[0], v[1], v[2])); - let Some((num, size, total)) = fields else { - error!("failed to get pages of collection {:?} page {}: {:?}", self.collection, page, fields); - break; - }; - if num * size >= total { - break; + let values = fields.iter().map(|f| page_info[f].as_i64()).collect::>>(); + if let [Some(num), Some(size), Some(total)] = values[..] { + if num * size < total { + page += 1; + continue; + } + } else { + error!( + "invalid page info of collection {:?} page {}: read {:?} from {}", + self.collection, page, fields, page_info + ); } - page += 1; + break; } } } diff --git a/crates/bili_sync/src/bilibili/credential.rs b/crates/bili_sync/src/bilibili/credential.rs index a180fee..876f246 100644 --- a/crates/bili_sync/src/bilibili/credential.rs +++ b/crates/bili_sync/src/bilibili/credential.rs @@ -95,11 +95,13 @@ nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40 JNrRuoEUXpabUzGB8QIDAQAB -----END PUBLIC KEY-----", ) - .unwrap(); + .expect("fail to decode public key"); let ts = chrono::Local::now().timestamp_millis(); let data = format!("refresh_{}", ts).into_bytes(); let mut rng = rand::rngs::OsRng; - let encrypted = key.encrypt(&mut rng, Oaep::new::(), &data).unwrap(); + let encrypted = key + .encrypt(&mut rng, Oaep::new::(), &data) + .expect("fail to encrypt"); hex::encode(encrypted) } @@ -161,10 +163,10 @@ JNrRuoEUXpabUzGB8QIDAQAB _ => unreachable!(), } } - if !res["data"]["refresh_token"].is_string() { - bail!("refresh_token not found"); + match res["data"]["refresh_token"].as_str() { + Some(token) => credential.ac_time_value = token.to_string(), + None => bail!("refresh_token not found"), } - credential.ac_time_value = res["data"]["refresh_token"].as_str().unwrap().to_string(); Ok(credential) } @@ -195,9 +197,9 @@ fn regex_find(pattern: &str, doc: &str) -> Result { let re = Regex::new(pattern)?; Ok(re .captures(doc) - .ok_or(anyhow!("pattern not match"))? + .ok_or_else(|| anyhow!("no match found"))? .get(1) - .unwrap() + .ok_or_else(|| anyhow!("no capture found"))? .as_str() .to_string()) } @@ -240,7 +242,9 @@ fn _encoded_query<'a>( .collect(); params.push(("wts", timestamp.into())); params.sort_by(|a, b| a.0.cmp(b.0)); - let query = serde_urlencoded::to_string(¶ms).unwrap().replace('+', "%20"); + let query = serde_urlencoded::to_string(¶ms) + .expect("fail to encode query") + .replace('+', "%20"); params.push(("w_rid", format!("{:x}", md5::compute(query.clone() + mixin_key)).into())); params } diff --git a/crates/bili_sync/src/bilibili/favorite_list.rs b/crates/bili_sync/src/bilibili/favorite_list.rs index 1f4c723..cb74753 100644 --- a/crates/bili_sync/src/bilibili/favorite_list.rs +++ b/crates/bili_sync/src/bilibili/favorite_list.rs @@ -71,23 +71,25 @@ impl<'a> FavoriteList<'a> { Err(e) => { error!("failed to get videos of favorite {} page {}: {}", self.fid, page, e); break; - }, + } }; - if !videos["data"]["medias"].is_array() { - warn!("no medias found in favorite {} page {}", self.fid, page); + let medias = &mut videos["data"]["medias"]; + if medias.as_array().is_none_or(|v| v.is_empty()) { + error!("no medias found in favorite {} page {}", self.fid, page); break; } - let videos_info = match serde_json::from_value::>(videos["data"]["medias"].take()) { + let videos_info: Vec = match serde_json::from_value(medias.take()) { Ok(v) => v, Err(e) => { error!("failed to parse videos of favorite {} page {}: {}", self.fid, page, e); break; - }, + } }; - for video_info in videos_info{ + for video_info in videos_info { yield video_info; } - if videos["data"]["has_more"].is_boolean() && videos["data"]["has_more"].as_bool().unwrap(){ + let has_more = &videos["data"]["has_more"]; + if has_more.as_bool().is_some_and(|v| v) { page += 1; continue; } diff --git a/crates/bili_sync/src/bilibili/submission.rs b/crates/bili_sync/src/bilibili/submission.rs index 0df27b2..4a96c7f 100644 --- a/crates/bili_sync/src/bilibili/submission.rs +++ b/crates/bili_sync/src/bilibili/submission.rs @@ -66,23 +66,25 @@ impl<'a> Submission<'a> { Err(e) => { error!("failed to get videos of upper {} page {}: {}", self.upper_id, page, e); break; - }, + } }; - if !videos["data"]["list"]["vlist"].is_array() { - warn!("no medias found in upper {} page {}", self.upper_id, page); + let vlist = &mut videos["data"]["list"]["vlist"]; + if vlist.as_array().is_none_or(|v| v.is_empty()) { + error!("no medias found in upper {} page {}", self.upper_id, page); break; } - let videos_info = match serde_json::from_value::>(videos["data"]["list"]["vlist"].take()) { + let videos_info: Vec = match serde_json::from_value(vlist.take()) { Ok(v) => v, Err(e) => { error!("failed to parse videos of upper {} page {}: {}", self.upper_id, page, e); break; - }, + } }; - for video_info in videos_info{ + for video_info in videos_info { yield video_info; } - if videos["data"]["page"]["count"].is_i64() && videos["data"]["page"]["count"].as_i64().unwrap() > (page * 30) as i64 { + let count = &videos["data"]["page"]["count"]; + if count.as_i64().is_some_and(|v| v > (page * 30) as i64) { page += 1; continue; } diff --git a/crates/bili_sync/src/bilibili/video.rs b/crates/bili_sync/src/bilibili/video.rs index a9aa196..3c39b56 100644 --- a/crates/bili_sync/src/bilibili/video.rs +++ b/crates/bili_sync/src/bilibili/video.rs @@ -172,7 +172,7 @@ fn bvid_to_aid(bvid: &str) -> u64 { (bvid[4], bvid[7]) = (bvid[7], bvid[4]); let mut tmp = 0u64; for char in bvid.into_iter().skip(3) { - let idx = DATA.iter().position(|&x| x == char).unwrap(); + let idx = DATA.iter().position(|&x| x == char).expect("invalid bvid"); tmp = tmp * BASE + idx as u64; } (tmp & MASK_CODE) ^ XOR_CODE diff --git a/crates/bili_sync/src/config/global.rs b/crates/bili_sync/src/config/global.rs index 0af0f62..e131d3d 100644 --- a/crates/bili_sync/src/config/global.rs +++ b/crates/bili_sync/src/config/global.rs @@ -22,8 +22,12 @@ pub static TEMPLATE: Lazy = Lazy::new(|| { } }); handlebars.register_helper("truncate", Box::new(truncate)); - handlebars.path_safe_register("video", &CONFIG.video_name).unwrap(); - handlebars.path_safe_register("page", &CONFIG.page_name).unwrap(); + handlebars + .path_safe_register("video", &CONFIG.video_name) + .expect("failed to register video template"); + handlebars + .path_safe_register("page", &CONFIG.page_name) + .expect("failed to register page template"); handlebars }); diff --git a/crates/bili_sync/src/utils/filenamify.rs b/crates/bili_sync/src/utils/filenamify.rs index fab07ce..05c7ebb 100644 --- a/crates/bili_sync/src/utils/filenamify.rs +++ b/crates/bili_sync/src/utils/filenamify.rs @@ -1,7 +1,7 @@ macro_rules! regex { ($re:literal $(,)?) => {{ static RE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); - RE.get_or_init(|| regex::Regex::new($re).unwrap()) + RE.get_or_init(|| regex::Regex::new($re).expect("invalid regex")) }}; }