mirror of
https://github.com/amtoaer/bili-sync.git
synced 2026-05-08 21:03:01 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16e14fc371 | ||
|
|
b4a5dee236 | ||
|
|
2b3e6f9547 | ||
|
|
f8b93d2c76 | ||
|
|
94462ca706 |
2
.github/workflows/build-binary.yaml
vendored
2
.github/workflows/build-binary.yaml
vendored
@@ -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
100
Cargo.lock
generated
@@ -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",
|
||||
]
|
||||
|
||||
34
Cargo.toml
34
Cargo.toml
@@ -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]
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::bilibili::danmaku::canvas::CanvasConfig;
|
||||
use crate::bilibili::danmaku::Danmu;
|
||||
use crate::bilibili::danmaku::canvas::CanvasConfig;
|
||||
|
||||
pub enum Collision {
|
||||
// 会越来越远
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! 一个弹幕实例,但是没有位置信息
|
||||
use anyhow::{bail, Result};
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
use crate::bilibili::danmaku::canvas::CanvasConfig;
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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!("配置文件加载完毕,覆盖刷新原有配置");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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?)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ¶ms {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -21,7 +21,7 @@ export default defineConfig({
|
||||
nav: [
|
||||
{ text: "主页", link: "/" },
|
||||
{
|
||||
text: "v2.4.0",
|
||||
text: "v2.4.1",
|
||||
items: [
|
||||
{
|
||||
text: "程序更新",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# bili-sync 是什么?
|
||||
|
||||
> [!TIP]
|
||||
> 当前最新程序版本为 v2.4.0,文档将始终与最新程序版本保持一致。
|
||||
> 当前最新程序版本为 v2.4.1,文档将始终与最新程序版本保持一致。
|
||||
|
||||
bili-sync 是一款专为 NAS 用户编写的哔哩哔哩同步工具。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user