feat: 支持忽略常见错误的通知

This commit is contained in:
amtoaer
2026-06-08 18:31:21 +08:00
parent 6d8bf14880
commit d748b2bd0f
8 changed files with 60 additions and 7 deletions

View File

@@ -2,10 +2,14 @@ use thiserror::Error;
#[derive(Error, Debug, Clone)]
pub enum BiliError {
#[error("response missing 'code' or 'message' field, full response: {0}")]
#[error("response missing 'code' field, full response: {0}")]
InvalidResponse(String),
#[error("API returned error code {0}, full response: {1}")]
ErrorResponse(i64, String),
#[error("API returned error code {code}, full response: {response}")]
ErrorResponse {
code: i64,
message: Option<String>,
response: String,
},
#[error("risk control triggered by server, full response: {0}")]
RiskControlOccurred(String),
#[error("invalid HTTP response code {0}, reason: {1}")]
@@ -21,4 +25,15 @@ impl BiliError {
BiliError::RiskControlOccurred(_) | BiliError::VideoStreamsEmpty | BiliError::InvalidStatusCode(_, _)
)
}
pub fn is_common_error(&self) -> bool {
matches!(
self,
BiliError::ErrorResponse {
code: -503,
message,
..
} if message.as_ref().is_some_and(|m| m == "服务暂不可用")
)
}
}

View File

@@ -60,10 +60,18 @@ impl Validate for serde_json::Value {
let code = self["code"]
.as_i64()
.with_context(|| BiliError::InvalidResponse(self.to_string()))?;
let message = self["message"].as_str().map(ToOwned::to_owned);
if code == -352 || !self["data"]["v_voucher"].is_null() {
bail!(BiliError::RiskControlOccurred(self.to_string()));
}
ensure!(code == 0, BiliError::ErrorResponse(code, self.to_string()));
ensure!(
code == 0,
BiliError::ErrorResponse {
code,
message,
response: self.to_string(),
}
);
Ok(self)
}
}

View File

@@ -38,6 +38,8 @@ pub struct Config {
pub page_name: String,
#[serde(default)]
pub notifiers: Option<Arc<Vec<Notifier>>>,
#[serde(default)]
pub ignore_common_errors: bool,
#[serde(default = "default_favorite_path")]
pub favorite_default_path: String,
#[serde(default = "default_collection_path")]
@@ -124,6 +126,7 @@ impl Default for Config {
video_name: "{{title}}".to_owned(),
page_name: "{{bvid}}".to_owned(),
notifiers: None,
ignore_common_errors: false,
favorite_default_path: default_favorite_path(),
collection_default_path: default_collection_path(),
submission_default_path: default_submission_path(),

View File

@@ -140,6 +140,7 @@ impl DownloadTaskManager {
&initial_config,
&cx.bili_client,
format!("初始化视频下载任务失败:{:#}", err),
&err,
);
None
}
@@ -193,6 +194,7 @@ impl DownloadTaskManager {
&initial_config,
&cx.bili_client,
format!("重载视频下载任务失败:{:#}", err),
&err,
);
None
}
@@ -234,6 +236,7 @@ impl DownloadTaskManager {
&config,
&cx.bili_client,
format!("本轮凭据检查与刷新任务执行遇到错误:{:#}", e),
&e,
);
}
}
@@ -285,6 +288,7 @@ impl DownloadTaskManager {
&config,
&cx.bili_client,
format!("本轮视频下载任务执行遇到错误:{:#}", e),
&e,
);
}
}
@@ -360,6 +364,7 @@ async fn download_video(
config,
&bili_client,
format!("处理 {} 时遇到错误:{:#},跳过该视频源", display_name, e),
&e,
);
if let Ok(e) = e.downcast::<BiliError>()
&& e.is_risk_control_related()

View File

@@ -1,4 +1,6 @@
use crate::bilibili::BiliClient;
use anyhow::Error;
use crate::bilibili::{BiliClient, BiliError};
use crate::config::Config;
use crate::notifier::{Message, NotifierAllExt};
@@ -12,8 +14,17 @@ pub fn notify(config: &Config, bili_client: &BiliClient, msg: impl Into<Message<
}
}
pub fn error_and_notify(config: &Config, bili_client: &BiliClient, msg: String) {
pub fn error_and_notify(config: &Config, bili_client: &BiliClient, msg: String, error: &Error) {
error!("{msg}");
if config.ignore_common_errors
&& error.chain().any(|cause| {
cause
.downcast_ref::<BiliError>()
.is_some_and(BiliError::is_common_error)
})
{
return;
}
if let Some(notifiers) = &config.notifiers
&& !notifiers.is_empty()
{

View File

@@ -140,7 +140,7 @@ pub async fn fetch_video_details(
"获取视频 {} - {} 的详细信息失败,错误为:{:#}",
&video_model.bvid, &video_model.name, e
);
if let Some(BiliError::ErrorResponse(-404, _)) = e.downcast_ref::<BiliError>() {
if let Some(BiliError::ErrorResponse { code: -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?;

View File

@@ -330,6 +330,7 @@ export interface Config {
video_name: string;
page_name: string;
notifiers: Notifier[] | null;
ignore_common_errors: boolean;
favorite_default_path: string;
collection_default_path: string;
submission_default_path: string;

View File

@@ -792,6 +792,16 @@
<!-- 通知设置 -->
<Tabs.Content value="notifiers" class="mt-6 space-y-6">
<div class="space-y-4">
<div class="flex items-center justify-between rounded-lg border p-4">
<div class="space-y-1">
<Label for="ignore-common-errors">忽略常见错误</Label>
<p class="text-muted-foreground text-sm">
b 站接口频繁出现 -503 服务暂不可用,在通知器内通知容易刷屏,开启该选项以忽略此错误通知
</p>
</div>
<Switch id="ignore-common-errors" bind:checked={formData.ignore_common_errors} />
</div>
<div class="flex items-center justify-between">
<div>
<h3 class="text-lg font-semibold">通知器管理</h3>