mirror of
https://github.com/amtoaer/bili-sync.git
synced 2026-07-07 23:51:47 +08:00
feat: 尽量将用户可见日志替换成中文,修复部分问题
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//! 一个弹幕实例,但是没有位置信息
|
//! 一个弹幕实例,但是没有位置信息
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Result};
|
||||||
|
|
||||||
use super::canvas::CanvasConfig;
|
use super::canvas::CanvasConfig;
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
@@ -18,7 +18,8 @@ impl DanmuType {
|
|||||||
4 => DanmuType::Bottom,
|
4 => DanmuType::Bottom,
|
||||||
5 => DanmuType::Top,
|
5 => DanmuType::Top,
|
||||||
6 => DanmuType::Reverse,
|
6 => DanmuType::Reverse,
|
||||||
_ => unreachable!(),
|
// 高级弹幕、代码弹幕等,不支持,这里 return error,外面 unwrap_or_default 当成 Float 处理
|
||||||
|
_ => bail!("UnSupported danmu type"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ impl<'a> FavoriteList<'a> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
if !videos["data"]["medias"].is_array() {
|
if !videos["data"]["medias"].is_array() {
|
||||||
error!("no medias found in favorite {} page {}", self.fid, page);
|
warn!("no medias found in favorite {} page {}", self.fid, page);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let videos_info = match serde_json::from_value::<Vec<VideoInfo>>(videos["data"]["medias"].take()) {
|
let videos_info = match serde_json::from_value::<Vec<VideoInfo>>(videos["data"]["medias"].take()) {
|
||||||
|
|||||||
@@ -114,16 +114,23 @@ impl<'a> Video<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn get_danmaku_segment(&self, page: &PageInfo, segment_idx: i32) -> Result<Vec<DanmakuElem>> {
|
async fn get_danmaku_segment(&self, page: &PageInfo, segment_idx: i32) -> Result<Vec<DanmakuElem>> {
|
||||||
let res = self
|
let mut res = self
|
||||||
.client
|
.client
|
||||||
.request(Method::GET, "http://api.bilibili.com/x/v2/dm/web/seg.so")
|
.request(Method::GET, "http://api.bilibili.com/x/v2/dm/web/seg.so")
|
||||||
.query(&[("type", 1), ("oid", page.cid), ("segment_index", segment_idx)])
|
.query(&[("type", 1), ("oid", page.cid), ("segment_index", segment_idx)])
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.error_for_status()?
|
.error_for_status()?;
|
||||||
.bytes()
|
let headers = std::mem::take(res.headers_mut());
|
||||||
.await?;
|
let content_type = headers.get("content-type");
|
||||||
Ok(DmSegMobileReply::decode(res)?.elems)
|
if !content_type.is_some_and(|v| v == "application/octet-stream") {
|
||||||
|
bail!(
|
||||||
|
"unexpected content type: {:?}, body: {:?}",
|
||||||
|
content_type,
|
||||||
|
res.text().await
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(DmSegMobileReply::decode(res.bytes().await?)?.elems)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_page_analyzer(&self, page: &PageInfo) -> Result<PageAnalyzer> {
|
pub async fn get_page_analyzer(&self, page: &PageInfo) -> Result<PageAnalyzer> {
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ use crate::bilibili::{Credential, DanmakuOption, FilterOption};
|
|||||||
|
|
||||||
pub static CONFIG: Lazy<Config> = Lazy::new(|| {
|
pub static CONFIG: Lazy<Config> = Lazy::new(|| {
|
||||||
let config = Config::load().unwrap_or_else(|err| {
|
let config = Config::load().unwrap_or_else(|err| {
|
||||||
warn!("Failed loading config: {err}");
|
warn!("加载配置失败,错误为: {err},将使用默认配置...");
|
||||||
Config::new()
|
Config::new()
|
||||||
});
|
});
|
||||||
// 放到外面,确保新的配置项被保存
|
// 放到外面,确保新的配置项被保存
|
||||||
|
info!("配置加载完毕,覆盖刷新原有配置");
|
||||||
config.save().unwrap();
|
config.save().unwrap();
|
||||||
// 检查配置文件内容
|
// 检查配置文件内容
|
||||||
|
info!("校验配置文件内容...");
|
||||||
config.check();
|
config.check();
|
||||||
config
|
config
|
||||||
});
|
});
|
||||||
@@ -62,43 +64,50 @@ impl Config {
|
|||||||
let mut ok = true;
|
let mut ok = true;
|
||||||
if self.favorite_list.is_empty() {
|
if self.favorite_list.is_empty() {
|
||||||
ok = false;
|
ok = false;
|
||||||
error!("No favorite list found, program won't do anything");
|
error!("未设置需监听的收藏夹,程序空转没有意义");
|
||||||
}
|
}
|
||||||
for path in self.favorite_list.values() {
|
for path in self.favorite_list.values() {
|
||||||
if !path.is_absolute() {
|
if !path.is_absolute() {
|
||||||
ok = false;
|
ok = false;
|
||||||
error!("Path in favorite list must be absolute: {}", path.display());
|
error!("收藏夹保存的路径应为绝对路径,检测到: {}", path.display());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !self.upper_path.is_absolute() {
|
if !self.upper_path.is_absolute() {
|
||||||
ok = false;
|
ok = false;
|
||||||
error!("Upper face path must be absolute");
|
error!("up 主头像保存的路径应为绝对路径");
|
||||||
}
|
}
|
||||||
if self.video_name.is_empty() {
|
if self.video_name.is_empty() {
|
||||||
ok = false;
|
ok = false;
|
||||||
error!("No video name template found");
|
error!("未设置 video_name 模板");
|
||||||
}
|
}
|
||||||
if self.page_name.is_empty() {
|
if self.page_name.is_empty() {
|
||||||
ok = false;
|
ok = false;
|
||||||
error!("No page name template found");
|
error!("未设置 page_name 模板");
|
||||||
}
|
}
|
||||||
let credential = self.credential.load();
|
let credential = self.credential.load();
|
||||||
if let Some(credential) = credential.as_deref() {
|
match credential.as_deref() {
|
||||||
if credential.sessdata.is_empty()
|
Some(credential) => {
|
||||||
|| credential.bili_jct.is_empty()
|
if credential.sessdata.is_empty()
|
||||||
|| credential.buvid3.is_empty()
|
|| credential.bili_jct.is_empty()
|
||||||
|| credential.dedeuserid.is_empty()
|
|| credential.buvid3.is_empty()
|
||||||
|| credential.ac_time_value.is_empty()
|
|| credential.dedeuserid.is_empty()
|
||||||
{
|
|| credential.ac_time_value.is_empty()
|
||||||
ok = false;
|
{
|
||||||
error!("Credential is incomplete");
|
ok = false;
|
||||||
|
error!("Credential 信息不完整,请确保填写完整");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
ok = false;
|
||||||
|
error!("未设置 Credential 信息");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
warn!("No credential found, can't access high quality video");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
panic!("Config in {} is invalid", CONFIG_DIR.join("config.toml").display());
|
panic!(
|
||||||
|
"位于 {} 的配置文件不合法,请参考提示信息修复后继续运行",
|
||||||
|
CONFIG_DIR.join("config.toml").display()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ use crate::core::utils::{
|
|||||||
create_video_pages, create_videos, exist_labels, filter_unfilled_videos, handle_favorite_info, total_video_count,
|
create_video_pages, create_videos, exist_labels, filter_unfilled_videos, handle_favorite_info, total_video_count,
|
||||||
};
|
};
|
||||||
use crate::downloader::Downloader;
|
use crate::downloader::Downloader;
|
||||||
use crate::error::DownloadAbortError;
|
use crate::error::{DownloadAbortError, ProcessPageError};
|
||||||
|
|
||||||
/// 处理某个收藏夹,首先刷新收藏夹信息,然后下载收藏夹中未下载成功的视频
|
/// 处理某个收藏夹,首先刷新收藏夹信息,然后下载收藏夹中未下载成功的视频
|
||||||
pub async fn process_favorite_list(
|
pub async fn process_favorite_list(
|
||||||
@@ -48,7 +48,7 @@ pub async fn refresh_favorite_list(
|
|||||||
let bili_favorite_list = FavoriteList::new(bili_client, fid.to_owned());
|
let bili_favorite_list = FavoriteList::new(bili_client, fid.to_owned());
|
||||||
let favorite_list_info = bili_favorite_list.get_info().await?;
|
let favorite_list_info = bili_favorite_list.get_info().await?;
|
||||||
let favorite_model = handle_favorite_info(&favorite_list_info, path, connection).await?;
|
let favorite_model = handle_favorite_info(&favorite_list_info, path, connection).await?;
|
||||||
info!("Scan the favorite: {fid}.");
|
info!("开始扫描收藏夹: {} - {}...", favorite_model.f_id, favorite_model.name);
|
||||||
// 每十个视频一组,避免太多的数据库操作
|
// 每十个视频一组,避免太多的数据库操作
|
||||||
let video_stream = bili_favorite_list.into_video_stream().chunks(10);
|
let video_stream = bili_favorite_list.into_video_stream().chunks(10);
|
||||||
pin_mut!(video_stream);
|
pin_mut!(video_stream);
|
||||||
@@ -64,12 +64,15 @@ pub async fn refresh_favorite_list(
|
|||||||
// 将视频信息写入数据库
|
// 将视频信息写入数据库
|
||||||
create_videos(&videos_info, &favorite_model, connection).await?;
|
create_videos(&videos_info, &favorite_model, connection).await?;
|
||||||
if should_break {
|
if should_break {
|
||||||
info!("Reach the last processed processed position, break..");
|
info!("到达上一次处理的位置,提前中止");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let total_count = total_video_count(&favorite_model, connection).await? - total_count;
|
let total_count = total_video_count(&favorite_model, connection).await? - total_count;
|
||||||
info!("Scan the favorite: {fid} done, got {got_count} videos, {total_count} new videos.");
|
info!(
|
||||||
|
"扫描收藏夹: {} - {} 完成, 获取了 {} 条视频, 其中有 {} 条新视频",
|
||||||
|
favorite_model.f_id, favorite_model.name, got_count, total_count
|
||||||
|
);
|
||||||
Ok(favorite_model)
|
Ok(favorite_model)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,14 +82,20 @@ pub async fn fetch_video_details(
|
|||||||
favorite_model: favorite::Model,
|
favorite_model: favorite::Model,
|
||||||
connection: &DatabaseConnection,
|
connection: &DatabaseConnection,
|
||||||
) -> Result<favorite::Model> {
|
) -> Result<favorite::Model> {
|
||||||
info!("start to fetch video details in favorite: {}", favorite_model.f_id);
|
info!(
|
||||||
|
"开始获取收藏夹 {} - {} 的视频与分页信息...",
|
||||||
|
favorite_model.f_id, favorite_model.name
|
||||||
|
);
|
||||||
let videos_model = filter_unfilled_videos(&favorite_model, connection).await?;
|
let videos_model = filter_unfilled_videos(&favorite_model, connection).await?;
|
||||||
for video_model in videos_model {
|
for video_model in videos_model {
|
||||||
let bili_video = Video::new(bili_client, video_model.bvid.clone());
|
let bili_video = Video::new(bili_client, video_model.bvid.clone());
|
||||||
let tags = match bili_video.get_tags().await {
|
let tags = match bili_video.get_tags().await {
|
||||||
Ok(tags) => tags,
|
Ok(tags) => tags,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("failed to get tags for video: {}, {}", &video_model.bvid, e);
|
error!(
|
||||||
|
"获取视频 {} - {} 的标签失败,错误为:{}",
|
||||||
|
&video_model.bvid, &video_model.name, e
|
||||||
|
);
|
||||||
if let Some(BiliError::RequestFailed(code, _)) = e.downcast_ref::<BiliError>() {
|
if let Some(BiliError::RequestFailed(code, _)) = e.downcast_ref::<BiliError>() {
|
||||||
if *code == -404 {
|
if *code == -404 {
|
||||||
let mut video_active_model: video::ActiveModel = video_model.into();
|
let mut video_active_model: video::ActiveModel = video_model.into();
|
||||||
@@ -100,7 +109,10 @@ pub async fn fetch_video_details(
|
|||||||
let pages_info = match bili_video.get_pages().await {
|
let pages_info = match bili_video.get_pages().await {
|
||||||
Ok(pages) => pages,
|
Ok(pages) => pages,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("failed to get pages for video: {}, {}", &video_model.bvid, e);
|
error!(
|
||||||
|
"获取视频 {} - {} 的分页信息失败,错误为:{}",
|
||||||
|
&video_model.bvid, &video_model.name, e
|
||||||
|
);
|
||||||
if let Some(BiliError::RequestFailed(code, _)) = e.downcast_ref::<BiliError>() {
|
if let Some(BiliError::RequestFailed(code, _)) = e.downcast_ref::<BiliError>() {
|
||||||
if *code == -404 {
|
if *code == -404 {
|
||||||
let mut video_active_model: video::ActiveModel = video_model.into();
|
let mut video_active_model: video::ActiveModel = video_model.into();
|
||||||
@@ -121,7 +133,10 @@ pub async fn fetch_video_details(
|
|||||||
video_active_model.save(&txn).await?;
|
video_active_model.save(&txn).await?;
|
||||||
txn.commit().await?;
|
txn.commit().await?;
|
||||||
}
|
}
|
||||||
info!("fetch video details in favorite: {} done.", favorite_model.f_id);
|
info!(
|
||||||
|
"获取收藏夹 {} - {} 的视频与分页信息完成",
|
||||||
|
favorite_model.f_id, favorite_model.name
|
||||||
|
);
|
||||||
Ok(favorite_model)
|
Ok(favorite_model)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +146,10 @@ pub async fn download_unprocessed_videos(
|
|||||||
favorite_model: favorite::Model,
|
favorite_model: favorite::Model,
|
||||||
connection: &DatabaseConnection,
|
connection: &DatabaseConnection,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
info!("start to download videos in favorite: {}", favorite_model.f_id);
|
info!(
|
||||||
|
"开始下载收藏夹: {} - {} 中所有未处理过的视频...",
|
||||||
|
favorite_model.f_id, favorite_model.name
|
||||||
|
);
|
||||||
let unhandled_videos_pages = unhandled_videos_pages(&favorite_model, connection).await?;
|
let unhandled_videos_pages = unhandled_videos_pages(&favorite_model, connection).await?;
|
||||||
// 对于视频,允许五个同时下载(视频内还有分页、不同分页还有多种下载任务)
|
// 对于视频,允许五个同时下载(视频内还有分页、不同分页还有多种下载任务)
|
||||||
let semaphore = Semaphore::new(5);
|
let semaphore = Semaphore::new(5);
|
||||||
@@ -164,7 +182,7 @@ pub async fn download_unprocessed_videos(
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.downcast_ref::<DownloadAbortError>().is_some() {
|
if e.downcast_ref::<DownloadAbortError>().is_some() {
|
||||||
warn!("{e}");
|
error!("下载视频时触发风控,将终止收藏夹下所有下载任务,等待下一轮执行");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,7 +195,10 @@ pub async fn download_unprocessed_videos(
|
|||||||
if !models.is_empty() {
|
if !models.is_empty() {
|
||||||
update_videos_model(models, connection).await?;
|
update_videos_model(models, connection).await?;
|
||||||
}
|
}
|
||||||
info!("download videos in favorite: {} done.", favorite_model.f_id);
|
info!(
|
||||||
|
"下载收藏夹: {} - {} 中未处理过的视频完成",
|
||||||
|
favorite_model.f_id, favorite_model.name
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,20 +273,20 @@ pub async fn download_video_pages(
|
|||||||
results
|
results
|
||||||
.iter()
|
.iter()
|
||||||
.take(4)
|
.take(4)
|
||||||
.zip(["poster", "video nfo", "upper face", "upper nfo"])
|
.zip(["封面", "视频 nfo", "up 主头像", "up 主 nfo"])
|
||||||
.for_each(|(res, task_name)| {
|
.for_each(|(res, task_name)| match res {
|
||||||
if res.is_err() {
|
Ok(_) => info!(
|
||||||
error!(
|
"处理视频 {} - {} 的 {} 成功",
|
||||||
"Video {} {} failed: {}",
|
&video_model.bvid, &video_model.name, task_name
|
||||||
&video_model.bvid,
|
),
|
||||||
task_name,
|
Err(e) => error!(
|
||||||
res.as_ref().unwrap_err()
|
"处理视频 {} - {} 的 {} 失败: {}",
|
||||||
);
|
&video_model.bvid, &video_model.name, task_name, e
|
||||||
}
|
),
|
||||||
});
|
});
|
||||||
if let Err(e) = results.into_iter().nth(4).unwrap() {
|
if let Err(e) = results.into_iter().nth(4).unwrap() {
|
||||||
if let Ok(e) = e.downcast::<DownloadAbortError>() {
|
if let Ok(e) = e.downcast::<DownloadAbortError>() {
|
||||||
bail!(e);
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut video_active_model: video::ActiveModel = video_model.into();
|
let mut video_active_model: video::ActiveModel = video_model.into();
|
||||||
@@ -291,14 +312,14 @@ pub async fn dispatch_download_page(
|
|||||||
.map(|page_model| download_page(bili_client, video_model, page_model, &child_semaphore, downloader))
|
.map(|page_model| download_page(bili_client, video_model, page_model, &child_semaphore, downloader))
|
||||||
.collect::<FuturesUnordered<_>>();
|
.collect::<FuturesUnordered<_>>();
|
||||||
let mut models = Vec::with_capacity(10);
|
let mut models = Vec::with_capacity(10);
|
||||||
let mut should_error = false;
|
let (mut should_error, mut is_break) = (false, false);
|
||||||
while let Some(res) = tasks.next().await {
|
while let Some(res) = tasks.next().await {
|
||||||
match res {
|
match res {
|
||||||
Ok(model) => {
|
Ok(model) => {
|
||||||
if let Set(status) = model.download_status {
|
if let Set(status) = model.download_status {
|
||||||
let status = PageStatus::new(status);
|
let status = PageStatus::new(status);
|
||||||
if status.should_run().iter().any(|v| *v) {
|
if status.should_run().iter().any(|v| *v) {
|
||||||
// 有一个分页没下载完成,就应该将视频本身标记为未完成
|
// 有一个分页没变成终止状态(即下载成功或者重试次数达到限制),就应该向上层传递 Error
|
||||||
should_error = true;
|
should_error = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,7 +327,7 @@ pub async fn dispatch_download_page(
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.downcast_ref::<DownloadAbortError>().is_some() {
|
if e.downcast_ref::<DownloadAbortError>().is_some() {
|
||||||
warn!("{e}");
|
is_break = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,7 +340,19 @@ pub async fn dispatch_download_page(
|
|||||||
update_pages_model(models, connection).await?;
|
update_pages_model(models, connection).await?;
|
||||||
}
|
}
|
||||||
if should_error {
|
if should_error {
|
||||||
bail!("Some pages failed to download");
|
if is_break {
|
||||||
|
error!(
|
||||||
|
"下载视频 {} - {} 的分页时触发风控,将异常向上传递...",
|
||||||
|
&video_model.bvid, &video_model.name
|
||||||
|
);
|
||||||
|
bail!(DownloadAbortError());
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
"下载视频 {} - {} 的分页时出现了错误,将在下一轮尝试重新处理",
|
||||||
|
&video_model.bvid, &video_model.name
|
||||||
|
);
|
||||||
|
bail!(ProcessPageError());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -418,22 +451,21 @@ pub async fn download_page(
|
|||||||
status.update_status(&results);
|
status.update_status(&results);
|
||||||
results
|
results
|
||||||
.iter()
|
.iter()
|
||||||
.zip(["poster", "video", "nfo", "danmaku"])
|
.zip(["封面", "视频", "视频 nfo", "弹幕"])
|
||||||
.for_each(|(res, task_name)| {
|
.for_each(|(res, task_name)| match res {
|
||||||
if res.is_err() {
|
Ok(_) => info!(
|
||||||
error!(
|
"处理视频 {} - {} 第 {} 页的 {} 成功",
|
||||||
"Video {} page {} {} failed: {}",
|
&video_model.bvid, &video_model.name, page_model.pid, task_name
|
||||||
&video_model.bvid,
|
),
|
||||||
page_model.pid,
|
Err(e) => error!(
|
||||||
task_name,
|
"处理视频 {} - {} 第 {} 页的 {} 失败: {}",
|
||||||
res.as_ref().unwrap_err()
|
&video_model.bvid, &video_model.name, page_model.pid, task_name, e
|
||||||
);
|
),
|
||||||
}
|
|
||||||
});
|
});
|
||||||
// 查看下载视频的状态,该状态会影响上层是否 break
|
// 查看下载视频的状态,该状态会影响上层是否 break
|
||||||
if let Err(e) = results.into_iter().nth(1).unwrap() {
|
if let Err(e) = results.into_iter().nth(1).unwrap() {
|
||||||
if let Ok(e) = e.downcast::<DownloadAbortError>() {
|
if let Ok(e) = e.downcast::<DownloadAbortError>() {
|
||||||
bail!(e);
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut page_active_model: page::ActiveModel = page_model.into();
|
let mut page_active_model: page::ActiveModel = page_model.into();
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ impl PageStatus {
|
|||||||
|
|
||||||
pub fn update_status(&mut self, result: &[Result<()>]) {
|
pub fn update_status(&mut self, result: &[Result<()>]) {
|
||||||
assert!(result.len() == 4, "PageStatus should have 4 status");
|
assert!(result.len() == 4, "PageStatus should have 4 status");
|
||||||
self.0.update_status(&result)
|
self.0.update_status(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
#[error("Bilibili api request too frequently, abort all tasks and try again later")]
|
#[error("Request too frequently")]
|
||||||
pub struct DownloadAbortError();
|
pub struct DownloadAbortError();
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
#[error("Process page error")]
|
||||||
|
pub struct ProcessPageError();
|
||||||
|
|||||||
11
src/main.rs
11
src/main.rs
@@ -26,20 +26,19 @@ async fn main() -> ! {
|
|||||||
loop {
|
loop {
|
||||||
if anchor != chrono::Local::now().date_naive() {
|
if anchor != chrono::Local::now().date_naive() {
|
||||||
if let Err(e) = bili_client.check_refresh().await {
|
if let Err(e) = bili_client.check_refresh().await {
|
||||||
error!("Error: {e}");
|
error!("检查刷新 Credential 遇到错误:{e},等待下一轮执行");
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(CONFIG.interval)).await;
|
tokio::time::sleep(std::time::Duration::from_secs(CONFIG.interval)).await;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
anchor = chrono::Local::now().date_naive();
|
anchor = chrono::Local::now().date_naive();
|
||||||
}
|
}
|
||||||
for (fid, path) in &CONFIG.favorite_list {
|
for (fid, path) in &CONFIG.favorite_list {
|
||||||
let res = process_favorite_list(&bili_client, fid, path, &connection).await;
|
if let Err(e) = process_favorite_list(&bili_client, fid, path, &connection).await {
|
||||||
if let Err(e) = res {
|
// 可预期的错误都被内部处理了,这里漏出来应该是大问题
|
||||||
error!("Error: {e}");
|
error!("处理收藏夹 {fid} 时遇到非预期的错误:{e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info!("All favorite lists have been processed, wait for next round.");
|
info!("所有收藏夹处理完毕,等待下一轮执行");
|
||||||
|
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(CONFIG.interval)).await;
|
tokio::time::sleep(std::time::Duration::from_secs(CONFIG.interval)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user