refactor: fix database
This commit is contained in:
parent
70932900cd
commit
caaa5dc0cc
198
Cargo.lock
generated
198
Cargo.lock
generated
@ -2,6 +2,16 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "Inflector"
|
||||||
|
version = "0.11.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.24.2"
|
version = "0.24.2"
|
||||||
@ -165,6 +175,12 @@ version = "0.7.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ascii_utils"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assert-json-diff"
|
name = "assert-json-diff"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
@ -191,6 +207,98 @@ dependencies = [
|
|||||||
"zstd-safe",
|
"zstd-safe",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-graphql"
|
||||||
|
version = "7.0.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59fd6bd734afb8b6e4d0f84a3e77305ce0a7ccc60d70f6001cb5e1c3f38d8ff1"
|
||||||
|
dependencies = [
|
||||||
|
"async-graphql-derive",
|
||||||
|
"async-graphql-parser",
|
||||||
|
"async-graphql-value",
|
||||||
|
"async-stream",
|
||||||
|
"async-trait",
|
||||||
|
"base64 0.22.1",
|
||||||
|
"bytes",
|
||||||
|
"fast_chemail",
|
||||||
|
"fnv",
|
||||||
|
"futures-timer",
|
||||||
|
"futures-util",
|
||||||
|
"handlebars",
|
||||||
|
"http 1.2.0",
|
||||||
|
"indexmap 2.7.0",
|
||||||
|
"mime",
|
||||||
|
"multer",
|
||||||
|
"num-traits",
|
||||||
|
"pin-project-lite",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_urlencoded",
|
||||||
|
"static_assertions_next",
|
||||||
|
"tempfile",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-graphql-axum"
|
||||||
|
version = "7.0.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec8c1bb47161c37286e40e2fa58055e97b2a2b6cf1022a6686967e10636fa5d7"
|
||||||
|
dependencies = [
|
||||||
|
"async-graphql",
|
||||||
|
"async-trait",
|
||||||
|
"axum",
|
||||||
|
"bytes",
|
||||||
|
"futures-util",
|
||||||
|
"serde_json",
|
||||||
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
"tokio-util",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-graphql-derive"
|
||||||
|
version = "7.0.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac38b4dd452d529d6c0248b51df23603f0a875770352e26ae8c346ce6c149b3e"
|
||||||
|
dependencies = [
|
||||||
|
"Inflector",
|
||||||
|
"async-graphql-parser",
|
||||||
|
"darling",
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strum",
|
||||||
|
"syn 2.0.92",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-graphql-parser"
|
||||||
|
version = "7.0.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42d271ddda2f55b13970928abbcbc3423cfc18187c60e8769b48f21a93b7adaa"
|
||||||
|
dependencies = [
|
||||||
|
"async-graphql-value",
|
||||||
|
"pest",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-graphql-value"
|
||||||
|
version = "7.0.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aefe909173a037eaf3281b046dc22580b59a38b765d7b8d5116f2ffef098048d"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"indexmap 2.7.0",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-stream"
|
name = "async-stream"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
@ -282,6 +390,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"axum-core",
|
"axum-core",
|
||||||
"axum-macros",
|
"axum-macros",
|
||||||
|
"base64 0.22.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 1.2.0",
|
"http 1.2.0",
|
||||||
@ -300,8 +409,10 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_path_to_error",
|
"serde_path_to_error",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
|
"sha1",
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-tungstenite",
|
||||||
"tower 0.5.2",
|
"tower 0.5.2",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
@ -722,6 +833,9 @@ name = "bytes"
|
|||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
|
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytesize"
|
name = "bytesize"
|
||||||
@ -1576,6 +1690,15 @@ dependencies = [
|
|||||||
"regex-syntax 0.8.5",
|
"regex-syntax 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fast_chemail"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "495a39d30d624c2caabe6312bfead73e7717692b44e0b32df168c275a2e8e9e4"
|
||||||
|
dependencies = [
|
||||||
|
"ascii_utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
@ -1768,6 +1891,12 @@ version = "0.3.31"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-timer"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
@ -1904,6 +2033,20 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "handlebars"
|
||||||
|
version = "5.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"pest",
|
||||||
|
"pest_derive",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@ -4369,6 +4512,8 @@ name = "recorder"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"async-graphql",
|
||||||
|
"async-graphql-axum",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
"axum-auth",
|
"axum-auth",
|
||||||
@ -5874,6 +6019,12 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions_next"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7beae5182595e9a8b683fa98c4317f956c9a2dec3b9716990d20023cc60c766"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "string_cache"
|
name = "string_cache"
|
||||||
version = "0.8.7"
|
version = "0.8.7"
|
||||||
@ -5945,6 +6096,22 @@ name = "strum"
|
|||||||
version = "0.26.3"
|
version = "0.26.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||||
|
dependencies = [
|
||||||
|
"strum_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.26.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.5.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn 2.0.92",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
@ -6328,6 +6495,18 @@ dependencies = [
|
|||||||
"xattr",
|
"xattr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-tungstenite"
|
||||||
|
version = "0.24.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"tokio",
|
||||||
|
"tungstenite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.13"
|
version = "0.7.13"
|
||||||
@ -6336,6 +6515,7 @@ checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -6559,6 +6739,24 @@ version = "0.2.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tungstenite"
|
||||||
|
version = "0.24.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"bytes",
|
||||||
|
"data-encoding",
|
||||||
|
"http 1.2.0",
|
||||||
|
"httparse",
|
||||||
|
"log",
|
||||||
|
"rand",
|
||||||
|
"sha1",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
"utf-8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typed-builder"
|
name = "typed-builder"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
|
@ -44,7 +44,7 @@ axum = "0.7.9"
|
|||||||
uuid = { version = "1.6.0", features = ["v4"] }
|
uuid = { version = "1.6.0", features = ["v4"] }
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
|
||||||
sea-orm-migration = { version = "1", features = ["runtime-tokio-rustls"] }
|
sea-orm-migration = { version = "1", features = ["runtime-tokio-rustls"] }
|
||||||
reqwest = "0.12.9"
|
reqwest = { version = "0.12.9" }
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
rss = "2"
|
rss = "2"
|
||||||
bytes = "1.9"
|
bytes = "1.9"
|
||||||
@ -85,6 +85,8 @@ testcontainers-modules = { version = "0.11.4", optional = true }
|
|||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
anyhow = "1.0.95"
|
anyhow = "1.0.95"
|
||||||
bollard = { version = "0.18", optional = true }
|
bollard = { version = "0.18", optional = true }
|
||||||
|
async-graphql = "7.0.13"
|
||||||
|
async-graphql-axum = "7.0.13"
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -20,7 +20,7 @@ use crate::{
|
|||||||
dal::{AppDalClient, AppDalInitalizer},
|
dal::{AppDalClient, AppDalInitalizer},
|
||||||
extract::mikan::{client::AppMikanClientInitializer, AppMikanClient},
|
extract::mikan::{client::AppMikanClientInitializer, AppMikanClient},
|
||||||
migrations::Migrator,
|
migrations::Migrator,
|
||||||
models::entities::subscribers,
|
models::subscribers,
|
||||||
workers::subscription_worker::SubscriptionWorker,
|
workers::subscription_worker::SubscriptionWorker,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ pub struct OidcAuthConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(tag = "type", rename_all = "snake_case")]
|
#[serde(tag = "auth_type", rename_all = "snake_case")]
|
||||||
pub enum AppAuthConfig {
|
pub enum AppAuthConfig {
|
||||||
Basic(BasicAuthConfig),
|
Basic(BasicAuthConfig),
|
||||||
Oidc(OidcAuthConfig),
|
Oidc(OidcAuthConfig),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use loco_rs::prelude::*;
|
use loco_rs::prelude::*;
|
||||||
|
|
||||||
use crate::{models::entities::subscribers, views::subscribers::CurrentResponse};
|
use crate::{models::subscribers, views::subscribers::CurrentResponse};
|
||||||
|
|
||||||
async fn current(State(ctx): State<AppContext>) -> Result<impl IntoResponse> {
|
async fn current(State(ctx): State<AppContext>) -> Result<impl IntoResponse> {
|
||||||
let subscriber = subscribers::Model::find_root(&ctx).await?;
|
let subscriber = subscribers::Model::find_root(&ctx).await?;
|
||||||
|
@ -38,7 +38,6 @@ pub enum Bangumi {
|
|||||||
Id,
|
Id,
|
||||||
MikanBangumiId,
|
MikanBangumiId,
|
||||||
DisplayName,
|
DisplayName,
|
||||||
SubscriptionId,
|
|
||||||
SubscriberId,
|
SubscriberId,
|
||||||
RawName,
|
RawName,
|
||||||
Season,
|
Season,
|
||||||
@ -54,6 +53,14 @@ pub enum Bangumi {
|
|||||||
Extra,
|
Extra,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
pub enum SubscriptionBangumi {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
SubscriptionId,
|
||||||
|
BangumiId,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(DeriveIden)]
|
#[derive(DeriveIden)]
|
||||||
pub enum Episodes {
|
pub enum Episodes {
|
||||||
Table,
|
Table,
|
||||||
@ -62,7 +69,6 @@ pub enum Episodes {
|
|||||||
RawName,
|
RawName,
|
||||||
DisplayName,
|
DisplayName,
|
||||||
BangumiId,
|
BangumiId,
|
||||||
SubscriptionId,
|
|
||||||
SubscriberId,
|
SubscriberId,
|
||||||
DownloadId,
|
DownloadId,
|
||||||
SavePath,
|
SavePath,
|
||||||
@ -79,13 +85,23 @@ pub enum Episodes {
|
|||||||
Extra,
|
Extra,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(DeriveIden)]
|
||||||
|
pub enum SubscriptionEpisode {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
SubscriptionId,
|
||||||
|
EpisodeId,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(DeriveIden)]
|
#[derive(DeriveIden)]
|
||||||
pub enum Downloads {
|
pub enum Downloads {
|
||||||
Table,
|
Table,
|
||||||
Id,
|
Id,
|
||||||
OriginalName,
|
RawName,
|
||||||
DisplayName,
|
DisplayName,
|
||||||
SubscriptionId,
|
SubscriberId,
|
||||||
|
DownloaderId,
|
||||||
|
EpisodeId,
|
||||||
Status,
|
Status,
|
||||||
CurrSize,
|
CurrSize,
|
||||||
AllSize,
|
AllSize,
|
||||||
|
@ -2,7 +2,8 @@ use loco_rs::schema::jsonb_null;
|
|||||||
use sea_orm_migration::{prelude::*, schema::*};
|
use sea_orm_migration::{prelude::*, schema::*};
|
||||||
|
|
||||||
use super::defs::{
|
use super::defs::{
|
||||||
Bangumi, CustomSchemaManagerExt, Episodes, GeneralIds, Subscribers, Subscriptions,
|
Bangumi, CustomSchemaManagerExt, Episodes, GeneralIds, Subscribers, SubscriptionBangumi,
|
||||||
|
SubscriptionEpisode, Subscriptions,
|
||||||
};
|
};
|
||||||
use crate::models::{
|
use crate::models::{
|
||||||
subscribers::SEED_SUBSCRIBER,
|
subscribers::SEED_SUBSCRIBER,
|
||||||
@ -37,12 +38,15 @@ impl MigrationTrait for Migration {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let insert = Query::insert()
|
manager
|
||||||
.into_table(Subscribers::Table)
|
.exec_stmt(
|
||||||
.columns([Subscribers::Pid, Subscribers::DisplayName])
|
Query::insert()
|
||||||
.values_panic([SEED_SUBSCRIBER.into(), SEED_SUBSCRIBER.into()])
|
.into_table(Subscribers::Table)
|
||||||
.to_owned();
|
.columns([Subscribers::Pid, Subscribers::DisplayName])
|
||||||
manager.exec_stmt(insert).await?;
|
.values_panic([SEED_SUBSCRIBER.into(), SEED_SUBSCRIBER.into()])
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
create_postgres_enum_for_active_enum!(
|
create_postgres_enum_for_active_enum!(
|
||||||
manager,
|
manager,
|
||||||
@ -70,7 +74,7 @@ impl MigrationTrait for Migration {
|
|||||||
.name("fk_subscriptions_subscriber_id")
|
.name("fk_subscriptions_subscriber_id")
|
||||||
.from(Subscriptions::Table, Subscriptions::SubscriberId)
|
.from(Subscriptions::Table, Subscriptions::SubscriberId)
|
||||||
.to(Subscribers::Table, Subscribers::Id)
|
.to(Subscribers::Table, Subscribers::Id)
|
||||||
.on_update(ForeignKeyAction::Restrict)
|
.on_update(ForeignKeyAction::Cascade)
|
||||||
.on_delete(ForeignKeyAction::Cascade),
|
.on_delete(ForeignKeyAction::Cascade),
|
||||||
)
|
)
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
@ -89,7 +93,6 @@ impl MigrationTrait for Migration {
|
|||||||
table_auto(Bangumi::Table)
|
table_auto(Bangumi::Table)
|
||||||
.col(pk_auto(Bangumi::Id))
|
.col(pk_auto(Bangumi::Id))
|
||||||
.col(text_null(Bangumi::MikanBangumiId))
|
.col(text_null(Bangumi::MikanBangumiId))
|
||||||
.col(integer(Bangumi::SubscriptionId))
|
|
||||||
.col(integer(Bangumi::SubscriberId))
|
.col(integer(Bangumi::SubscriberId))
|
||||||
.col(text(Bangumi::DisplayName))
|
.col(text(Bangumi::DisplayName))
|
||||||
.col(text(Bangumi::RawName))
|
.col(text(Bangumi::RawName))
|
||||||
@ -104,22 +107,24 @@ impl MigrationTrait for Migration {
|
|||||||
.col(boolean(Bangumi::Deleted).default(false))
|
.col(boolean(Bangumi::Deleted).default(false))
|
||||||
.col(text_null(Bangumi::Homepage))
|
.col(text_null(Bangumi::Homepage))
|
||||||
.col(jsonb_null(Bangumi::Extra))
|
.col(jsonb_null(Bangumi::Extra))
|
||||||
.foreign_key(
|
|
||||||
ForeignKey::create()
|
|
||||||
.name("fk_bangumi_subscription_id")
|
|
||||||
.from(Bangumi::Table, Bangumi::SubscriptionId)
|
|
||||||
.to(Subscriptions::Table, Subscriptions::Id)
|
|
||||||
.on_update(ForeignKeyAction::Restrict)
|
|
||||||
.on_delete(ForeignKeyAction::Cascade),
|
|
||||||
)
|
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk_bangumi_subscriber_id")
|
.name("fk_bangumi_subscriber_id")
|
||||||
.from(Bangumi::Table, Bangumi::SubscriberId)
|
.from(Bangumi::Table, Bangumi::SubscriberId)
|
||||||
.to(Subscribers::Table, Subscribers::Id)
|
.to(Subscribers::Table, Subscribers::Id)
|
||||||
.on_update(ForeignKeyAction::Restrict)
|
.on_update(ForeignKeyAction::Cascade)
|
||||||
.on_delete(ForeignKeyAction::Cascade),
|
.on_delete(ForeignKeyAction::Cascade),
|
||||||
)
|
)
|
||||||
|
.index(
|
||||||
|
Index::create()
|
||||||
|
.if_not_exists()
|
||||||
|
.name("idx_bangumi_mikan_bangumi_id_mikan_fansub_id_subscriber_id")
|
||||||
|
.table(Bangumi::Table)
|
||||||
|
.col(Bangumi::MikanBangumiId)
|
||||||
|
.col(Bangumi::MikanFansubId)
|
||||||
|
.col(Bangumi::SubscriberId)
|
||||||
|
.unique(),
|
||||||
|
)
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@ -150,6 +155,44 @@ impl MigrationTrait for Migration {
|
|||||||
.create_postgres_auto_update_ts_trigger_for_col(Bangumi::Table, GeneralIds::UpdatedAt)
|
.create_postgres_auto_update_ts_trigger_for_col(Bangumi::Table, GeneralIds::UpdatedAt)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
table_auto(SubscriptionBangumi::Table)
|
||||||
|
.col(pk_auto(SubscriptionBangumi::Id))
|
||||||
|
.col(integer(SubscriptionBangumi::SubscriptionId))
|
||||||
|
.col(integer(SubscriptionBangumi::BangumiId))
|
||||||
|
.foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("fk_subscription_bangumi_subscription_id")
|
||||||
|
.from(
|
||||||
|
SubscriptionBangumi::Table,
|
||||||
|
SubscriptionBangumi::SubscriptionId,
|
||||||
|
)
|
||||||
|
.to(Subscriptions::Table, Subscriptions::Id)
|
||||||
|
.on_update(ForeignKeyAction::Cascade)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("fk_subscription_bangumi_bangumi_id")
|
||||||
|
.from(SubscriptionBangumi::Table, SubscriptionBangumi::BangumiId)
|
||||||
|
.to(Bangumi::Table, Bangumi::Id)
|
||||||
|
.on_update(ForeignKeyAction::Cascade)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade),
|
||||||
|
)
|
||||||
|
.index(
|
||||||
|
Index::create()
|
||||||
|
.if_not_exists()
|
||||||
|
.name("constraint_subscription_bangumi_subscription_id_bangumi_id")
|
||||||
|
.table(SubscriptionBangumi::Table)
|
||||||
|
.col(SubscriptionBangumi::SubscriptionId)
|
||||||
|
.col(SubscriptionBangumi::BangumiId)
|
||||||
|
.unique(),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
.create_table(
|
.create_table(
|
||||||
table_auto(Episodes::Table)
|
table_auto(Episodes::Table)
|
||||||
@ -158,7 +201,6 @@ impl MigrationTrait for Migration {
|
|||||||
.col(text(Episodes::RawName))
|
.col(text(Episodes::RawName))
|
||||||
.col(text(Episodes::DisplayName))
|
.col(text(Episodes::DisplayName))
|
||||||
.col(integer(Episodes::BangumiId))
|
.col(integer(Episodes::BangumiId))
|
||||||
.col(integer(Episodes::SubscriptionId))
|
|
||||||
.col(integer(Episodes::SubscriberId))
|
.col(integer(Episodes::SubscriberId))
|
||||||
.col(text_null(Episodes::SavePath))
|
.col(text_null(Episodes::SavePath))
|
||||||
.col(text_null(Episodes::Resolution))
|
.col(text_null(Episodes::Resolution))
|
||||||
@ -172,20 +214,12 @@ impl MigrationTrait for Migration {
|
|||||||
.col(boolean(Episodes::Deleted).default(false))
|
.col(boolean(Episodes::Deleted).default(false))
|
||||||
.col(text_null(Episodes::Source))
|
.col(text_null(Episodes::Source))
|
||||||
.col(jsonb_null(Episodes::Extra))
|
.col(jsonb_null(Episodes::Extra))
|
||||||
.foreign_key(
|
|
||||||
ForeignKey::create()
|
|
||||||
.name("fk_episodes_subscription_id")
|
|
||||||
.from(Episodes::Table, Episodes::SubscriptionId)
|
|
||||||
.to(Subscriptions::Table, Subscriptions::Id)
|
|
||||||
.on_update(ForeignKeyAction::Restrict)
|
|
||||||
.on_delete(ForeignKeyAction::Cascade),
|
|
||||||
)
|
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk_episodes_bangumi_id")
|
.name("fk_episodes_bangumi_id")
|
||||||
.from(Episodes::Table, Episodes::BangumiId)
|
.from(Episodes::Table, Episodes::BangumiId)
|
||||||
.to(Bangumi::Table, Bangumi::Id)
|
.to(Bangumi::Table, Bangumi::Id)
|
||||||
.on_update(ForeignKeyAction::Restrict)
|
.on_update(ForeignKeyAction::Cascade)
|
||||||
.on_delete(ForeignKeyAction::Cascade),
|
.on_delete(ForeignKeyAction::Cascade),
|
||||||
)
|
)
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
@ -193,7 +227,7 @@ impl MigrationTrait for Migration {
|
|||||||
.name("fk_episodes_subscriber_id")
|
.name("fk_episodes_subscriber_id")
|
||||||
.from(Episodes::Table, Episodes::SubscriberId)
|
.from(Episodes::Table, Episodes::SubscriberId)
|
||||||
.to(Subscribers::Table, Subscribers::Id)
|
.to(Subscribers::Table, Subscribers::Id)
|
||||||
.on_update(ForeignKeyAction::Restrict)
|
.on_update(ForeignKeyAction::Cascade)
|
||||||
.on_delete(ForeignKeyAction::Cascade),
|
.on_delete(ForeignKeyAction::Cascade),
|
||||||
)
|
)
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
@ -228,12 +262,50 @@ impl MigrationTrait for Migration {
|
|||||||
.create_postgres_auto_update_ts_trigger_for_col(Episodes::Table, GeneralIds::UpdatedAt)
|
.create_postgres_auto_update_ts_trigger_for_col(Episodes::Table, GeneralIds::UpdatedAt)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
table_auto(SubscriptionEpisode::Table)
|
||||||
|
.col(pk_auto(SubscriptionEpisode::Id))
|
||||||
|
.col(integer(SubscriptionEpisode::SubscriptionId))
|
||||||
|
.col(integer(SubscriptionEpisode::EpisodeId))
|
||||||
|
.foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("fk_subscription_episode_subscription_id")
|
||||||
|
.from(
|
||||||
|
SubscriptionEpisode::Table,
|
||||||
|
SubscriptionEpisode::SubscriptionId,
|
||||||
|
)
|
||||||
|
.to(Subscriptions::Table, Subscriptions::Id)
|
||||||
|
.on_update(ForeignKeyAction::Cascade)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("fk_subscription_episode_episode_id")
|
||||||
|
.from(SubscriptionEpisode::Table, SubscriptionEpisode::EpisodeId)
|
||||||
|
.to(Episodes::Table, Episodes::Id)
|
||||||
|
.on_update(ForeignKeyAction::Cascade)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade),
|
||||||
|
)
|
||||||
|
.index(
|
||||||
|
Index::create()
|
||||||
|
.if_not_exists()
|
||||||
|
.name("constraint_subscription_episode_subscription_id_episode_id")
|
||||||
|
.table(SubscriptionEpisode::Table)
|
||||||
|
.col(SubscriptionEpisode::SubscriptionId)
|
||||||
|
.col(SubscriptionEpisode::EpisodeId)
|
||||||
|
.unique(),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
manager
|
manager
|
||||||
.drop_table(Table::drop().table(Episodes::Table).to_owned())
|
.drop_table(Table::drop().table(SubscriptionEpisode::Table).to_owned())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
@ -241,7 +313,11 @@ impl MigrationTrait for Migration {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
.drop_table(Table::drop().table(Bangumi::Table).to_owned())
|
.drop_table(Table::drop().table(Episodes::Table).to_owned())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(SubscriptionBangumi::Table).to_owned())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
@ -249,7 +325,7 @@ impl MigrationTrait for Migration {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
.drop_table(Table::drop().table(Subscriptions::Table).to_owned())
|
.drop_table(Table::drop().table(Bangumi::Table).to_owned())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
@ -260,7 +336,7 @@ impl MigrationTrait for Migration {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
.drop_table(Table::drop().table(Subscribers::Table).to_owned())
|
.drop_table(Table::drop().table(Subscriptions::Table).to_owned())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
@ -268,17 +344,21 @@ impl MigrationTrait for Migration {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
.drop_postgres_enum_for_active_enum(subscriptions::SubscriptionCategoryEnum)
|
.drop_table(Table::drop().table(Subscribers::Table).to_owned())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
.drop_postgres_auto_update_ts_fn_for_col(GeneralIds::UpdatedAt)
|
.drop_postgres_enum_for_active_enum(subscriptions::SubscriptionCategoryEnum)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
.drop_postgres_enum_for_active_enum(SubscriptionCategoryEnum)
|
.drop_postgres_enum_for_active_enum(SubscriptionCategoryEnum)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.drop_postgres_auto_update_ts_fn_for_col(GeneralIds::UpdatedAt)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,12 @@ use loco_rs::schema::table_auto;
|
|||||||
use sea_orm_migration::{prelude::*, schema::*};
|
use sea_orm_migration::{prelude::*, schema::*};
|
||||||
|
|
||||||
use super::defs::*;
|
use super::defs::*;
|
||||||
use crate::models::prelude::{
|
use crate::models::{
|
||||||
downloads::{DownloadMimeEnum, DownloadStatusEnum},
|
downloaders::DownloaderCategoryEnum,
|
||||||
DownloadMime, DownloadStatus,
|
prelude::{
|
||||||
|
downloads::{DownloadMimeEnum, DownloadStatusEnum},
|
||||||
|
DownloadMime, DownloadStatus, DownloaderCategory,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(DeriveMigrationName)]
|
#[derive(DeriveMigrationName)]
|
||||||
@ -13,6 +16,48 @@ pub struct Migration;
|
|||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl MigrationTrait for Migration {
|
impl MigrationTrait for Migration {
|
||||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
create_postgres_enum_for_active_enum!(
|
||||||
|
manager,
|
||||||
|
DownloaderCategoryEnum,
|
||||||
|
DownloaderCategory::QBittorrent
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
table_auto(Downloaders::Table)
|
||||||
|
.col(pk_auto(Downloaders::Id))
|
||||||
|
.col(text(Downloaders::Endpoint))
|
||||||
|
.col(string_null(Downloaders::Username))
|
||||||
|
.col(string_null(Downloaders::Password))
|
||||||
|
.col(enumeration(
|
||||||
|
Downloaders::Category,
|
||||||
|
DownloaderCategoryEnum,
|
||||||
|
DownloaderCategory::iden_values(),
|
||||||
|
))
|
||||||
|
.col(text(Downloaders::SavePath))
|
||||||
|
.col(integer(Downloaders::SubscriberId))
|
||||||
|
.foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("fk_downloader_subscriber_id")
|
||||||
|
.from_tbl(Downloaders::Table)
|
||||||
|
.from_col(Downloaders::SubscriberId)
|
||||||
|
.to_tbl(Subscribers::Table)
|
||||||
|
.to_col(Subscribers::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.on_update(ForeignKeyAction::Cascade),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_postgres_auto_update_ts_trigger_for_col(
|
||||||
|
Downloaders::Table,
|
||||||
|
GeneralIds::UpdatedAt,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
create_postgres_enum_for_active_enum!(
|
create_postgres_enum_for_active_enum!(
|
||||||
manager,
|
manager,
|
||||||
DownloadMimeEnum,
|
DownloadMimeEnum,
|
||||||
@ -37,9 +82,11 @@ impl MigrationTrait for Migration {
|
|||||||
.create_table(
|
.create_table(
|
||||||
table_auto(Downloads::Table)
|
table_auto(Downloads::Table)
|
||||||
.col(pk_auto(Downloads::Id))
|
.col(pk_auto(Downloads::Id))
|
||||||
.col(string(Downloads::OriginalName))
|
.col(string(Downloads::RawName))
|
||||||
.col(string(Downloads::DisplayName))
|
.col(string(Downloads::DisplayName))
|
||||||
.col(integer(Downloads::SubscriptionId))
|
.col(integer(Downloads::SubscriberId))
|
||||||
|
.col(integer(Downloads::DownloaderId))
|
||||||
|
.col(integer(Downloads::EpisodeId))
|
||||||
.col(enumeration(
|
.col(enumeration(
|
||||||
Downloads::Status,
|
Downloads::Status,
|
||||||
DownloadStatusEnum,
|
DownloadStatusEnum,
|
||||||
@ -57,16 +104,42 @@ impl MigrationTrait for Migration {
|
|||||||
.col(text_null(Downloads::SavePath))
|
.col(text_null(Downloads::SavePath))
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk_downloads_subscription_id")
|
.name("fk_downloads_subscriber_id")
|
||||||
.from(Downloads::Table, Downloads::SubscriptionId)
|
.from_tbl(Downloads::Table)
|
||||||
.to(Subscriptions::Table, Subscriptions::Id)
|
.from_col(Downloads::SubscriberId)
|
||||||
.on_update(ForeignKeyAction::Restrict)
|
.to_tbl(Subscribers::Table)
|
||||||
.on_delete(ForeignKeyAction::Cascade),
|
.to_col(Subscribers::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.on_update(ForeignKeyAction::Cascade),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("fk_downloads_downloader_id")
|
||||||
|
.from_tbl(Downloads::Table)
|
||||||
|
.from_col(Downloads::DownloaderId)
|
||||||
|
.to_tbl(Downloaders::Table)
|
||||||
|
.to_col(Downloaders::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.on_update(ForeignKeyAction::Cascade),
|
||||||
|
)
|
||||||
|
.foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("fk_downloads_episode_id")
|
||||||
|
.from_tbl(Downloads::Table)
|
||||||
|
.from_col(Downloads::EpisodeId)
|
||||||
|
.to_tbl(Episodes::Table)
|
||||||
|
.to_col(Episodes::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.on_update(ForeignKeyAction::Cascade),
|
||||||
)
|
)
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_postgres_auto_update_ts_trigger_for_col(Downloads::Table, GeneralIds::UpdatedAt)
|
||||||
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
.create_index(
|
.create_index(
|
||||||
Index::create()
|
Index::create()
|
||||||
@ -78,37 +151,12 @@ impl MigrationTrait for Migration {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
|
||||||
.alter_table(
|
|
||||||
Table::alter()
|
|
||||||
.table(Episodes::Table)
|
|
||||||
.add_column_if_not_exists(integer_null(Episodes::DownloadId))
|
|
||||||
.add_foreign_key(
|
|
||||||
TableForeignKey::new()
|
|
||||||
.name("fk_episodes_download_id")
|
|
||||||
.from_tbl(Episodes::Table)
|
|
||||||
.from_col(Episodes::DownloadId)
|
|
||||||
.to_tbl(Downloads::Table)
|
|
||||||
.to_col(Downloads::Id)
|
|
||||||
.on_update(ForeignKeyAction::Restrict)
|
|
||||||
.on_delete(ForeignKeyAction::SetNull),
|
|
||||||
)
|
|
||||||
.to_owned(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
manager
|
manager
|
||||||
.alter_table(
|
.drop_postgres_auto_update_ts_trigger_for_col(Downloads::Table, GeneralIds::UpdatedAt)
|
||||||
Table::alter()
|
|
||||||
.table(Episodes::Table)
|
|
||||||
.drop_foreign_key(Alias::new("fk_episodes_download_id"))
|
|
||||||
.drop_column(Episodes::DownloadId)
|
|
||||||
.to_owned(),
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
manager
|
manager
|
||||||
@ -123,6 +171,18 @@ impl MigrationTrait for Migration {
|
|||||||
.drop_postgres_enum_for_active_enum(DownloadStatusEnum)
|
.drop_postgres_enum_for_active_enum(DownloadStatusEnum)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.drop_postgres_auto_update_ts_trigger_for_col(Downloaders::Table, GeneralIds::UpdatedAt)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Downloaders::Table).to_owned())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.drop_postgres_enum_for_active_enum(DownloaderCategoryEnum)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,10 @@ use sea_orm_migration::{prelude::*, schema::*};
|
|||||||
use super::defs::Auth;
|
use super::defs::Auth;
|
||||||
use crate::{
|
use crate::{
|
||||||
migrations::defs::{CustomSchemaManagerExt, GeneralIds, Subscribers},
|
migrations::defs::{CustomSchemaManagerExt, GeneralIds, Subscribers},
|
||||||
models::auth::{AuthType, AuthTypeEnum},
|
models::{
|
||||||
|
auth::{AuthType, AuthTypeEnum},
|
||||||
|
subscribers::SEED_SUBSCRIBER,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(DeriveMigrationName)]
|
#[derive(DeriveMigrationName)]
|
||||||
@ -40,7 +43,7 @@ impl MigrationTrait for Migration {
|
|||||||
.to_tbl(Subscribers::Table)
|
.to_tbl(Subscribers::Table)
|
||||||
.to_col(Subscribers::Id)
|
.to_col(Subscribers::Id)
|
||||||
.on_delete(ForeignKeyAction::Cascade)
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
.on_update(ForeignKeyAction::Restrict),
|
.on_update(ForeignKeyAction::Cascade),
|
||||||
)
|
)
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
)
|
)
|
||||||
@ -62,6 +65,20 @@ impl MigrationTrait for Migration {
|
|||||||
.create_postgres_auto_update_ts_trigger_for_col(Auth::Table, GeneralIds::UpdatedAt)
|
.create_postgres_auto_update_ts_trigger_for_col(Auth::Table, GeneralIds::UpdatedAt)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
manager
|
||||||
|
.exec_stmt(
|
||||||
|
Query::insert()
|
||||||
|
.into_table(Auth::Table)
|
||||||
|
.columns([Auth::Pid, Auth::AuthType, Auth::SubscriberId])
|
||||||
|
.values_panic([
|
||||||
|
SEED_SUBSCRIBER.into(),
|
||||||
|
SimpleExpr::from(AuthType::Basic).as_enum(AuthTypeEnum),
|
||||||
|
1.into(),
|
||||||
|
])
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ pub use sea_orm_migration::prelude::*;
|
|||||||
pub mod defs;
|
pub mod defs;
|
||||||
pub mod m20220101_000001_init;
|
pub mod m20220101_000001_init;
|
||||||
pub mod m20240224_082543_add_downloads;
|
pub mod m20240224_082543_add_downloads;
|
||||||
pub mod m20240225_060853_subscriber_add_downloader;
|
|
||||||
pub mod m20241231_000001_auth;
|
pub mod m20241231_000001_auth;
|
||||||
|
|
||||||
pub struct Migrator;
|
pub struct Migrator;
|
||||||
@ -15,7 +14,6 @@ impl MigratorTrait for Migrator {
|
|||||||
vec![
|
vec![
|
||||||
Box::new(m20220101_000001_init::Migration),
|
Box::new(m20220101_000001_init::Migration),
|
||||||
Box::new(m20240224_082543_add_downloads::Migration),
|
Box::new(m20240224_082543_add_downloads::Migration),
|
||||||
Box::new(m20240225_060853_subscriber_add_downloader::Migration),
|
|
||||||
Box::new(m20241231_000001_auth::Migration),
|
Box::new(m20241231_000001_auth::Migration),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,54 @@
|
|||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub use super::entities::auth::*;
|
#[derive(
|
||||||
|
Clone, Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, DeriveDisplay, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
|
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "auth_type")]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum AuthType {
|
||||||
|
#[sea_orm(string_value = "basic")]
|
||||||
|
Basic,
|
||||||
|
#[sea_orm(string_value = "oidc")]
|
||||||
|
Oidc,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "auth")]
|
||||||
|
pub struct Model {
|
||||||
|
pub created_at: DateTime,
|
||||||
|
pub updated_at: DateTime,
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub pid: String,
|
||||||
|
pub subscriber_id: i32,
|
||||||
|
pub auth_type: AuthType,
|
||||||
|
pub avatar_url: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::subscribers::Entity",
|
||||||
|
from = "Column::SubscriberId",
|
||||||
|
to = "super::subscribers::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
SubscriberId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscribers::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::SubscriberId.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelatedEntity)]
|
||||||
|
pub enum RelatedEntity {
|
||||||
|
#[sea_orm(entity = "super::subscribers::Entity")]
|
||||||
|
Subscriber,
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
@ -1,7 +1,87 @@
|
|||||||
use loco_rs::app::AppContext;
|
use loco_rs::app::AppContext;
|
||||||
use sea_orm::{entity::prelude::*, ActiveValue, TryIntoModel};
|
use sea_orm::{entity::prelude::*, sea_query::OnConflict, ActiveValue, FromJsonQueryResult};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub use super::entities::bangumi::*;
|
use super::subscription_bangumi;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
|
||||||
|
pub struct BangumiFilter {
|
||||||
|
pub name: Option<Vec<String>>,
|
||||||
|
pub group: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
|
||||||
|
pub struct BangumiExtra {
|
||||||
|
pub name_zh: Option<String>,
|
||||||
|
pub s_name_zh: Option<String>,
|
||||||
|
pub name_en: Option<String>,
|
||||||
|
pub s_name_en: Option<String>,
|
||||||
|
pub name_jp: Option<String>,
|
||||||
|
pub s_name_jp: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "bangumi")]
|
||||||
|
pub struct Model {
|
||||||
|
pub created_at: DateTime,
|
||||||
|
pub updated_at: DateTime,
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub mikan_bangumi_id: Option<String>,
|
||||||
|
pub subscriber_id: i32,
|
||||||
|
pub display_name: String,
|
||||||
|
pub raw_name: String,
|
||||||
|
pub season: i32,
|
||||||
|
pub season_raw: Option<String>,
|
||||||
|
pub fansub: Option<String>,
|
||||||
|
pub mikan_fansub_id: Option<String>,
|
||||||
|
pub filter: Option<BangumiFilter>,
|
||||||
|
pub rss_link: Option<String>,
|
||||||
|
pub poster_link: Option<String>,
|
||||||
|
pub save_path: Option<String>,
|
||||||
|
#[sea_orm(default = "false")]
|
||||||
|
pub deleted: bool,
|
||||||
|
pub homepage: Option<String>,
|
||||||
|
pub extra: Option<BangumiExtra>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(has_many = "super::subscriptions::Entity")]
|
||||||
|
Subscription,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::subscribers::Entity",
|
||||||
|
from = "Column::SubscriberId",
|
||||||
|
to = "super::subscribers::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Subscriber,
|
||||||
|
#[sea_orm(has_many = "super::episodes::Entity")]
|
||||||
|
Episode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::episodes::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Episode.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscriptions::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
super::subscription_bangumi::Relation::Subscription.def()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn via() -> Option<RelationDef> {
|
||||||
|
Some(super::subscription_bangumi::Relation::Bangumi.def().rev())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscribers::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Subscriber.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Model {
|
impl Model {
|
||||||
pub async fn get_or_insert_from_mikan<F>(
|
pub async fn get_or_insert_from_mikan<F>(
|
||||||
@ -30,12 +110,37 @@ impl Model {
|
|||||||
let mut bgm = ActiveModel {
|
let mut bgm = ActiveModel {
|
||||||
mikan_bangumi_id: ActiveValue::Set(Some(mikan_bangumi_id)),
|
mikan_bangumi_id: ActiveValue::Set(Some(mikan_bangumi_id)),
|
||||||
mikan_fansub_id: ActiveValue::Set(Some(mikan_fansub_id)),
|
mikan_fansub_id: ActiveValue::Set(Some(mikan_fansub_id)),
|
||||||
subscription_id: ActiveValue::Set(subscription_id),
|
|
||||||
subscriber_id: ActiveValue::Set(subscriber_id),
|
subscriber_id: ActiveValue::Set(subscriber_id),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
f(&mut bgm).await?;
|
f(&mut bgm).await?;
|
||||||
let bgm: Model = bgm.save(db).await?.try_into_model()?;
|
let bgm = Entity::insert(bgm)
|
||||||
|
.on_conflict(
|
||||||
|
OnConflict::columns([
|
||||||
|
Column::MikanBangumiId,
|
||||||
|
Column::MikanFansubId,
|
||||||
|
Column::SubscriberId,
|
||||||
|
])
|
||||||
|
.update_columns([
|
||||||
|
Column::RawName,
|
||||||
|
Column::Extra,
|
||||||
|
Column::Fansub,
|
||||||
|
Column::PosterLink,
|
||||||
|
Column::Season,
|
||||||
|
Column::SeasonRaw,
|
||||||
|
])
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.exec_with_returning(db)
|
||||||
|
.await?;
|
||||||
|
subscription_bangumi::Entity::insert(subscription_bangumi::ActiveModel {
|
||||||
|
subscription_id: ActiveValue::Set(subscription_id),
|
||||||
|
bangumi_id: ActiveValue::Set(bgm.id),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.on_conflict_do_nothing()
|
||||||
|
.exec(db)
|
||||||
|
.await?;
|
||||||
Ok(bgm)
|
Ok(bgm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,59 @@
|
|||||||
use sea_orm::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub use crate::models::entities::downloaders::*;
|
#[derive(
|
||||||
|
Clone, Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, DeriveDisplay, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
|
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "downloader_type")]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum DownloaderCategory {
|
||||||
|
#[sea_orm(string_value = "qbittorrent")]
|
||||||
|
QBittorrent,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "downloaders")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(column_type = "Timestamp")]
|
||||||
|
pub created_at: DateTime,
|
||||||
|
#[sea_orm(column_type = "Timestamp")]
|
||||||
|
pub updated_at: DateTime,
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub category: DownloaderCategory,
|
||||||
|
pub endpoint: String,
|
||||||
|
pub password: String,
|
||||||
|
pub username: String,
|
||||||
|
pub subscriber_id: i32,
|
||||||
|
pub save_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::subscribers::Entity",
|
||||||
|
from = "Column::SubscriberId",
|
||||||
|
to = "super::subscribers::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Subscriber,
|
||||||
|
#[sea_orm(has_many = "super::downloads::Entity")]
|
||||||
|
Download,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscribers::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Subscriber.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::downloads::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Download.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
@ -10,6 +62,7 @@ impl Model {
|
|||||||
pub fn get_endpoint(&self) -> String {
|
pub fn get_endpoint(&self) -> String {
|
||||||
self.endpoint.clone()
|
self.endpoint.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endpoint_url(&self) -> Result<Url, url::ParseError> {
|
pub fn endpoint_url(&self) -> Result<Url, url::ParseError> {
|
||||||
let url = Url::parse(&self.endpoint)?;
|
let url = Url::parse(&self.endpoint)?;
|
||||||
Ok(url)
|
Ok(url)
|
||||||
|
@ -1,27 +1,107 @@
|
|||||||
use sea_orm::{prelude::*, ActiveValue};
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::extract::mikan::MikanRssItem;
|
#[derive(
|
||||||
pub use crate::models::entities::downloads::*;
|
Clone, Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, DeriveDisplay, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
|
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "download_status")]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum DownloadStatus {
|
||||||
|
#[sea_orm(string_value = "pending")]
|
||||||
|
Pending,
|
||||||
|
#[sea_orm(string_value = "downloading")]
|
||||||
|
Downloading,
|
||||||
|
#[sea_orm(string_value = "paused")]
|
||||||
|
Paused,
|
||||||
|
#[sea_orm(string_value = "completed")]
|
||||||
|
Completed,
|
||||||
|
#[sea_orm(string_value = "failed")]
|
||||||
|
Failed,
|
||||||
|
#[sea_orm(string_value = "deleted")]
|
||||||
|
Deleted,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone, Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, DeriveDisplay, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
|
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "download_mime")]
|
||||||
|
pub enum DownloadMime {
|
||||||
|
#[sea_orm(string_value = "application/octet-stream")]
|
||||||
|
#[serde(rename = "application/octet-stream")]
|
||||||
|
OctetStream,
|
||||||
|
#[sea_orm(string_value = "application/x-bittorrent")]
|
||||||
|
#[serde(rename = "application/x-bittorrent")]
|
||||||
|
BitTorrent,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "downloads")]
|
||||||
|
pub struct Model {
|
||||||
|
pub created_at: DateTime,
|
||||||
|
pub updated_at: DateTime,
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub raw_name: String,
|
||||||
|
pub display_name: String,
|
||||||
|
pub downloader_id: i32,
|
||||||
|
pub episode_id: i32,
|
||||||
|
pub subscriber_id: i32,
|
||||||
|
pub status: DownloadStatus,
|
||||||
|
pub mime: DownloadMime,
|
||||||
|
pub url: String,
|
||||||
|
pub all_size: Option<u64>,
|
||||||
|
pub curr_size: Option<u64>,
|
||||||
|
pub homepage: Option<String>,
|
||||||
|
pub save_path: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::subscribers::Entity",
|
||||||
|
from = "Column::SubscriberId",
|
||||||
|
to = "super::subscribers::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Subscriber,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::downloaders::Entity",
|
||||||
|
from = "Column::DownloaderId",
|
||||||
|
to = "super::downloaders::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Downloader,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::episodes::Entity",
|
||||||
|
from = "Column::EpisodeId",
|
||||||
|
to = "super::episodes::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Episode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscribers::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Subscriber.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::downloaders::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Downloader.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::episodes::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Episode.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
impl ActiveModel {
|
impl ActiveModel {}
|
||||||
pub fn from_mikan_rss_item(m: MikanRssItem, subscription_id: i32) -> Self {
|
|
||||||
let _ = Self {
|
|
||||||
origin_name: ActiveValue::Set(m.title.clone()),
|
|
||||||
display_name: ActiveValue::Set(m.title),
|
|
||||||
subscription_id: ActiveValue::Set(subscription_id),
|
|
||||||
status: ActiveValue::Set(DownloadStatus::Pending),
|
|
||||||
mime: ActiveValue::Set(DownloadMime::BitTorrent),
|
|
||||||
url: ActiveValue::Set(m.url.to_string()),
|
|
||||||
curr_size: ActiveValue::Set(m.content_length.as_ref().map(|_| 0)),
|
|
||||||
all_size: ActiveValue::Set(m.content_length),
|
|
||||||
homepage: ActiveValue::Set(Some(m.homepage.to_string())),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Model {}
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use loco_rs::app::AppContext;
|
use loco_rs::app::AppContext;
|
||||||
use sea_orm::{entity::prelude::*, sea_query::OnConflict, ActiveValue};
|
use sea_orm::{entity::prelude::*, sea_query::OnConflict, ActiveValue, FromJsonQueryResult};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::bangumi;
|
use super::{bangumi, query::InsertManyReturningExt, subscription_episode};
|
||||||
pub use super::entities::episodes::*;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::AppContextExt,
|
app::AppContextExt,
|
||||||
extract::{
|
extract::{
|
||||||
@ -13,6 +13,92 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult, Default)]
|
||||||
|
pub struct EpisodeExtra {
|
||||||
|
pub name_zh: Option<String>,
|
||||||
|
pub s_name_zh: Option<String>,
|
||||||
|
pub name_en: Option<String>,
|
||||||
|
pub s_name_en: Option<String>,
|
||||||
|
pub name_jp: Option<String>,
|
||||||
|
pub s_name_jp: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "episodes")]
|
||||||
|
pub struct Model {
|
||||||
|
pub created_at: DateTime,
|
||||||
|
pub updated_at: DateTime,
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
#[sea_orm(indexed)]
|
||||||
|
pub mikan_episode_id: Option<String>,
|
||||||
|
pub raw_name: String,
|
||||||
|
pub display_name: String,
|
||||||
|
pub bangumi_id: i32,
|
||||||
|
pub subscriber_id: i32,
|
||||||
|
pub save_path: Option<String>,
|
||||||
|
pub resolution: Option<String>,
|
||||||
|
pub season: i32,
|
||||||
|
pub season_raw: Option<String>,
|
||||||
|
pub fansub: Option<String>,
|
||||||
|
pub poster_link: Option<String>,
|
||||||
|
pub episode_index: i32,
|
||||||
|
pub homepage: Option<String>,
|
||||||
|
pub subtitle: Option<Vec<String>>,
|
||||||
|
#[sea_orm(default = "false")]
|
||||||
|
pub deleted: bool,
|
||||||
|
pub source: Option<String>,
|
||||||
|
pub extra: EpisodeExtra,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::subscribers::Entity",
|
||||||
|
from = "Column::SubscriberId",
|
||||||
|
to = "super::subscribers::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Subscriber,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::bangumi::Entity",
|
||||||
|
from = "Column::BangumiId",
|
||||||
|
to = "super::bangumi::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Bangumi,
|
||||||
|
#[sea_orm(has_many = "super::subscriptions::Entity")]
|
||||||
|
Subscriptions,
|
||||||
|
#[sea_orm(has_one = "super::downloads::Entity")]
|
||||||
|
Downloads,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::bangumi::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Bangumi.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::downloads::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Downloads.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscriptions::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Subscriptions.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscribers::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Subscriber.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct MikanEpsiodeCreation {
|
pub struct MikanEpsiodeCreation {
|
||||||
pub episode: MikanEpisodeMeta,
|
pub episode: MikanEpisodeMeta,
|
||||||
@ -22,6 +108,7 @@ pub struct MikanEpsiodeCreation {
|
|||||||
impl Model {
|
impl Model {
|
||||||
pub async fn add_episodes(
|
pub async fn add_episodes(
|
||||||
ctx: &AppContext,
|
ctx: &AppContext,
|
||||||
|
subscription_id: i32,
|
||||||
creations: impl IntoIterator<Item = MikanEpsiodeCreation>,
|
creations: impl IntoIterator<Item = MikanEpsiodeCreation>,
|
||||||
) -> eyre::Result<()> {
|
) -> eyre::Result<()> {
|
||||||
let db = &ctx.db;
|
let db = &ctx.db;
|
||||||
@ -35,13 +122,33 @@ impl Model {
|
|||||||
})
|
})
|
||||||
.flatten();
|
.flatten();
|
||||||
|
|
||||||
Entity::insert_many(new_episode_active_modes)
|
let inserted_episodes = Entity::insert_many(new_episode_active_modes)
|
||||||
.on_conflict(
|
.on_conflict(
|
||||||
OnConflict::columns([Column::BangumiId, Column::MikanEpisodeId])
|
OnConflict::columns([Column::BangumiId, Column::MikanEpisodeId])
|
||||||
.do_nothing()
|
.do_nothing()
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
)
|
)
|
||||||
.on_empty_do_nothing()
|
.exec_with_returning_columns(db, [Column::Id])
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|r| r.try_get_many_by_index::<i32>());
|
||||||
|
|
||||||
|
let insert_subscription_episode_links = inserted_episodes.into_iter().map(|episode_id| {
|
||||||
|
subscription_episode::ActiveModel::from_subscription_and_episode(
|
||||||
|
subscription_id,
|
||||||
|
episode_id,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
subscription_episode::Entity::insert_many(insert_subscription_episode_links)
|
||||||
|
.on_conflict(
|
||||||
|
OnConflict::columns([
|
||||||
|
subscription_episode::Column::SubscriptionId,
|
||||||
|
subscription_episode::Column::EpisodeId,
|
||||||
|
])
|
||||||
|
.do_nothing()
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
.exec(db)
|
.exec(db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@ -72,7 +179,6 @@ impl ActiveModel {
|
|||||||
raw_name: ActiveValue::Set(item.episode_title.clone()),
|
raw_name: ActiveValue::Set(item.episode_title.clone()),
|
||||||
display_name: ActiveValue::Set(item.episode_title.clone()),
|
display_name: ActiveValue::Set(item.episode_title.clone()),
|
||||||
bangumi_id: ActiveValue::Set(bgm.id),
|
bangumi_id: ActiveValue::Set(bgm.id),
|
||||||
subscription_id: ActiveValue::Set(bgm.subscription_id),
|
|
||||||
subscriber_id: ActiveValue::Set(bgm.subscriber_id),
|
subscriber_id: ActiveValue::Set(bgm.subscriber_id),
|
||||||
resolution: ActiveValue::Set(raw_meta.resolution),
|
resolution: ActiveValue::Set(raw_meta.resolution),
|
||||||
season: ActiveValue::Set(if raw_meta.season > 0 {
|
season: ActiveValue::Set(if raw_meta.season > 0 {
|
||||||
|
@ -2,10 +2,10 @@ pub mod auth;
|
|||||||
pub mod bangumi;
|
pub mod bangumi;
|
||||||
pub mod downloaders;
|
pub mod downloaders;
|
||||||
pub mod downloads;
|
pub mod downloads;
|
||||||
pub mod entities;
|
|
||||||
pub mod episodes;
|
pub mod episodes;
|
||||||
pub mod notifications;
|
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
pub mod query;
|
pub mod query;
|
||||||
pub mod subscribers;
|
pub mod subscribers;
|
||||||
|
pub mod subscription_bangumi;
|
||||||
|
pub mod subscription_episode;
|
||||||
pub mod subscriptions;
|
pub mod subscriptions;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
prelude::Expr,
|
prelude::Expr,
|
||||||
sea_query::{Alias, IntoColumnRef, IntoTableRef, Query, SelectStatement},
|
sea_query::{Alias, IntoColumnRef, IntoTableRef, Query, SelectStatement},
|
||||||
Value,
|
ActiveModelTrait, ColumnTrait, ConnectionTrait, DbErr, EntityTrait, Insert, IntoActiveModel,
|
||||||
|
Iterable, QueryResult, QueryTrait, SelectModel, SelectorRaw, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn filter_values_in<
|
pub fn filter_values_in<
|
||||||
@ -24,3 +25,76 @@ pub fn filter_values_in<
|
|||||||
.and_where(Expr::col(col_ref).is_not_null())
|
.and_where(Expr::col(col_ref).is_not_null())
|
||||||
.to_owned()
|
.to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
pub trait InsertManyReturningExt<A>: Sized
|
||||||
|
where
|
||||||
|
<A::Entity as EntityTrait>::Model: IntoActiveModel<A>,
|
||||||
|
A: ActiveModelTrait,
|
||||||
|
{
|
||||||
|
fn exec_with_returning_models<C>(
|
||||||
|
self,
|
||||||
|
db: &C,
|
||||||
|
) -> SelectorRaw<SelectModel<<A::Entity as EntityTrait>::Model>>
|
||||||
|
where
|
||||||
|
C: ConnectionTrait;
|
||||||
|
|
||||||
|
async fn exec_with_returning_columns<C, I>(
|
||||||
|
self,
|
||||||
|
db: &C,
|
||||||
|
columns: I,
|
||||||
|
) -> Result<Vec<QueryResult>, DbErr>
|
||||||
|
where
|
||||||
|
C: ConnectionTrait,
|
||||||
|
I: IntoIterator<Item = <A::Entity as EntityTrait>::Column> + Send;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<A> InsertManyReturningExt<A> for Insert<A>
|
||||||
|
where
|
||||||
|
<A::Entity as EntityTrait>::Model: IntoActiveModel<A>,
|
||||||
|
A: ActiveModelTrait + Send,
|
||||||
|
{
|
||||||
|
fn exec_with_returning_models<C>(
|
||||||
|
self,
|
||||||
|
db: &C,
|
||||||
|
) -> SelectorRaw<SelectModel<<A::Entity as EntityTrait>::Model>>
|
||||||
|
where
|
||||||
|
C: ConnectionTrait,
|
||||||
|
{
|
||||||
|
let mut insert_statement = self.into_query();
|
||||||
|
let db_backend = db.get_database_backend();
|
||||||
|
let returning = Query::returning().exprs(
|
||||||
|
<A::Entity as EntityTrait>::Column::iter()
|
||||||
|
.map(|c| c.select_as(c.into_returning_expr(db_backend))),
|
||||||
|
);
|
||||||
|
insert_statement.returning(returning);
|
||||||
|
let insert_statement = db_backend.build(&insert_statement);
|
||||||
|
SelectorRaw::<SelectModel<<A::Entity as EntityTrait>::Model>>::from_statement(
|
||||||
|
insert_statement,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn exec_with_returning_columns<C, I>(
|
||||||
|
self,
|
||||||
|
db: &C,
|
||||||
|
columns: I,
|
||||||
|
) -> Result<Vec<QueryResult>, DbErr>
|
||||||
|
where
|
||||||
|
C: ConnectionTrait,
|
||||||
|
I: IntoIterator<Item = <A::Entity as EntityTrait>::Column> + Send,
|
||||||
|
{
|
||||||
|
let mut insert_statement = self.into_query();
|
||||||
|
let db_backend = db.get_database_backend();
|
||||||
|
let returning = Query::returning().exprs(
|
||||||
|
columns
|
||||||
|
.into_iter()
|
||||||
|
.map(|c| c.select_as(c.into_returning_expr(db_backend))),
|
||||||
|
);
|
||||||
|
insert_statement.returning(returning);
|
||||||
|
|
||||||
|
let statement = db_backend.build(&insert_statement);
|
||||||
|
|
||||||
|
db.query_all(statement).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,13 +2,73 @@ use loco_rs::{
|
|||||||
app::AppContext,
|
app::AppContext,
|
||||||
model::{ModelError, ModelResult},
|
model::{ModelError, ModelResult},
|
||||||
};
|
};
|
||||||
use sea_orm::{entity::prelude::*, ActiveValue, TransactionTrait};
|
use sea_orm::{entity::prelude::*, ActiveValue, FromJsonQueryResult, TransactionTrait};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub use super::entities::subscribers::*;
|
|
||||||
|
|
||||||
pub const SEED_SUBSCRIBER: &str = "konobangu";
|
pub const SEED_SUBSCRIBER: &str = "konobangu";
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
|
||||||
|
pub struct SubscriberBangumiConfig {
|
||||||
|
pub leading_group_tag: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "subscribers")]
|
||||||
|
pub struct Model {
|
||||||
|
pub created_at: DateTime,
|
||||||
|
pub updated_at: DateTime,
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
#[sea_orm(unique)]
|
||||||
|
pub pid: String,
|
||||||
|
pub display_name: String,
|
||||||
|
pub bangumi_conf: Option<SubscriberBangumiConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(has_many = "super::subscriptions::Entity")]
|
||||||
|
Subscription,
|
||||||
|
#[sea_orm(has_many = "super::downloaders::Entity")]
|
||||||
|
Downloader,
|
||||||
|
#[sea_orm(has_many = "super::bangumi::Entity")]
|
||||||
|
Bangumi,
|
||||||
|
#[sea_orm(has_many = "super::episodes::Entity")]
|
||||||
|
Episode,
|
||||||
|
#[sea_orm(has_many = "super::auth::Entity")]
|
||||||
|
Auth,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscriptions::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Subscription.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::downloaders::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Downloader.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::bangumi::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Bangumi.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::episodes::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Episode.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::auth::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Auth.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct SubscriberIdParams {
|
pub struct SubscriberIdParams {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
56
apps/recorder/src/models/subscription_bangumi.rs
Normal file
56
apps/recorder/src/models/subscription_bangumi.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use sea_orm::{entity::prelude::*, ActiveValue};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "subscription_bangumi")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub subscription_id: i32,
|
||||||
|
pub bangumi_id: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::subscriptions::Entity",
|
||||||
|
from = "Column::SubscriptionId",
|
||||||
|
to = "super::subscriptions::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Subscription,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::bangumi::Entity",
|
||||||
|
from = "Column::BangumiId",
|
||||||
|
to = "super::bangumi::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Bangumi,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscriptions::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Subscription.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::bangumi::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Bangumi.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
impl ActiveModel {
|
||||||
|
pub fn from_subscription_and_bangumi(subscription_id: i32, bangumi_id: i32) -> Self {
|
||||||
|
Self {
|
||||||
|
subscription_id: ActiveValue::Set(subscription_id),
|
||||||
|
bangumi_id: ActiveValue::Set(bangumi_id),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
apps/recorder/src/models/subscription_episode.rs
Normal file
56
apps/recorder/src/models/subscription_episode.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use sea_orm::{entity::prelude::*, ActiveValue};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "subscription_episode")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub subscription_id: i32,
|
||||||
|
pub episode_id: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::subscriptions::Entity",
|
||||||
|
from = "Column::SubscriptionId",
|
||||||
|
to = "super::subscriptions::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Subscription,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::episodes::Entity",
|
||||||
|
from = "Column::EpisodeId",
|
||||||
|
to = "super::episodes::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Episode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscriptions::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Subscription.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::episodes::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Episode.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
impl ActiveModel {
|
||||||
|
pub fn from_subscription_and_episode(subscription_id: i32, episode_id: i32) -> Self {
|
||||||
|
Self {
|
||||||
|
subscription_id: ActiveValue::Set(subscription_id),
|
||||||
|
episode_id: ActiveValue::Set(episode_id),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,6 @@ use loco_rs::app::AppContext;
|
|||||||
use sea_orm::{entity::prelude::*, ActiveValue};
|
use sea_orm::{entity::prelude::*, ActiveValue};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub use super::entities::subscriptions::{self, *};
|
|
||||||
use super::{bangumi, episodes, query::filter_values_in};
|
use super::{bangumi, episodes, query::filter_values_in};
|
||||||
use crate::{
|
use crate::{
|
||||||
app::AppContextExt,
|
app::AppContextExt,
|
||||||
@ -24,6 +23,92 @@ use crate::{
|
|||||||
models::episodes::MikanEpsiodeCreation,
|
models::episodes::MikanEpsiodeCreation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone, Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize, DeriveDisplay,
|
||||||
|
)]
|
||||||
|
#[sea_orm(
|
||||||
|
rs_type = "String",
|
||||||
|
db_type = "Enum",
|
||||||
|
enum_name = "subscription_category"
|
||||||
|
)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum SubscriptionCategory {
|
||||||
|
#[sea_orm(string_value = "mikan")]
|
||||||
|
Mikan,
|
||||||
|
#[sea_orm(string_value = "manual")]
|
||||||
|
Manual,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "subscriptions")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(column_type = "Timestamp")]
|
||||||
|
pub created_at: DateTime,
|
||||||
|
#[sea_orm(column_type = "Timestamp")]
|
||||||
|
pub updated_at: DateTime,
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub display_name: String,
|
||||||
|
pub subscriber_id: i32,
|
||||||
|
pub category: SubscriptionCategory,
|
||||||
|
pub source_url: String,
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::subscribers::Entity",
|
||||||
|
from = "Column::SubscriberId",
|
||||||
|
to = "super::subscribers::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Subscriber,
|
||||||
|
#[sea_orm(has_many = "super::bangumi::Entity")]
|
||||||
|
Bangumi,
|
||||||
|
#[sea_orm(has_many = "super::episodes::Entity")]
|
||||||
|
Episodes,
|
||||||
|
#[sea_orm(has_many = "super::subscription_episode::Entity")]
|
||||||
|
SubscriptionEpisode,
|
||||||
|
#[sea_orm(has_many = "super::subscription_bangumi::Entity")]
|
||||||
|
SubscriptionBangumi,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::subscribers::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Subscriber.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::bangumi::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
super::subscription_bangumi::Relation::Bangumi.def()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn via() -> Option<RelationDef> {
|
||||||
|
Some(
|
||||||
|
super::subscription_bangumi::Relation::Subscription
|
||||||
|
.def()
|
||||||
|
.rev(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::episodes::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
super::subscription_episode::Relation::Episode.def()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn via() -> Option<RelationDef> {
|
||||||
|
Some(
|
||||||
|
super::subscription_episode::Relation::Subscription
|
||||||
|
.def()
|
||||||
|
.rev(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct SubscriptionCreateFromRssDto {
|
pub struct SubscriptionCreateFromRssDto {
|
||||||
pub rss_link: String,
|
pub rss_link: String,
|
||||||
@ -77,7 +162,7 @@ impl Model {
|
|||||||
Ok(subscription.insert(db).await?)
|
Ok(subscription.insert(db).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn toggle_iters(
|
pub async fn toggle_with_ids(
|
||||||
ctx: &AppContext,
|
ctx: &AppContext,
|
||||||
ids: impl Iterator<Item = i32>,
|
ids: impl Iterator<Item = i32>,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
@ -91,7 +176,7 @@ impl Model {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_iters(
|
pub async fn delete_with_ids(
|
||||||
ctx: &AppContext,
|
ctx: &AppContext,
|
||||||
ids: impl Iterator<Item = i32>,
|
ids: impl Iterator<Item = i32>,
|
||||||
) -> eyre::Result<()> {
|
) -> eyre::Result<()> {
|
||||||
@ -213,6 +298,7 @@ impl Model {
|
|||||||
);
|
);
|
||||||
episodes::Model::add_episodes(
|
episodes::Model::add_episodes(
|
||||||
ctx,
|
ctx,
|
||||||
|
self.id,
|
||||||
new_ep_metas.into_iter().map(|item| MikanEpsiodeCreation {
|
new_ep_metas.into_iter().map(|item| MikanEpsiodeCreation {
|
||||||
episode: item,
|
episode: item,
|
||||||
bangumi: bgm.clone(),
|
bangumi: bgm.clone(),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::models::entities::subscribers;
|
use crate::models::subscribers;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct CurrentResponse {
|
pub struct CurrentResponse {
|
||||||
|
Loading…
Reference in New Issue
Block a user