refactor: 把循环拆分到外层,提取公共代码 (#151)

This commit is contained in:
ᴀᴍᴛᴏᴀᴇʀ
2024-07-24 00:36:19 +08:00
committed by GitHub
parent 20e3ac2129
commit 8f37fdf841
5 changed files with 101 additions and 114 deletions
+26 -38
View File
@@ -11,12 +11,12 @@ use sea_orm::entity::prelude::*;
use sea_orm::ActiveValue::Set; use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, QuerySelect, TransactionTrait}; use sea_orm::{DatabaseConnection, QuerySelect, TransactionTrait};
use crate::adapter::VideoListModel; use crate::adapter::{error_fetch_video_detail, VideoListModel};
use crate::bilibili::{BiliClient, BiliError, Collection, CollectionItem, CollectionType, Video, VideoInfo}; use crate::bilibili::{self, BiliClient, Collection, CollectionItem, CollectionType, VideoInfo};
use crate::config::{CONFIG, TEMPLATE}; use crate::config::TEMPLATE;
use crate::utils::id_time_key;
use crate::utils::model::create_video_pages; use crate::utils::model::create_video_pages;
use crate::utils::status::Status; use crate::utils::status::Status;
use crate::utils::{delay, id_time_key};
pub async fn collection_from<'a>( pub async fn collection_from<'a>(
collection_item: &'a CollectionItem, collection_item: &'a CollectionItem,
@@ -144,42 +144,30 @@ impl VideoListModel for collection::Model {
async fn fetch_videos_detail( async fn fetch_videos_detail(
&self, &self,
bili_clent: &BiliClient, video: bilibili::Video<'_>,
videos_model: Vec<video::Model>, video_model: video::Model,
connection: &DatabaseConnection, connection: &DatabaseConnection,
) -> Result<()> { ) -> Result<()> {
for video_model in videos_model { let info: Result<_> = async { Ok((video.get_tags().await?, video.get_view_info().await?)) }.await;
let video = Video::new(bili_clent, video_model.bvid.clone()); match info {
let info: Result<_> = async { Ok((video.get_tags().await?, video.get_view_info().await?)) }.await; Ok((tags, view_info)) => {
match info { let VideoInfo::View { pages, .. } = &view_info else {
Ok((tags, view_info)) => { unreachable!("view_info must be VideoInfo::View")
let VideoInfo::View { pages, .. } = &view_info else { };
unreachable!("view_info must be VideoInfo::View") let txn = connection.begin().await?;
}; // 将分页信息写入数据库
let txn = connection.begin().await?; create_video_pages(pages, &video_model, &txn).await?;
// 将分页信息写入数据库 // 将页标记和 tag 写入数据库
create_video_pages(pages, &video_model, &txn).await?; let mut video_active_model = self.video_model_by_info(&view_info, Some(video_model));
// 将页标记和 tag 写入数据库 video_active_model.single_page = Set(Some(pages.len() == 1));
let mut video_active_model = self.video_model_by_info(&view_info, Some(video_model)); video_active_model.tags = Set(Some(serde_json::to_value(tags).unwrap()));
video_active_model.single_page = Set(Some(pages.len() == 1)); video_active_model.save(&txn).await?;
video_active_model.tags = Set(Some(serde_json::to_value(tags).unwrap())); txn.commit().await?;
video_active_model.save(&txn).await?; }
txn.commit().await?; Err(e) => {
} error_fetch_video_detail(e, video_model, connection).await?;
Err(e) => { }
error!( };
"获取视频 {} - {} 的详细信息失败,错误为:{}",
&video_model.bvid, &video_model.name, e
);
if let Some(BiliError::RequestFailed(-404, _)) = e.downcast_ref::<BiliError>() {
let mut video_active_model: video::ActiveModel = video_model.into();
video_active_model.valid = Set(false);
video_active_model.save(connection).await?;
}
}
};
delay(CONFIG.delay.fetch_video_detail.as_ref()).await;
}
Ok(()) Ok(())
} }
+23 -35
View File
@@ -11,12 +11,12 @@ use sea_orm::entity::prelude::*;
use sea_orm::ActiveValue::Set; use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, QuerySelect, TransactionTrait}; use sea_orm::{DatabaseConnection, QuerySelect, TransactionTrait};
use crate::adapter::VideoListModel; use crate::adapter::{error_fetch_video_detail, VideoListModel};
use crate::bilibili::{BiliClient, BiliError, FavoriteList, Video, VideoInfo}; use crate::bilibili::{self, BiliClient, FavoriteList, VideoInfo};
use crate::config::{CONFIG, TEMPLATE}; use crate::config::TEMPLATE;
use crate::utils::id_time_key;
use crate::utils::model::create_video_pages; use crate::utils::model::create_video_pages;
use crate::utils::status::Status; use crate::utils::status::Status;
use crate::utils::{delay, id_time_key};
pub async fn favorite_from<'a>( pub async fn favorite_from<'a>(
fid: &str, fid: &str,
@@ -134,39 +134,27 @@ impl VideoListModel for favorite::Model {
async fn fetch_videos_detail( async fn fetch_videos_detail(
&self, &self,
bili_clent: &BiliClient, video: bilibili::Video<'_>,
videos_model: Vec<video::Model>, video_model: video::Model,
connection: &DatabaseConnection, connection: &DatabaseConnection,
) -> Result<()> { ) -> Result<()> {
for video_model in videos_model { let info: Result<_> = async { Ok((video.get_tags().await?, video.get_pages().await?)) }.await;
let video = Video::new(bili_clent, video_model.bvid.clone()); match info {
let info: Result<_> = async { Ok((video.get_tags().await?, video.get_pages().await?)) }.await; Ok((tags, pages_info)) => {
match info { let txn = connection.begin().await?;
Ok((tags, pages_info)) => { // 将分页信息写入数据库
let txn = connection.begin().await?; create_video_pages(&pages_info, &video_model, &txn).await?;
// 将分页信息写入数据库 // 将页标记和 tag 写入数据库
create_video_pages(&pages_info, &video_model, &txn).await?; let mut video_active_model: video::ActiveModel = video_model.into();
// 将页标记和 tag 写入数据库 video_active_model.single_page = Set(Some(pages_info.len() == 1));
let mut video_active_model: video::ActiveModel = video_model.into(); video_active_model.tags = Set(Some(serde_json::to_value(tags).unwrap()));
video_active_model.single_page = Set(Some(pages_info.len() == 1)); video_active_model.save(&txn).await?;
video_active_model.tags = Set(Some(serde_json::to_value(tags).unwrap())); txn.commit().await?;
video_active_model.save(&txn).await?; }
txn.commit().await?; Err(e) => {
} error_fetch_video_detail(e, video_model, connection).await?;
Err(e) => { }
error!( };
"获取视频 {} - {} 的详细信息失败,错误为:{}",
&video_model.bvid, &video_model.name, e
);
if let Some(BiliError::RequestFailed(-404, _)) = e.downcast_ref::<BiliError>() {
let mut video_active_model: video::ActiveModel = video_model.into();
video_active_model.valid = Set(false);
video_active_model.save(connection).await?;
}
}
};
delay(CONFIG.delay.fetch_video_detail.as_ref()).await;
}
Ok(()) Ok(())
} }
+22 -3
View File
@@ -11,10 +11,12 @@ use async_trait::async_trait;
pub use collection::collection_from; pub use collection::collection_from;
pub use favorite::favorite_from; pub use favorite::favorite_from;
use futures::Stream; use futures::Stream;
use sea_orm::entity::prelude::*;
use sea_orm::ActiveValue::Set;
use sea_orm::DatabaseConnection; use sea_orm::DatabaseConnection;
use watch_later::watch_later_from; use watch_later::watch_later_from;
use crate::bilibili::{BiliClient, CollectionItem, VideoInfo}; use crate::bilibili::{self, BiliClient, BiliError, CollectionItem, VideoInfo};
pub enum Args<'a> { pub enum Args<'a> {
Favorite { fid: &'a str }, Favorite { fid: &'a str },
@@ -35,6 +37,23 @@ pub async fn video_list_from<'a>(
} }
} }
async fn error_fetch_video_detail(
e: anyhow::Error,
video_model: bili_sync_entity::video::Model,
connection: &DatabaseConnection,
) -> Result<()> {
error!(
"获取视频 {} - {} 的详细信息失败,错误为:{}",
&video_model.bvid, &video_model.name, e
);
if let Some(BiliError::RequestFailed(-404, _)) = e.downcast_ref::<BiliError>() {
let mut video_active_model: bili_sync_entity::video::ActiveModel = video_model.into();
video_active_model.valid = Set(false);
video_active_model.save(connection).await?;
}
Ok(())
}
#[async_trait] #[async_trait]
pub trait VideoListModel { pub trait VideoListModel {
/* 逻辑相关 */ /* 逻辑相关 */
@@ -65,8 +84,8 @@ pub trait VideoListModel {
/// 获取视频 model 中缺失的信息 /// 获取视频 model 中缺失的信息
async fn fetch_videos_detail( async fn fetch_videos_detail(
&self, &self,
bili_client: &BiliClient, video: bilibili::Video<'_>,
videos_model: Vec<bili_sync_entity::video::Model>, video_model: bili_sync_entity::video::Model,
connection: &DatabaseConnection, connection: &DatabaseConnection,
) -> Result<()>; ) -> Result<()>;
+23 -35
View File
@@ -11,12 +11,12 @@ use sea_orm::entity::prelude::*;
use sea_orm::ActiveValue::Set; use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, QuerySelect, TransactionTrait}; use sea_orm::{DatabaseConnection, QuerySelect, TransactionTrait};
use crate::adapter::VideoListModel; use crate::adapter::{error_fetch_video_detail, VideoListModel};
use crate::bilibili::{BiliClient, BiliError, Video, VideoInfo, WatchLater}; use crate::bilibili::{self, BiliClient, VideoInfo, WatchLater};
use crate::config::{CONFIG, TEMPLATE}; use crate::config::TEMPLATE;
use crate::utils::id_time_key;
use crate::utils::model::create_video_pages; use crate::utils::model::create_video_pages;
use crate::utils::status::Status; use crate::utils::status::Status;
use crate::utils::{delay, id_time_key};
pub async fn watch_later_from<'a>( pub async fn watch_later_from<'a>(
path: &Path, path: &Path,
@@ -130,39 +130,27 @@ impl VideoListModel for watch_later::Model {
async fn fetch_videos_detail( async fn fetch_videos_detail(
&self, &self,
bili_clent: &BiliClient, video: bilibili::Video<'_>,
videos_model: Vec<video::Model>, video_model: video::Model,
connection: &DatabaseConnection, connection: &DatabaseConnection,
) -> Result<()> { ) -> Result<()> {
for video_model in videos_model { let info: Result<_> = async { Ok((video.get_tags().await?, video.get_pages().await?)) }.await;
let video = Video::new(bili_clent, video_model.bvid.clone()); match info {
let info: Result<_> = async { Ok((video.get_tags().await?, video.get_pages().await?)) }.await; Ok((tags, pages_info)) => {
match info { let txn = connection.begin().await?;
Ok((tags, pages_info)) => { // 将分页信息写入数据库
let txn = connection.begin().await?; create_video_pages(&pages_info, &video_model, &txn).await?;
// 将分页信息写入数据库 // 将页标记和 tag 写入数据库
create_video_pages(&pages_info, &video_model, &txn).await?; let mut video_active_model: video::ActiveModel = video_model.into();
// 将页标记和 tag 写入数据库 video_active_model.single_page = Set(Some(pages_info.len() == 1));
let mut video_active_model: video::ActiveModel = video_model.into(); video_active_model.tags = Set(Some(serde_json::to_value(tags).unwrap()));
video_active_model.single_page = Set(Some(pages_info.len() == 1)); video_active_model.save(&txn).await?;
video_active_model.tags = Set(Some(serde_json::to_value(tags).unwrap())); txn.commit().await?;
video_active_model.save(&txn).await?; }
txn.commit().await?; Err(e) => {
} error_fetch_video_detail(e, video_model, connection).await?;
Err(e) => { }
error!( };
"获取视频 {} - {} 的详细信息失败,错误为:{}",
&video_model.bvid, &video_model.name, e
);
if let Some(BiliError::RequestFailed(-404, _)) = e.downcast_ref::<BiliError>() {
let mut video_active_model: video::ActiveModel = video_model.into();
video_active_model.valid = Set(false);
video_active_model.save(connection).await?;
}
}
};
delay(CONFIG.delay.fetch_video_detail.as_ref()).await;
}
Ok(()) Ok(())
} }
+7 -3
View File
@@ -75,9 +75,13 @@ pub async fn fetch_video_details(
) -> Result<Box<dyn VideoListModel>> { ) -> Result<Box<dyn VideoListModel>> {
video_list_model.log_fetch_video_start(); video_list_model.log_fetch_video_start();
let videos_model = video_list_model.unfilled_videos(connection).await?; let videos_model = video_list_model.unfilled_videos(connection).await?;
video_list_model for video_model in videos_model {
.fetch_videos_detail(bili_client, videos_model, connection) let video = Video::new(bili_client, video_model.bvid.clone());
.await?; video_list_model
.fetch_videos_detail(video, video_model, connection)
.await?;
delay(CONFIG.delay.fetch_video_detail.as_ref()).await;
}
video_list_model.log_fetch_video_end(); video_list_model.log_fetch_video_end();
Ok(video_list_model) Ok(video_list_model)
} }