From 0e5778b6cbf040ee868ee1845ab5da041f1a2573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=80=E1=B4=8D=E1=B4=9B=E1=B4=8F=E1=B4=80=E1=B4=87?= =?UTF-8?q?=CA=80?= Date: Fri, 21 Aug 2026 13:17:12 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E5=90=8D=E7=A7=B0=E8=A7=A3=E6=9E=90=20(#742)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/bili_sync/src/bilibili/video.rs | 16 ++++++++++++---- crates/bili_sync/src/workflow.rs | 17 +++++++++++++++-- crates/bili_sync_migration/src/lib.rs | 2 ++ ...0821_025000_mark_empty_tags_for_refetch.rs | 19 +++++++++++++++++++ 4 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 crates/bili_sync_migration/src/m20260821_025000_mark_empty_tags_for_refetch.rs diff --git a/crates/bili_sync/src/bilibili/video.rs b/crates/bili_sync/src/bilibili/video.rs index 2090485..b01b66f 100644 --- a/crates/bili_sync/src/bilibili/video.rs +++ b/crates/bili_sync/src/bilibili/video.rs @@ -1,4 +1,4 @@ -use anyhow::{Context, Result, ensure}; +use anyhow::{Context, Result, bail, ensure}; use futures::TryStreamExt; use futures::stream::FuturesUnordered; use prost::Message; @@ -101,12 +101,20 @@ impl<'a> Video<'a> { .json::() .await? .validate()?; - Ok(res["data"] + res["data"] .as_array_mut() .context("tags is not an array")? .iter_mut() - .filter_map(|v| if let Value::String(s) = v.take() { Some(s) } else { None }) - .collect()) + .map(|v| { + if let Some(tag) = v.get_mut("tag_name") + && let Value::String(s) = tag.take() + { + Ok(s) + } else { + bail!("tag_name is not a string"); + } + }) + .collect() } pub async fn get_danmaku_writer(&self, page: &'a PageInfo) -> Result> { diff --git a/crates/bili_sync/src/workflow.rs b/crates/bili_sync/src/workflow.rs index e41cc26..75e7724 100644 --- a/crates/bili_sync/src/workflow.rs +++ b/crates/bili_sync/src/workflow.rs @@ -219,7 +219,7 @@ pub async fn download_unprocessed_videos( let unhandled_videos_pages = filter_unhandled_video_pages(video_source.filter_expr(), connection).await?; let mut assigned_upper_ids = HashSet::new(); let tasks = stream::iter(unhandled_videos_pages) - .map(|(video_model, pages_model)| { + .map(|(mut video_model, pages_model)| { // 这里按理说是可以直接拿到 assigned_uppers 的,但rust 会错误地认为它引用了 local variable // 导致编译出错,暂时先这样单独提取出一个 owned 的 upper id 列表,再在任务内部筛选 let task_uids = video_model @@ -227,7 +227,19 @@ pub async fn download_unprocessed_videos( .map(|u| u.mid) .filter(|uid| assigned_upper_ids.insert(*uid)) .collect::>(); - download_video_pages(video_model, pages_model, task_uids, cx) + async move { + // b 站接口调整导致一段时间内的 tag 被错误保存为 [],迁移文件会将当前的 [] 更新为 None + // 此处在下载前发现 None 的 tag 尝试重新填充以修复错误 + if video_model.tags.is_none() { + video_model.tags = Some( + Video::new(cx.bili_client, video_model.bvid.as_str(), &cx.config.credential) + .get_tags() + .await? + .into(), + ); + } + download_video_pages(video_model, pages_model, task_uids, cx).await + } }) .buffer_unordered(config.concurrent_limit.video); let mut risk_control_related_error = None; @@ -359,6 +371,7 @@ pub async fn download_video_pages( } } let mut video_active_model: video::ActiveModel = video_model.into(); + video_active_model.tags.reset(); video_active_model.download_status = Set(status.into()); video_active_model.path = Set(base_path.to_string_lossy().to_string()); Ok(video_active_model) diff --git a/crates/bili_sync_migration/src/lib.rs b/crates/bili_sync_migration/src/lib.rs index 8d80324..1202608 100644 --- a/crates/bili_sync_migration/src/lib.rs +++ b/crates/bili_sync_migration/src/lib.rs @@ -12,6 +12,7 @@ mod m20250903_094454_add_rule_and_should_download; mod m20251009_123713_add_use_dynamic_api; mod m20260324_055217_add_staff; mod m20260712_123205_add_filter_option; +mod m20260821_025000_mark_empty_tags_for_refetch; pub struct Migrator; @@ -31,6 +32,7 @@ impl MigratorTrait for Migrator { Box::new(m20251009_123713_add_use_dynamic_api::Migration), Box::new(m20260324_055217_add_staff::Migration), Box::new(m20260712_123205_add_filter_option::Migration), + Box::new(m20260821_025000_mark_empty_tags_for_refetch::Migration), ] } } diff --git a/crates/bili_sync_migration/src/m20260821_025000_mark_empty_tags_for_refetch.rs b/crates/bili_sync_migration/src/m20260821_025000_mark_empty_tags_for_refetch.rs new file mode 100644 index 0000000..8d22ad5 --- /dev/null +++ b/crates/bili_sync_migration/src/m20260821_025000_mark_empty_tags_for_refetch.rs @@ -0,0 +1,19 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared("UPDATE video SET tags = NULL WHERE tags = '[]'") + .await?; + Ok(()) + } + + async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> { + Ok(()) + } +}