From c7e0d31811aacd5008a17a7ad7c58bd192c02ea7 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: Tue, 14 Oct 2025 16:32:40 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E7=A7=BB=E9=99=A4=E6=97=A7=E7=89=88?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E7=9A=84=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E9=80=BB=E8=BE=91=20(#501)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/bili_sync/src/config/current.rs | 23 --- crates/bili_sync/src/config/item.rs | 9 -- crates/bili_sync/src/config/legacy.rs | 134 ------------------ crates/bili_sync/src/config/mod.rs | 2 - .../bili_sync/src/config/versioned_config.rs | 32 ++--- crates/bili_sync/src/utils/model.rs | 70 +-------- 6 files changed, 16 insertions(+), 254 deletions(-) delete mode 100644 crates/bili_sync/src/config/legacy.rs diff --git a/crates/bili_sync/src/config/current.rs b/crates/bili_sync/src/config/current.rs index 7dc8016..3465df7 100644 --- a/crates/bili_sync/src/config/current.rs +++ b/crates/bili_sync/src/config/current.rs @@ -7,7 +7,6 @@ use serde::{Deserialize, Serialize}; use validator::Validate; use crate::bilibili::{Credential, DanmakuOption, FilterOption}; -use crate::config::LegacyConfig; use crate::config::default::{default_auth_token, default_bind_address, default_time_format}; use crate::config::item::{ConcurrentLimit, NFOTimeType, SkipOption}; use crate::utils::model::{load_db_config, save_db_config}; @@ -109,25 +108,3 @@ impl Default for Config { } } } - -impl From for Config { - fn from(legacy: LegacyConfig) -> Self { - Self { - auth_token: legacy.auth_token, - bind_address: legacy.bind_address, - credential: legacy.credential, - filter_option: legacy.filter_option, - danmaku_option: legacy.danmaku_option, - skip_option: SkipOption::default(), - video_name: legacy.video_name, - page_name: legacy.page_name, - interval: legacy.interval, - upper_path: legacy.upper_path, - nfo_time_type: legacy.nfo_time_type, - concurrent_limit: legacy.concurrent_limit, - time_format: legacy.time_format, - cdn_sorting: legacy.cdn_sorting, - version: 0, - } - } -} diff --git a/crates/bili_sync/src/config/item.rs b/crates/bili_sync/src/config/item.rs index df25533..fb76f9d 100644 --- a/crates/bili_sync/src/config/item.rs +++ b/crates/bili_sync/src/config/item.rs @@ -1,17 +1,8 @@ -use std::path::PathBuf; - use anyhow::Result; use serde::{Deserialize, Serialize}; use crate::utils::filenamify::filenamify; -/// 稍后再看的配置 -#[derive(Serialize, Deserialize, Default)] -pub struct WatchLaterConfig { - pub enabled: bool, - pub path: PathBuf, -} - /// NFO 文件使用的时间类型 #[derive(Serialize, Deserialize, Default, Clone)] #[serde(rename_all = "lowercase")] diff --git a/crates/bili_sync/src/config/legacy.rs b/crates/bili_sync/src/config/legacy.rs deleted file mode 100644 index fdfd390..0000000 --- a/crates/bili_sync/src/config/legacy.rs +++ /dev/null @@ -1,134 +0,0 @@ -use std::collections::HashMap; -use std::path::{Path, PathBuf}; - -use anyhow::Result; -use sea_orm::DatabaseConnection; -use serde::de::{Deserializer, MapAccess, Visitor}; -use serde::ser::SerializeMap; -use serde::{Deserialize, Serialize}; - -use crate::bilibili::{CollectionItem, CollectionType, Credential, DanmakuOption, FilterOption}; -use crate::config::Config; -use crate::config::default::{default_auth_token, default_bind_address, default_time_format}; -use crate::config::item::{ConcurrentLimit, NFOTimeType, WatchLaterConfig}; -use crate::utils::model::migrate_legacy_config; - -#[derive(Serialize, Deserialize)] -pub struct LegacyConfig { - #[serde(default = "default_auth_token")] - pub auth_token: String, - #[serde(default = "default_bind_address")] - pub bind_address: String, - pub credential: Credential, - pub filter_option: FilterOption, - #[serde(default)] - pub danmaku_option: DanmakuOption, - pub favorite_list: HashMap, - #[serde( - default, - serialize_with = "serialize_collection_list", - deserialize_with = "deserialize_collection_list" - )] - pub collection_list: HashMap, - #[serde(default)] - pub submission_list: HashMap, - #[serde(default)] - pub watch_later: WatchLaterConfig, - pub video_name: String, - pub page_name: String, - pub interval: u64, - pub upper_path: PathBuf, - #[serde(default)] - pub nfo_time_type: NFOTimeType, - #[serde(default)] - pub concurrent_limit: ConcurrentLimit, - #[serde(default = "default_time_format")] - pub time_format: String, - #[serde(default)] - pub cdn_sorting: bool, -} - -impl LegacyConfig { - async fn load_from_file(path: &Path) -> Result { - let legacy_config_str = tokio::fs::read_to_string(path).await?; - Ok(toml::from_str(&legacy_config_str)?) - } - - pub async fn migrate_from_file(path: &Path, connection: &DatabaseConnection) -> Result { - let legacy_config = Self::load_from_file(path).await?; - migrate_legacy_config(&legacy_config, connection).await?; - Ok(legacy_config.into()) - } -} - -/* -后面是用于自定义 Collection 的序列化、反序列化的样板代码 -*/ -pub(super) fn serialize_collection_list( - collection_list: &HashMap, - serializer: S, -) -> Result -where - S: serde::Serializer, -{ - let mut map = serializer.serialize_map(Some(collection_list.len()))?; - for (k, v) in collection_list { - let prefix = match k.collection_type { - CollectionType::Series => "series", - CollectionType::Season => "season", - }; - map.serialize_entry(&[prefix, &k.mid, &k.sid].join(":"), v)?; - } - map.end() -} - -pub(super) fn deserialize_collection_list<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - struct CollectionListVisitor; - - impl<'de> Visitor<'de> for CollectionListVisitor { - type Value = HashMap; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a map of collection list") - } - - fn visit_map(self, mut map: A) -> Result - where - A: MapAccess<'de>, - { - let mut collection_list = HashMap::new(); - while let Some((key, value)) = map.next_entry::()? { - let collection_item = match key.split(':').collect::>().as_slice() { - [prefix, mid, sid] => { - let collection_type = match *prefix { - "series" => CollectionType::Series, - "season" => CollectionType::Season, - _ => { - return Err(serde::de::Error::custom( - "invalid collection type, should be series or season", - )); - } - }; - CollectionItem { - mid: mid.to_string(), - sid: sid.to_string(), - collection_type, - } - } - _ => { - return Err(serde::de::Error::custom( - "invalid collection key, should be series:mid:sid or season:mid:sid", - )); - } - }; - collection_list.insert(collection_item, value); - } - Ok(collection_list) - } - } - - deserializer.deserialize_map(CollectionListVisitor) -} diff --git a/crates/bili_sync/src/config/mod.rs b/crates/bili_sync/src/config/mod.rs index dc7b9fc..2f56fc7 100644 --- a/crates/bili_sync/src/config/mod.rs +++ b/crates/bili_sync/src/config/mod.rs @@ -3,7 +3,6 @@ mod current; mod default; mod handlebar; mod item; -mod legacy; mod versioned_cache; mod versioned_config; @@ -11,6 +10,5 @@ pub use crate::config::args::{ARGS, version}; pub use crate::config::current::{CONFIG_DIR, Config}; pub use crate::config::handlebar::TEMPLATE; pub use crate::config::item::{NFOTimeType, PathSafeTemplate, RateLimit, SkipOption}; -pub use crate::config::legacy::LegacyConfig; pub use crate::config::versioned_cache::VersionedCache; pub use crate::config::versioned_config::VersionedConfig; diff --git a/crates/bili_sync/src/config/versioned_config.rs b/crates/bili_sync/src/config/versioned_config.rs index 7079b1a..b8daafa 100644 --- a/crates/bili_sync/src/config/versioned_config.rs +++ b/crates/bili_sync/src/config/versioned_config.rs @@ -6,7 +6,7 @@ use sea_orm::DatabaseConnection; use tokio::sync::OnceCell; use crate::bilibili::Credential; -use crate::config::{CONFIG_DIR, Config, LegacyConfig}; +use crate::config::{CONFIG_DIR, Config}; pub static VERSIONED_CONFIG: OnceCell = OnceCell::const_new(); @@ -22,23 +22,19 @@ impl VersionedConfig { Some(Ok(config)) => config, Some(Err(e)) => bail!("解析数据库配置失败: {}", e), None => { - let config = match LegacyConfig::migrate_from_file(&CONFIG_DIR.join("config.toml"), connection).await { - Ok(config) => config, - Err(e) => { - if e.downcast_ref::() - .is_none_or(|e| e.kind() != std::io::ErrorKind::NotFound) - { - bail!("未成功读取并迁移旧版本配置:{:#}", e); - } else { - let config = Config::default(); - warn!( - "生成 auth_token:{},可使用该 token 登录 web UI,该信息仅在首次运行时打印", - config.auth_token - ); - config - } - } - }; + if CONFIG_DIR.join("config.toml").exists() { + // 数据库中没有配置,但旧版配置文件存在,说明是从 2.6.0 之前的版本直接升级的 + bail!( + "当前版本已移除配置文件的迁移逻辑,不再支持从配置文件加载配置。\n\ + 如果你正在运行 2.6.0 之前的版本,请先升级至 2.6.x 或 2.7.x,\n\ + 启动时会自动将配置文件迁移至数据库,然后再升级至最新版本。" + ); + } + let config = Config::default(); + warn!( + "生成 auth_token:{},可使用该 token 登录 web UI,该信息仅在首次运行时打印", + config.auth_token + ); config.save_to_database(connection).await?; config } diff --git a/crates/bili_sync/src/utils/model.rs b/crates/bili_sync/src/utils/model.rs index 6215906..744054e 100644 --- a/crates/bili_sync/src/utils/model.rs +++ b/crates/bili_sync/src/utils/model.rs @@ -1,13 +1,13 @@ use anyhow::{Context, Result, anyhow}; use bili_sync_entity::*; use sea_orm::ActiveValue::Set; +use sea_orm::DatabaseTransaction; use sea_orm::entity::prelude::*; use sea_orm::sea_query::{OnConflict, SimpleExpr}; -use sea_orm::{DatabaseTransaction, TransactionTrait}; use crate::adapter::{VideoSource, VideoSourceEnum}; use crate::bilibili::VideoInfo; -use crate::config::{Config, LegacyConfig}; +use crate::config::Config; use crate::utils::status::STATUS_COMPLETED; /// 筛选未填充的视频 @@ -166,69 +166,3 @@ pub async fn save_db_config(config: &Config, connection: &DatabaseConnection) -> .context("Failed to save config to database")?; Ok(()) } - -/// 迁移旧版本配置(即将所有相关联的内容设置为 enabled) -pub async fn migrate_legacy_config(config: &LegacyConfig, connection: &DatabaseConnection) -> Result<()> { - let transaction = connection.begin().await.context("Failed to begin transaction")?; - tokio::try_join!( - migrate_favorite(config, &transaction), - migrate_watch_later(config, &transaction), - migrate_submission(config, &transaction), - migrate_collection(config, &transaction) - )?; - transaction.commit().await.context("Failed to commit transaction")?; - Ok(()) -} - -async fn migrate_favorite(config: &LegacyConfig, connection: &DatabaseTransaction) -> Result<()> { - favorite::Entity::update_many() - .filter(favorite::Column::FId.is_in(config.favorite_list.keys().collect::>())) - .col_expr(favorite::Column::Enabled, Expr::value(true)) - .exec(connection) - .await - .context("Failed to migrate favorite config")?; - Ok(()) -} - -async fn migrate_watch_later(config: &LegacyConfig, connection: &DatabaseTransaction) -> Result<()> { - if config.watch_later.enabled { - watch_later::Entity::update_many() - .col_expr(watch_later::Column::Enabled, Expr::value(true)) - .exec(connection) - .await - .context("Failed to migrate watch later config")?; - } - Ok(()) -} - -async fn migrate_submission(config: &LegacyConfig, connection: &DatabaseTransaction) -> Result<()> { - submission::Entity::update_many() - .filter(submission::Column::UpperId.is_in(config.submission_list.keys().collect::>())) - .col_expr(submission::Column::Enabled, Expr::value(true)) - .exec(connection) - .await - .context("Failed to migrate submission config")?; - Ok(()) -} - -async fn migrate_collection(config: &LegacyConfig, connection: &DatabaseTransaction) -> Result<()> { - let tuples: Vec<(i64, i64, i32)> = config - .collection_list - .keys() - .filter_map(|key| Some((key.sid.parse().ok()?, key.mid.parse().ok()?, key.collection_type.into()))) - .collect(); - collection::Entity::update_many() - .filter( - Expr::tuple([ - Expr::column(collection::Column::SId), - Expr::column(collection::Column::MId), - Expr::column(collection::Column::Type), - ]) - .in_tuples(tuples), - ) - .col_expr(collection::Column::Enabled, Expr::value(true)) - .exec(connection) - .await - .context("Failed to migrate collection config")?; - Ok(()) -}