Compare commits

..

5 Commits

Author SHA1 Message Date
amtoaer
16e14fc371 chore: 发布 bili-sync 2.4.1 2025-02-21 21:22:52 +08:00
amtoaer
b4a5dee236 ci: 使 ci 版本带有版本标签 2025-02-21 21:15:10 +08:00
ᴀᴍᴛᴏᴀᴇʀ
2b3e6f9547 chore: 程序开始时打印欢迎信息,调整日志和构建流 (#285) 2025-02-21 21:04:39 +08:00
ᴀᴍᴛᴏᴀᴇʀ
f8b93d2c76 fix: 修复配置初始化的检测 (#284) 2025-02-21 19:32:46 +08:00
ᴀᴍᴛᴏᴀᴇʀ
94462ca706 chore: 更新 rust edition 到 2024,更新依赖 (#283) 2025-02-21 17:47:49 +08:00
37 changed files with 191 additions and 180 deletions

View File

@@ -68,6 +68,8 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download Web Build Artifact
uses: actions/download-artifact@v4
with:

100
Cargo.lock generated
View File

@@ -114,9 +114,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.95"
version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4"
dependencies = [
"backtrace",
]
@@ -454,7 +454,7 @@ dependencies = [
[[package]]
name = "bili_sync"
version = "2.4.0"
version = "2.4.1"
dependencies = [
"anyhow",
"arc-swap",
@@ -490,7 +490,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
"strum",
"strum 0.27.1",
"thiserror 2.0.11",
"tokio",
"tokio-util",
@@ -504,7 +504,7 @@ dependencies = [
[[package]]
name = "bili_sync_entity"
version = "2.4.0"
version = "2.4.1"
dependencies = [
"sea-orm",
"serde_json",
@@ -512,7 +512,7 @@ dependencies = [
[[package]]
name = "bili_sync_migration"
version = "2.4.0"
version = "2.4.1"
dependencies = [
"async-std",
"sea-orm-migration",
@@ -684,9 +684,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.26"
version = "4.5.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d"
dependencies = [
"clap_builder",
"clap_derive",
@@ -694,9 +694,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.26"
version = "4.5.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c"
dependencies = [
"anstream",
"anstyle",
@@ -706,9 +706,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.24"
version = "4.5.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@@ -1352,9 +1352,9 @@ dependencies = [
[[package]]
name = "handlebars"
version = "6.3.0"
version = "6.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6b224b95c1e668ac0270325ad563b2eef1469fbbb8959bc7c692c844b813d9"
checksum = "d752747ddabc4c1a70dd28e72f2e3c218a816773e0d7faf67433f1acfa6cba7c"
dependencies = [
"derive_builder",
"log",
@@ -1957,9 +1957,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.20.2"
version = "1.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
[[package]]
name = "option-ext"
@@ -2229,9 +2229,9 @@ dependencies = [
[[package]]
name = "prost"
version = "0.13.4"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec"
checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
dependencies = [
"bytes",
"prost-derive",
@@ -2239,9 +2239,9 @@ dependencies = [
[[package]]
name = "prost-derive"
version = "0.13.4"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3"
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
dependencies = [
"anyhow",
"itertools",
@@ -2734,9 +2734,9 @@ dependencies = [
[[package]]
name = "sea-orm"
version = "1.1.4"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a93194430b419da0801f404baf3b986399d6a2a4f43bc79bc96dea83f92ca43"
checksum = "00733e5418e8ae3758cdb988c3654174e716230cc53ee2cb884207cf86a23029"
dependencies = [
"async-stream",
"async-trait",
@@ -2752,7 +2752,7 @@ dependencies = [
"serde",
"serde_json",
"sqlx",
"strum",
"strum 0.26.3",
"thiserror 1.0.63",
"time",
"tracing",
@@ -2762,9 +2762,9 @@ dependencies = [
[[package]]
name = "sea-orm-cli"
version = "1.1.4"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e6e0e741bfdf434e6f6aadab156ba4d439e78c9449048698d98fa377871224a"
checksum = "0646647444d3a0366e30f26ff39f1656cc062b3dbf1f2e3d70cd9dc244b62cf7"
dependencies = [
"chrono",
"clap",
@@ -2779,9 +2779,9 @@ dependencies = [
[[package]]
name = "sea-orm-macros"
version = "1.1.4"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d19e8f22fb474a8a622eb516c46885a080535d8d559386188f525977eaad32b3"
checksum = "a98408f82fb4875d41ef469a79944a7da29767c7b3e4028e22188a3dd613b10f"
dependencies = [
"heck 0.4.1",
"proc-macro2",
@@ -2793,9 +2793,9 @@ dependencies = [
[[package]]
name = "sea-orm-migration"
version = "1.1.4"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0bb76ba314552ce15e3a24778cf9c116fc1225fa406e48b0a36e5a3cdbc1e21"
checksum = "b97ed0bea0d92241722718e239d899c051066a5fb259ced9986b9f60e488e076"
dependencies = [
"async-trait",
"clap",
@@ -2886,18 +2886,18 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "serde"
version = "1.0.217"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
dependencies = [
"proc-macro2",
"quote",
@@ -2906,9 +2906,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.135"
version = "1.0.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6"
dependencies = [
"itoa",
"memchr",
@@ -2928,9 +2928,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "0.6.7"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
dependencies = [
"serde",
]
@@ -3299,15 +3299,21 @@ name = "strum"
version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
[[package]]
name = "strum"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.26.4"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@@ -3547,14 +3553,14 @@ dependencies = [
[[package]]
name = "toml"
version = "0.8.19"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit 0.22.22",
"toml_edit 0.22.24",
]
[[package]]
@@ -3579,15 +3585,15 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.22.22"
version = "0.22.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow 0.6.24",
"winnow 0.7.3",
]
[[package]]
@@ -4199,9 +4205,9 @@ dependencies = [
[[package]]
name = "winnow"
version = "0.6.24"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a"
checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1"
dependencies = [
"memchr",
]

View File

@@ -4,41 +4,41 @@ default-members = ["crates/bili_sync"]
resolver = "2"
[workspace.package]
version = "2.4.0"
version = "2.4.1"
authors = ["amtoaer <amtoaer@gmail.com>"]
license = "MIT"
description = "由 Rust & Tokio 驱动的哔哩哔哩同步工具"
edition = "2021"
edition = "2024"
publish = false
[workspace.dependencies]
bili_sync_entity = { path = "crates/bili_sync_entity" }
bili_sync_migration = { path = "crates/bili_sync_migration" }
anyhow = { version = "1.0.95", features = ["backtrace"] }
anyhow = { version = "1.0.96", features = ["backtrace"] }
arc-swap = { version = "1.7.1", features = ["serde"] }
assert_matches = "1.5"
assert_matches = "1.5.0"
async-std = { version = "1.13.0", features = ["attributes", "tokio1"] }
async-stream = "0.3.6"
async-trait = "0.1.85"
async-trait = "0.1.86"
axum = { version = "0.8.1", features = ["macros"] }
built = { version = "0.7.7", features = ["git2", "chrono"] }
chrono = { version = "0.4.39", features = ["serde"] }
clap = { version = "4.5.26", features = ["env", "string"] }
clap = { version = "4.5.30", features = ["env", "string"] }
cookie = "0.18.1"
cow-utils = "0.1.3"
dirs = "6.0.0"
enum_dispatch = "0.3.13"
float-ord = "0.3.2"
futures = "0.3.31"
handlebars = "6.3.0"
handlebars = "6.3.1"
hex = "0.4.3"
leaky-bucket = "1.1.2"
md5 = "0.7.0"
memchr = "2.7.4"
mime_guess = "=2.0.5"
once_cell = "1.20.2"
prost = "0.13.4"
mime_guess = "2.0.5"
once_cell = "1.20.3"
prost = "0.13.5"
quick-xml = { version = "0.37.2", features = ["async-tokio"] }
rand = "0.8.5"
regex = "1.11.1"
@@ -53,24 +53,24 @@ reqwest = { version = "0.12.12", features = [
], default-features = false }
rsa = { version = "0.9.7", features = ["sha2"] }
rust-embed = "8.5.0"
sea-orm = { version = "1.1.4", features = [
sea-orm = { version = "1.1.5", features = [
"macros",
"runtime-tokio-rustls",
"sqlx-sqlite",
] }
sea-orm-migration = { version = "1.1.4", features = [] }
serde = { version = "1.0.217", features = ["derive"] }
serde_json = "1.0.135"
sea-orm-migration = { version = "1.1.5", features = [] }
serde = { version = "1.0.218", features = ["derive"] }
serde_json = "1.0.139"
serde_urlencoded = "0.7.1"
strum = { version = "0.26.3", features = ["derive"] }
strum = { version = "0.27.1", features = ["derive"] }
thiserror = "2.0.11"
tokio = { version = "1.43.0", features = ["full"] }
tokio-util = { version = "0.7.13", features = ["io", "rt"] }
toml = "0.8.19"
toml = "0.8.20"
tower = "0.5.2"
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.19", features = ["chrono"] }
utoipa = { version = "5", features = ["axum_extras"] }
utoipa = { version = "5.3.1", features = ["axum_extras"] }
utoipa-swagger-ui = { version = "9.0.0", features = ["axum", "vendored"] }
[workspace.metadata.release]

View File

@@ -4,12 +4,12 @@ use std::pin::Pin;
use anyhow::{Context, Result};
use bili_sync_entity::*;
use futures::Stream;
use sea_orm::ActiveValue::Set;
use sea_orm::entity::prelude::*;
use sea_orm::sea_query::{OnConflict, SimpleExpr};
use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, Unchanged};
use crate::adapter::{VideoSource, VideoSourceEnum, _ActiveModel};
use crate::adapter::{_ActiveModel, VideoSource, VideoSourceEnum};
use crate::bilibili::{BiliClient, Collection, CollectionItem, CollectionType, VideoInfo};
impl VideoSource for collection::Model {

View File

@@ -4,12 +4,12 @@ use std::pin::Pin;
use anyhow::{Context, Result};
use bili_sync_entity::*;
use futures::Stream;
use sea_orm::ActiveValue::Set;
use sea_orm::entity::prelude::*;
use sea_orm::sea_query::{OnConflict, SimpleExpr};
use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, Unchanged};
use crate::adapter::{VideoSource, VideoSourceEnum, _ActiveModel};
use crate::adapter::{_ActiveModel, VideoSource, VideoSourceEnum};
use crate::bilibili::{BiliClient, FavoriteList, VideoInfo};
impl VideoSource for favorite::Model {

View File

@@ -9,9 +9,9 @@ use std::pin::Pin;
use anyhow::Result;
use enum_dispatch::enum_dispatch;
use futures::Stream;
use sea_orm::DatabaseConnection;
use sea_orm::entity::prelude::*;
use sea_orm::sea_query::SimpleExpr;
use sea_orm::DatabaseConnection;
#[rustfmt::skip]
use bili_sync_entity::collection::Model as Collection;
@@ -71,7 +71,7 @@ pub trait VideoSource {
fn log_download_video_end(&self);
}
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
pub enum Args<'a> {
Favorite { fid: &'a str },
Collection { collection_item: &'a CollectionItem },

View File

@@ -4,12 +4,12 @@ use std::pin::Pin;
use anyhow::{Context, Result};
use bili_sync_entity::*;
use futures::Stream;
use sea_orm::ActiveValue::Set;
use sea_orm::entity::prelude::*;
use sea_orm::sea_query::{OnConflict, SimpleExpr};
use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, Unchanged};
use crate::adapter::{VideoSource, VideoSourceEnum, _ActiveModel};
use crate::adapter::{_ActiveModel, VideoSource, VideoSourceEnum};
use crate::bilibili::{BiliClient, Submission, VideoInfo};
impl VideoSource for submission::Model {

View File

@@ -4,12 +4,12 @@ use std::pin::Pin;
use anyhow::{Context, Result};
use bili_sync_entity::*;
use futures::Stream;
use sea_orm::ActiveValue::Set;
use sea_orm::entity::prelude::*;
use sea_orm::sea_query::{OnConflict, SimpleExpr};
use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, Unchanged};
use crate::adapter::{VideoSource, VideoSourceEnum, _ActiveModel};
use crate::adapter::{_ActiveModel, VideoSource, VideoSourceEnum};
use crate::bilibili::{BiliClient, VideoInfo, WatchLater};
impl VideoSource for watch_later::Model {

View File

@@ -3,8 +3,8 @@ use axum::http::HeaderMap;
use axum::middleware::Next;
use axum::response::{IntoResponse, Response};
use reqwest::StatusCode;
use utoipa::openapi::security::{ApiKey, ApiKeyValue, SecurityScheme};
use utoipa::Modify;
use utoipa::openapi::security::{ApiKey, ApiKeyValue, SecurityScheme};
use crate::api::wrapper::ApiResponse;
use crate::config::CONFIG;

View File

@@ -1,6 +1,6 @@
use std::sync::Arc;
use anyhow::{anyhow, Result};
use anyhow::{Result, anyhow};
use axum::extract::{Extension, Path, Query};
use bili_sync_entity::*;
use bili_sync_migration::{Expr, OnConflict};

View File

@@ -1,6 +1,6 @@
use anyhow::Error;
use axum::response::IntoResponse;
use axum::Json;
use axum::response::IntoResponse;
use reqwest::StatusCode;
use serde::Serialize;
use utoipa::ToSchema;

View File

@@ -1,4 +1,4 @@
use anyhow::{bail, Context, Result};
use anyhow::{Context, Result, bail};
use serde::{Deserialize, Serialize};
use crate::bilibili::error::BiliError;
@@ -313,27 +313,31 @@ mod tests {
#[test]
fn test_quality_order() {
assert!([
VideoQuality::Quality360p,
VideoQuality::Quality480p,
VideoQuality::Quality720p,
VideoQuality::Quality1080p,
VideoQuality::Quality1080pPLUS,
VideoQuality::Quality1080p60,
VideoQuality::Quality4k,
VideoQuality::QualityHdr,
VideoQuality::QualityDolby,
VideoQuality::Quality8k
]
.is_sorted());
assert!([
AudioQuality::Quality64k,
AudioQuality::Quality132k,
AudioQuality::Quality192k,
AudioQuality::QualityDolby,
AudioQuality::QualityHiRES,
]
.is_sorted());
assert!(
[
VideoQuality::Quality360p,
VideoQuality::Quality480p,
VideoQuality::Quality720p,
VideoQuality::Quality1080p,
VideoQuality::Quality1080pPLUS,
VideoQuality::Quality1080p60,
VideoQuality::Quality4k,
VideoQuality::QualityHdr,
VideoQuality::QualityDolby,
VideoQuality::Quality8k
]
.is_sorted()
);
assert!(
[
AudioQuality::Quality64k,
AudioQuality::Quality132k,
AudioQuality::Quality192k,
AudioQuality::QualityDolby,
AudioQuality::QualityHiRES,
]
.is_sorted()
);
}
#[ignore = "only for manual test"]

View File

@@ -3,11 +3,11 @@ use std::time::Duration;
use anyhow::{Context, Result};
use leaky_bucket::RateLimiter;
use reqwest::{header, Method};
use reqwest::{Method, header};
use crate::bilibili::credential::WbiImg;
use crate::bilibili::Credential;
use crate::config::{RateLimit, CONFIG};
use crate::bilibili::credential::WbiImg;
use crate::config::{CONFIG, RateLimit};
// 一个对 reqwest::Client 的简单封装,用于 Bilibili 请求
#[derive(Clone)]

View File

@@ -1,6 +1,6 @@
use std::fmt::{Display, Formatter};
use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result, anyhow};
use async_stream::try_stream;
use futures::Stream;
use reqwest::Method;
@@ -8,7 +8,7 @@ use serde::Deserialize;
use serde_json::Value;
use crate::bilibili::credential::encoded_query;
use crate::bilibili::{BiliClient, Validate, VideoInfo, MIXIN_KEY};
use crate::bilibili::{BiliClient, MIXIN_KEY, Validate, VideoInfo};
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum CollectionType {

View File

@@ -1,11 +1,11 @@
use std::borrow::Cow;
use std::collections::HashSet;
use anyhow::{bail, ensure, Context, Result};
use anyhow::{Context, Result, bail, ensure};
use cookie::Cookie;
use cow_utils::CowUtils;
use regex::Regex;
use reqwest::{header, Method};
use reqwest::{Method, header};
use rsa::pkcs8::DecodePublicKey;
use rsa::sha2::Sha256;
use rsa::{Oaep, RsaPublicKey};

View File

@@ -1,5 +1,5 @@
use crate::bilibili::danmaku::canvas::CanvasConfig;
use crate::bilibili::danmaku::Danmu;
use crate::bilibili::danmaku::canvas::CanvasConfig;
pub enum Collision {
// 会越来越远

View File

@@ -5,10 +5,10 @@ use anyhow::Result;
use float_ord::FloatOrd;
use lane::Lane;
use crate::bilibili::PageInfo;
use crate::bilibili::danmaku::canvas::lane::Collision;
use crate::bilibili::danmaku::danmu::DanmuType;
use crate::bilibili::danmaku::{Danmu, DrawEffect, Drawable};
use crate::bilibili::PageInfo;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct DanmakuOption {

View File

@@ -1,5 +1,5 @@
//! 一个弹幕实例,但是没有位置信息
use anyhow::{bail, Result};
use anyhow::{Result, bail};
use crate::bilibili::danmaku::canvas::CanvasConfig;

View File

@@ -3,9 +3,9 @@ use std::path::PathBuf;
use anyhow::Result;
use tokio::fs::{self, File};
use crate::bilibili::PageInfo;
use crate::bilibili::danmaku::canvas::CanvasConfig;
use crate::bilibili::danmaku::{AssWriter, Danmu};
use crate::bilibili::PageInfo;
use crate::config::CONFIG;
pub struct DanmakuWriter<'a> {

View File

@@ -1,4 +1,4 @@
use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result, anyhow};
use async_stream::try_stream;
use futures::Stream;
use serde_json::Value;

View File

@@ -1,7 +1,7 @@
use std::sync::Arc;
pub use analyzer::{BestStream, FilterOption};
use anyhow::{bail, ensure, Result};
use anyhow::{Result, bail, ensure};
use arc_swap::ArcSwapOption;
use chrono::serde::ts_seconds;
use chrono::{DateTime, Utc};

View File

@@ -1,4 +1,4 @@
use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result, anyhow};
use arc_swap::access::Access;
use async_stream::try_stream;
use futures::Stream;
@@ -7,7 +7,7 @@ use serde_json::Value;
use crate::bilibili::credential::encoded_query;
use crate::bilibili::favorite_list::Upper;
use crate::bilibili::{BiliClient, Validate, VideoInfo, MIXIN_KEY};
use crate::bilibili::{BiliClient, MIXIN_KEY, Validate, VideoInfo};
pub struct Submission<'a> {
client: &'a BiliClient,
upper_id: String,

View File

@@ -1,6 +1,6 @@
use anyhow::{ensure, Result};
use futures::stream::FuturesUnordered;
use anyhow::{Result, ensure};
use futures::TryStreamExt;
use futures::stream::FuturesUnordered;
use prost::Message;
use reqwest::Method;
@@ -9,7 +9,7 @@ use crate::bilibili::client::BiliClient;
use crate::bilibili::credential::encoded_query;
use crate::bilibili::danmaku::{DanmakuElem, DanmakuWriter, DmSegMobileReply};
use crate::bilibili::subtitle::{SubTitle, SubTitleBody, SubTitleInfo, SubTitlesInfo};
use crate::bilibili::{Validate, VideoInfo, MIXIN_KEY};
use crate::bilibili::{MIXIN_KEY, Validate, VideoInfo};
static MASK_CODE: u64 = 2251799813685247;
static XOR_CODE: u64 = 23442827791579;

View File

@@ -1,4 +1,4 @@
use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result, anyhow};
use async_stream::try_stream;
use futures::Stream;
use serde_json::Value;

View File

@@ -1,7 +1,9 @@
use std::borrow::Cow;
use clap::Parser;
#[derive(Parser)]
#[command(name = "Bili-Sync", version = version(), about, long_about = None)]
#[command(name = "Bili-Sync", version = detail_version(), about, long_about = None)]
pub struct Args {
#[arg(short, long, env = "SCAN_ONLY")]
pub scan_only: bool,
@@ -14,19 +16,22 @@ mod built_info {
include!(concat!(env!("OUT_DIR"), "/built.rs"));
}
fn version() -> String {
let version = if let (Some(git_version), Some(git_dirty)) = (built_info::GIT_VERSION, built_info::GIT_DIRTY) {
format!("{}{}", git_version, if git_dirty { "-dirty" } else { "" })
pub fn version() -> Cow<'static, str> {
if let (Some(git_version), Some(git_dirty)) = (built_info::GIT_VERSION, built_info::GIT_DIRTY) {
Cow::Owned(format!("{}{}", git_version, if git_dirty { "-dirty" } else { "" }))
} else {
built_info::PKG_VERSION.to_owned()
};
Cow::Borrowed(built_info::PKG_VERSION)
}
}
fn detail_version() -> String {
format!(
"{}
Architecture: {}-{}
Author: {}
Built Time: {}
Rustc Version: {}",
version,
version(),
built_info::CFG_OS,
built_info::CFG_TARGET_ARCH,
built_info::PKG_AUTHORS,

View File

@@ -4,9 +4,9 @@ use clap::Parser;
use handlebars::handlebars_helper;
use once_cell::sync::Lazy;
use crate::config::Config;
use crate::config::clap::Args;
use crate::config::item::PathSafeTemplate;
use crate::config::Config;
/// 全局的 CONFIG可以从中读取配置信息
pub static CONFIG: Lazy<Config> = Lazy::new(load_config);
@@ -40,6 +40,7 @@ pub static CONFIG_DIR: Lazy<PathBuf> =
#[cfg(not(test))]
fn load_config() -> Config {
info!("开始加载配置文件..");
let config = Config::load().unwrap_or_else(|err| {
if err
.downcast_ref::<std::io::Error>()
@@ -47,7 +48,7 @@ fn load_config() -> Config {
{
panic!("加载配置文件失败,错误为: {err}");
}
warn!("配置文件不存在,使用默认配置...");
warn!("配置文件不存在,使用默认配置..");
Config::default()
});
info!("配置文件加载完毕,覆盖刷新原有配置");

View File

@@ -114,7 +114,7 @@ where
_ => {
return Err(serde::de::Error::custom(
"invalid collection type, should be series or season",
))
));
}
};
CollectionItem {
@@ -126,7 +126,7 @@ where
_ => {
return Err(serde::de::Error::custom(
"invalid collection key, should be series:mid:sid or season:mid:sid",
))
));
}
};
collection_list.insert(collection_item, value);

View File

@@ -12,9 +12,11 @@ mod clap;
mod global;
mod item;
use crate::adapter::Args;
use crate::bilibili::{CollectionItem, Credential, DanmakuOption, FilterOption};
pub use crate::config::clap::version;
pub use crate::config::global::{ARGS, CONFIG, CONFIG_DIR, TEMPLATE};
use crate::config::item::{deserialize_collection_list, serialize_collection_list, ConcurrentLimit};
use crate::config::item::{ConcurrentLimit, deserialize_collection_list, serialize_collection_list};
pub use crate::config::item::{NFOTimeType, PathSafeTemplate, RateLimit, WatchLaterConfig};
fn default_time_format() -> String {
@@ -107,23 +109,35 @@ impl Config {
Ok(toml::from_str(&config_content)?)
}
pub fn as_video_sources(&self) -> Vec<(Args<'_>, &PathBuf)> {
let mut params = Vec::new();
self.favorite_list
.iter()
.for_each(|(fid, path)| params.push((Args::Favorite { fid }, path)));
self.collection_list
.iter()
.for_each(|(collection_item, path)| params.push((Args::Collection { collection_item }, path)));
if self.watch_later.enabled {
params.push((Args::WatchLater, &self.watch_later.path));
}
self.submission_list
.iter()
.for_each(|(upper_id, path)| params.push((Args::Submission { upper_id }, path)));
params
}
#[cfg(not(test))]
pub fn check(&self) {
let mut ok = true;
if self.favorite_list.is_empty() && self.collection_list.is_empty() && !self.watch_later.enabled {
let video_sources = self.as_video_sources();
if video_sources.is_empty() {
ok = false;
error!("没有配置任何需要扫描的内容,程序空转没有意义");
}
if self.watch_later.enabled && !self.watch_later.path.is_absolute() {
error!(
"稍后再看保存的路径应为绝对路径,检测到:{}",
self.watch_later.path.display()
);
}
for path in self.favorite_list.values() {
for (args, path) in video_sources {
if !path.is_absolute() {
ok = false;
error!("收藏夹保存的路径应为绝对路径,检测到: {}", path.display());
error!("{:?} 保存的路径应为绝对路径,检测到: {}", args, path.display());
}
}
if !self.upper_path.is_absolute() {

View File

@@ -1,7 +1,7 @@
use core::str;
use std::path::Path;
use anyhow::{bail, ensure, Result};
use anyhow::{Result, bail, ensure};
use futures::TryStreamExt;
use reqwest::Method;
use tokio::fs::{self, File};

View File

@@ -59,10 +59,11 @@ fn spawn_task(
});
}
/// 初始化日志系统,加载命令行参数和配置文件
/// 初始化日志系统,打印欢迎信息,加载配置文件
fn init() {
Lazy::force(&ARGS);
init_logger(&ARGS.log_level);
info!("欢迎使用 Bili-Sync当前程序版本{}", config::version());
info!("项目地址https://github.com/amtoaer/bili-sync");
Lazy::force(&CONFIG);
}

View File

@@ -2,10 +2,10 @@ use std::sync::Arc;
use anyhow::{Context, Result};
use axum::extract::Request;
use axum::http::{header, Uri};
use axum::http::{Uri, header};
use axum::response::IntoResponse;
use axum::routing::{get, post};
use axum::{middleware, Extension, Router, ServiceExt};
use axum::{Extension, Router, ServiceExt, middleware};
use reqwest::StatusCode;
use rust_embed::Embed;
use sea_orm::DatabaseConnection;
@@ -13,7 +13,7 @@ use utoipa::OpenApi;
use utoipa_swagger_ui::{Config, SwaggerUi};
use crate::api::auth;
use crate::api::handler::{get_video, get_video_sources, get_videos, reset_video, ApiDoc};
use crate::api::handler::{ApiDoc, get_video, get_video_sources, get_videos, reset_video};
use crate::config::CONFIG;
#[derive(Embed)]
@@ -42,7 +42,7 @@ pub async fn http_server(database_connection: Arc<DatabaseConnection>) -> Result
let listener = tokio::net::TcpListener::bind(&CONFIG.bind_address)
.await
.context("bind address failed")?;
info!("开始监听 http 服务: http://{}", CONFIG.bind_address);
info!("开始运行管理页: http://{}", CONFIG.bind_address);
Ok(axum::serve(listener, ServiceExt::<Request>::into_make_service(app)).await?)
}

View File

@@ -1,10 +1,8 @@
use std::path::PathBuf;
use std::sync::Arc;
use sea_orm::DatabaseConnection;
use tokio::time;
use crate::adapter::Args;
use crate::bilibili::{self, BiliClient};
use crate::config::CONFIG;
use crate::workflow::process_video_source;
@@ -13,8 +11,9 @@ use crate::workflow::process_video_source;
pub async fn video_downloader(connection: Arc<DatabaseConnection>) {
let mut anchor = chrono::Local::now().date_naive();
let bili_client = BiliClient::new();
let params = collect_task_params();
let video_sources = CONFIG.as_video_sources();
loop {
info!("开始执行本轮视频下载任务..");
'inner: {
match bili_client.wbi_img().await.map(|wbi_img| wbi_img.into()) {
Ok(Some(mixin_key)) => bilibili::set_global_mixin_key(mixin_key),
@@ -34,7 +33,7 @@ pub async fn video_downloader(connection: Arc<DatabaseConnection>) {
}
anchor = chrono::Local::now().date_naive();
}
for (args, path) in &params {
for (args, path) in &video_sources {
if let Err(e) = process_video_source(*args, &bili_client, path, &connection).await {
error!("处理过程遇到错误:{:#}", e);
}
@@ -44,24 +43,3 @@ pub async fn video_downloader(connection: Arc<DatabaseConnection>) {
time::sleep(time::Duration::from_secs(CONFIG.interval)).await;
}
}
/// 构造下载视频任务执行所需的参数(下载类型和保存路径)
fn collect_task_params() -> Vec<(Args<'static>, &'static PathBuf)> {
let mut params = Vec::new();
CONFIG
.favorite_list
.iter()
.for_each(|(fid, path)| params.push((Args::Favorite { fid }, path)));
CONFIG
.collection_list
.iter()
.for_each(|(collection_item, path)| params.push((Args::Collection { collection_item }, path)));
if CONFIG.watch_later.enabled {
params.push((Args::WatchLater, &CONFIG.watch_later.path));
}
CONFIG
.submission_list
.iter()
.for_each(|(upper_id, path)| params.push((Args::Submission { upper_id }, path)));
params
}

View File

@@ -1,8 +1,8 @@
use anyhow::{Context, Result};
use bili_sync_entity::*;
use sea_orm::DatabaseTransaction;
use sea_orm::entity::prelude::*;
use sea_orm::sea_query::{OnConflict, SimpleExpr};
use sea_orm::DatabaseTransaction;
use crate::adapter::{VideoSource, VideoSourceEnum};
use crate::bilibili::{PageInfo, VideoInfo};

View File

@@ -1,8 +1,8 @@
use anyhow::Result;
use bili_sync_entity::*;
use quick_xml::Error;
use quick_xml::events::{BytesCData, BytesText};
use quick_xml::writer::Writer;
use quick_xml::Error;
use tokio::io::AsyncWriteExt;
use crate::config::NFOTimeType;

View File

@@ -2,19 +2,19 @@ use std::collections::HashSet;
use std::path::{Path, PathBuf};
use std::pin::Pin;
use anyhow::{anyhow, bail, Context, Result};
use anyhow::{Context, Result, anyhow, bail};
use bili_sync_entity::*;
use futures::stream::{FuturesOrdered, FuturesUnordered};
use futures::{Future, Stream, StreamExt, TryStreamExt};
use sea_orm::entity::prelude::*;
use sea_orm::ActiveValue::Set;
use sea_orm::TransactionTrait;
use sea_orm::entity::prelude::*;
use tokio::fs;
use tokio::sync::Semaphore;
use crate::adapter::{video_source_from, Args, VideoSource, VideoSourceEnum};
use crate::adapter::{Args, VideoSource, VideoSourceEnum, video_source_from};
use crate::bilibili::{BestStream, BiliClient, BiliError, Dimension, PageInfo, Video, VideoInfo};
use crate::config::{PathSafeTemplate, ARGS, CONFIG, TEMPLATE};
use crate::config::{ARGS, CONFIG, PathSafeTemplate, TEMPLATE};
use crate::downloader::Downloader;
use crate::error::{DownloadAbortError, ExecutionStatus, ProcessPageError};
use crate::utils::format_arg::{page_format_args, video_format_args};
@@ -23,7 +23,7 @@ use crate::utils::model::{
update_videos_model,
};
use crate::utils::nfo::{ModelWrapper, NFOMode, NFOSerializer};
use crate::utils::status::{PageStatus, VideoStatus, STATUS_OK};
use crate::utils::status::{PageStatus, STATUS_OK, VideoStatus};
/// 完整地处理某个视频来源
pub async fn process_video_source(

View File

@@ -21,7 +21,7 @@ export default defineConfig({
nav: [
{ text: "主页", link: "/" },
{
text: "v2.4.0",
text: "v2.4.1",
items: [
{
text: "程序更新",

View File

@@ -1,7 +1,7 @@
# bili-sync 是什么?
> [!TIP]
> 当前最新程序版本为 v2.4.0,文档将始终与最新程序版本保持一致。
> 当前最新程序版本为 v2.4.1,文档将始终与最新程序版本保持一致。
bili-sync 是一款专为 NAS 用户编写的哔哩哔哩同步工具。