You've already forked flix
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
dd688fdc83
|
|||
|
0d34174a13
|
|||
|
8411c75377
|
|||
|
6eec67a0fd
|
Generated
+292
-353
File diff suppressed because it is too large
Load Diff
+10
-10
@@ -6,7 +6,7 @@ resolver = "2"
|
|||||||
authors = []
|
authors = []
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license-file = "LICENSE.md"
|
license-file = "LICENSE.md"
|
||||||
rust-version = "1.85.0"
|
rust-version = "1.88.0"
|
||||||
|
|
||||||
[workspace.lints.rust]
|
[workspace.lints.rust]
|
||||||
arithmetic_overflow = "forbid"
|
arithmetic_overflow = "forbid"
|
||||||
@@ -35,17 +35,17 @@ overflow-checks = true
|
|||||||
strip = "debuginfo"
|
strip = "debuginfo"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
flix = { path = "crates/flix", version = "=0.0.9", default-features = false }
|
flix = { path = "crates/flix", version = "=0.0.12", default-features = false }
|
||||||
flix-cli = { path = "crates/cli", version = "=0.0.9", default-features = false }
|
flix-cli = { path = "crates/cli", version = "=0.0.12", default-features = false }
|
||||||
flix-db = { path = "crates/db", version = "=0.0.9", default-features = false }
|
flix-db = { path = "crates/db", version = "=0.0.12", default-features = false }
|
||||||
flix-fs = { path = "crates/fs", version = "=0.0.9", default-features = false }
|
flix-fs = { path = "crates/fs", version = "=0.0.12", default-features = false }
|
||||||
flix-model = { path = "crates/model", version = "=0.0.9", default-features = false }
|
flix-model = { path = "crates/model", version = "=0.0.12", default-features = false }
|
||||||
flix-tmdb = { path = "crates/tmdb", version = "=0.0.9", default-features = false }
|
flix-tmdb = { path = "crates/tmdb", version = "=0.0.12", default-features = false }
|
||||||
|
|
||||||
seamantic = { version = "0.0.5", default-features = false }
|
seamantic = { version = "0.0.9", default-features = false }
|
||||||
|
|
||||||
sea-orm = { version = "2.0.0-rc.7", default-features = false }
|
sea-orm = { version = "2.0.0-rc.16", default-features = false }
|
||||||
sea-orm-migration = { version = "2.0.0-rc.7", default-features = false }
|
sea-orm-migration = { version = "2.0.0-rc.16", default-features = false }
|
||||||
|
|
||||||
anyhow = { version = "^1", default-features = false }
|
anyhow = { version = "^1", default-features = false }
|
||||||
async-stream = { version = "^0.3", default-features = false }
|
async-stream = { version = "^0.3", default-features = false }
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ Libraries and tools for dealing with media metadata
|
|||||||
- build: `cargo hack --feature-powerset build`
|
- build: `cargo hack --feature-powerset build`
|
||||||
- clippy: `cargo hack --feature-powerset clippy -- -D warnings`
|
- clippy: `cargo hack --feature-powerset clippy -- -D warnings`
|
||||||
- test: `cargo hack --feature-powerset test`
|
- test: `cargo hack --feature-powerset test`
|
||||||
- test old: `cargo +1.85 hack --feature-powerset test`
|
- test old: `cargo +1.88 hack --feature-powerset test`
|
||||||
- fmt: `cargo fmt --check`
|
- fmt: `cargo fmt --check`
|
||||||
- docs: `RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features`
|
- docs: `RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features`
|
||||||
- install: `cargo install --path crates/cli`
|
- install: `cargo install --path crates/cli`
|
||||||
|
- semver: `cargo semver-checks --all-features`
|
||||||
- publish: `cargo publish --dry-run --workspace`
|
- publish: `cargo publish --dry-run --workspace`
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix-cli"
|
name = "flix-cli"
|
||||||
version = "0.0.9"
|
version = "0.0.12"
|
||||||
|
|
||||||
categories = ["command-line-utilities"]
|
categories = ["command-line-utilities"]
|
||||||
description = "CLI for interacting with a flix database"
|
description = "CLI for interacting with a flix database"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix-db"
|
name = "flix-db"
|
||||||
version = "0.0.9"
|
version = "0.0.12"
|
||||||
|
|
||||||
categories = []
|
categories = []
|
||||||
description = "Types for storing persistent data about media"
|
description = "Types for storing persistent data about media"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use sea_orm_migration::MigratorTrait as _;
|
|||||||
pub struct Connection(DatabaseConnection);
|
pub struct Connection(DatabaseConnection);
|
||||||
|
|
||||||
impl Connection {
|
impl Connection {
|
||||||
/// Helper function for apllying database migrations while wrapping a
|
/// Helper function for applying database migrations while wrapping a
|
||||||
/// [DatabaseConnection] in a newtype
|
/// [DatabaseConnection] in a newtype
|
||||||
pub async fn try_from(database: DatabaseConnection) -> Result<Self, DbErr> {
|
pub async fn try_from(database: DatabaseConnection) -> Result<Self, DbErr> {
|
||||||
crate::migration::Migrator::up(&database, None).await?;
|
crate::migration::Migrator::up(&database, None).await?;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ pub struct Model {
|
|||||||
/// The collection's directory
|
/// The collection's directory
|
||||||
pub directory: PathBytes,
|
pub directory: PathBytes,
|
||||||
/// The collection's poster path
|
/// The collection's poster path
|
||||||
pub relative_poster_path: Option<PathBytes>,
|
pub relative_poster_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
@@ -51,6 +51,24 @@ pub enum Relation {
|
|||||||
on_delete = "Cascade"
|
on_delete = "Cascade"
|
||||||
)]
|
)]
|
||||||
Library,
|
Library,
|
||||||
|
/// The media info for this collection
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::super::info::collections::Entity",
|
||||||
|
from = "Column::Id",
|
||||||
|
to = "super::super::info::collections::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
MediaInfo,
|
||||||
|
/// The watched info for this collection
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::super::watched::collections::Entity",
|
||||||
|
from = "Column::Id",
|
||||||
|
to = "super::super::watched::collections::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
WatchInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Related<super::collections::Entity> for Entity {
|
impl Related<super::collections::Entity> for Entity {
|
||||||
@@ -64,3 +82,15 @@ impl Related<super::libraries::Entity> for Entity {
|
|||||||
Relation::Library.def()
|
Relation::Library.def()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Related<super::super::info::collections::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::MediaInfo.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::super::watched::collections::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::WatchInfo.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ pub struct Model {
|
|||||||
/// The episode's number
|
/// The episode's number
|
||||||
#[sea_orm(primary_key, auto_increment = false)]
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
pub episode: EpisodeNumber,
|
pub episode: EpisodeNumber,
|
||||||
|
/// The number of additional contained episodes
|
||||||
|
pub count: u8,
|
||||||
/// The episode's slug
|
/// The episode's slug
|
||||||
pub slug: String,
|
pub slug: String,
|
||||||
/// The episode's library
|
/// The episode's library
|
||||||
@@ -30,9 +32,9 @@ pub struct Model {
|
|||||||
/// The episode's directory
|
/// The episode's directory
|
||||||
pub directory: PathBytes,
|
pub directory: PathBytes,
|
||||||
/// The episode's media path
|
/// The episode's media path
|
||||||
pub relative_media_path: PathBytes,
|
pub relative_media_path: String,
|
||||||
/// The episode's poster path
|
/// The episode's poster path
|
||||||
pub relative_poster_path: Option<PathBytes>,
|
pub relative_poster_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
@@ -49,6 +51,24 @@ pub enum Relation {
|
|||||||
on_delete = "Cascade"
|
on_delete = "Cascade"
|
||||||
)]
|
)]
|
||||||
Library,
|
Library,
|
||||||
|
/// The media info for this episode
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::super::info::episodes::Entity",
|
||||||
|
from = "(Column::Show, Column::Season, Column::Episode)",
|
||||||
|
to = "(super::super::info::episodes::Column::Show, super::super::info::episodes::Column::Season, super::super::info::episodes::Column::Episode)",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
MediaInfo,
|
||||||
|
/// The watched info for this episode
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::super::watched::episodes::Entity",
|
||||||
|
from = "(Column::Show, Column::Season, Column::Episode)",
|
||||||
|
to = "(super::super::watched::episodes::Column::Show, super::super::watched::episodes::Column::Season, super::super::watched::episodes::Column::Episode)",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
WatchInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Related<super::libraries::Entity> for Entity {
|
impl Related<super::libraries::Entity> for Entity {
|
||||||
@@ -56,3 +76,15 @@ impl Related<super::libraries::Entity> for Entity {
|
|||||||
Relation::Library.def()
|
Relation::Library.def()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Related<super::super::info::episodes::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::MediaInfo.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::super::watched::episodes::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::WatchInfo.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ mod tests {
|
|||||||
assert_eq!(model.slug, concat!("C/", $id).to_string());
|
assert_eq!(model.slug, concat!("C/", $id).to_string());
|
||||||
assert_eq!(model.library, LibraryId::from_raw($lid));
|
assert_eq!(model.library, LibraryId::from_raw($lid));
|
||||||
assert_eq!(model.directory, Path::new(concat!("/C/", $id)).to_owned().into());
|
assert_eq!(model.directory, Path::new(concat!("/C/", $id)).to_owned().into());
|
||||||
assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, Path::new(concat!("C/Poster", $id)).to_owned().into() $(, $($skip),+)?));
|
assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, concat!("C/Poster", $id).to_owned() $(, $($skip),+)?));
|
||||||
};
|
};
|
||||||
($db:expr, $id:literal, $pid:expr, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
|
($db:expr, $id:literal, $pid:expr, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
|
||||||
let model = assert_collection!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
|
let model = assert_collection!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
|
||||||
@@ -89,7 +89,7 @@ mod tests {
|
|||||||
slug: notsettable!(slug, concat!("C/", $id).to_string() $(, $($skip),+)?),
|
slug: notsettable!(slug, concat!("C/", $id).to_string() $(, $($skip),+)?),
|
||||||
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
|
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
|
||||||
directory: notsettable!(directory, Path::new(concat!("/C/", $id)).to_owned().into() $(, $($skip),+)?),
|
directory: notsettable!(directory, Path::new(concat!("/C/", $id)).to_owned().into() $(, $($skip),+)?),
|
||||||
relative_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("C/Poster", $id)).to_owned().into()) $(, $($skip),+)?),
|
relative_poster_path: notsettable!(relative_poster_path, Some(concat!("C/Poster", $id).to_owned()) $(, $($skip),+)?),
|
||||||
}.insert($db).await
|
}.insert($db).await
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -129,8 +129,8 @@ mod tests {
|
|||||||
assert_eq!(model.slug, concat!("M/", $id).to_string());
|
assert_eq!(model.slug, concat!("M/", $id).to_string());
|
||||||
assert_eq!(model.library, LibraryId::from_raw($lid));
|
assert_eq!(model.library, LibraryId::from_raw($lid));
|
||||||
assert_eq!(model.directory, Path::new(concat!("/M/", $id)).to_owned().into());
|
assert_eq!(model.directory, Path::new(concat!("/M/", $id)).to_owned().into());
|
||||||
assert_eq!(model.relative_media_path, Path::new(concat!("M/Media", $id)).to_owned().into());
|
assert_eq!(model.relative_media_path, concat!("M/Media", $id));
|
||||||
assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, Path::new(concat!("M/Poster", $id)).to_owned().into() $(, $($skip),+)?));
|
assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, concat!("M/Poster", $id).to_owned() $(, $($skip),+)?));
|
||||||
};
|
};
|
||||||
($db:expr, $id:literal, $pid:expr, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
|
($db:expr, $id:literal, $pid:expr, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
|
||||||
let model = assert_movie!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
|
let model = assert_movie!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
|
||||||
@@ -145,8 +145,8 @@ mod tests {
|
|||||||
slug: notsettable!(slug, concat!("M/", $id).to_string() $(, $($skip),+)?),
|
slug: notsettable!(slug, concat!("M/", $id).to_string() $(, $($skip),+)?),
|
||||||
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
|
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
|
||||||
directory: notsettable!(directory, Path::new(concat!("/M/", $id)).to_owned().into() $(, $($skip),+)?),
|
directory: notsettable!(directory, Path::new(concat!("/M/", $id)).to_owned().into() $(, $($skip),+)?),
|
||||||
relative_media_path: notsettable!(relative_media_path, Path::new(concat!("M/Media", $id)).to_owned().into() $(, $($skip),+)?),
|
relative_media_path: notsettable!(relative_media_path, concat!("M/Media", $id).to_owned() $(, $($skip),+)?),
|
||||||
relative_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("M/Poster", $id)).to_owned().into()) $(, $($skip),+)?),
|
relative_poster_path: notsettable!(relative_poster_path, Some(concat!("M/Poster", $id).to_owned()) $(, $($skip),+)?),
|
||||||
}.insert($db).await
|
}.insert($db).await
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -187,7 +187,7 @@ mod tests {
|
|||||||
assert_eq!(model.slug, concat!("S/", $id).to_string());
|
assert_eq!(model.slug, concat!("S/", $id).to_string());
|
||||||
assert_eq!(model.library, LibraryId::from_raw($lid));
|
assert_eq!(model.library, LibraryId::from_raw($lid));
|
||||||
assert_eq!(model.directory, Path::new(concat!("/S/", $id)).to_owned().into());
|
assert_eq!(model.directory, Path::new(concat!("/S/", $id)).to_owned().into());
|
||||||
assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, Path::new(concat!("S/Poster", $id)).to_owned().into() $(, $($skip),+)?));
|
assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, concat!("S/Poster", $id).to_owned() $(, $($skip),+)?));
|
||||||
};
|
};
|
||||||
($db:expr, $id:literal, $pid:expr, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
|
($db:expr, $id:literal, $pid:expr, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
|
||||||
let model = assert_show!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
|
let model = assert_show!(@insert, $db, $id, $pid, $lid $(; $($skip),+)?)
|
||||||
@@ -202,7 +202,7 @@ mod tests {
|
|||||||
slug: notsettable!(slug, concat!("S/", $id).to_string() $(, $($skip),+)?),
|
slug: notsettable!(slug, concat!("S/", $id).to_string() $(, $($skip),+)?),
|
||||||
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
|
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
|
||||||
directory: notsettable!(directory, Path::new(concat!("/S/", $id)).to_owned().into() $(, $($skip),+)?),
|
directory: notsettable!(directory, Path::new(concat!("/S/", $id)).to_owned().into() $(, $($skip),+)?),
|
||||||
relative_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("S/Poster", $id)).to_owned().into()) $(, $($skip),+)?),
|
relative_poster_path: notsettable!(relative_poster_path, Some(concat!("S/Poster", $id).to_owned()) $(, $($skip),+)?),
|
||||||
}.insert($db).await
|
}.insert($db).await
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -242,7 +242,7 @@ mod tests {
|
|||||||
assert_eq!(model.slug, concat!("S/S", $id).to_string());
|
assert_eq!(model.slug, concat!("S/S", $id).to_string());
|
||||||
assert_eq!(model.library, LibraryId::from_raw($lid));
|
assert_eq!(model.library, LibraryId::from_raw($lid));
|
||||||
assert_eq!(model.directory, Path::new(concat!("/S/S", $id)).to_owned().into());
|
assert_eq!(model.directory, Path::new(concat!("/S/S", $id)).to_owned().into());
|
||||||
assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, Path::new(concat!("S/S/Poster", $id)).to_owned().into() $(, $($skip),+)?));
|
assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, concat!("S/S/Poster", $id).to_owned() $(, $($skip),+)?));
|
||||||
};
|
};
|
||||||
($db:expr, $id:literal, $season:literal, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
|
($db:expr, $id:literal, $season:literal, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
|
||||||
let model = assert_season!(@insert, $db, $id, $season, $lid $(; $($skip),+)?)
|
let model = assert_season!(@insert, $db, $id, $season, $lid $(; $($skip),+)?)
|
||||||
@@ -257,7 +257,7 @@ mod tests {
|
|||||||
slug: notsettable!(slug, concat!("S/S", $id).to_string() $(, $($skip),+)?),
|
slug: notsettable!(slug, concat!("S/S", $id).to_string() $(, $($skip),+)?),
|
||||||
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
|
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
|
||||||
directory: notsettable!(directory, Path::new(concat!("/S/S", $id)).to_owned().into() $(, $($skip),+)?),
|
directory: notsettable!(directory, Path::new(concat!("/S/S", $id)).to_owned().into() $(, $($skip),+)?),
|
||||||
relative_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("S/S/Poster", $id)).to_owned().into()) $(, $($skip),+)?),
|
relative_poster_path: notsettable!(relative_poster_path, Some(concat!("S/S/Poster", $id).to_owned()) $(, $($skip),+)?),
|
||||||
}.insert($db).await
|
}.insert($db).await
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -292,8 +292,8 @@ mod tests {
|
|||||||
assert_eq!(model.slug, concat!("S/S/E", $id).to_string());
|
assert_eq!(model.slug, concat!("S/S/E", $id).to_string());
|
||||||
assert_eq!(model.library, LibraryId::from_raw($lid));
|
assert_eq!(model.library, LibraryId::from_raw($lid));
|
||||||
assert_eq!(model.directory, Path::new(concat!("/S/S/E", $id)).to_owned().into());
|
assert_eq!(model.directory, Path::new(concat!("/S/S/E", $id)).to_owned().into());
|
||||||
assert_eq!(model.relative_media_path, Path::new(concat!("E/Media", $id)).to_owned().into());
|
assert_eq!(model.relative_media_path, concat!("E/Media", $id));
|
||||||
assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, Path::new(concat!("S/S/E/Poster", $id)).to_owned().into() $(, $($skip),+)?));
|
assert_eq!(model.relative_poster_path, noneable!(relative_poster_path, concat!("S/S/E/Poster", $id).to_owned() $(, $($skip),+)?));
|
||||||
};
|
};
|
||||||
($db:expr, $id:literal, $season:literal, $episode:literal, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
|
($db:expr, $id:literal, $season:literal, $episode:literal, $lid:literal, $error:ident $(; $($skip:ident),+)?) => {
|
||||||
let model = assert_episode!(@insert, $db, $id, $season, $episode, $lid $(; $($skip),+)?)
|
let model = assert_episode!(@insert, $db, $id, $season, $episode, $lid $(; $($skip),+)?)
|
||||||
@@ -306,11 +306,12 @@ mod tests {
|
|||||||
show: notsettable!(id, ShowId::from_raw($id) $(, $($skip),+)?),
|
show: notsettable!(id, ShowId::from_raw($id) $(, $($skip),+)?),
|
||||||
season: notsettable!(season, $season $(, $($skip),+)?),
|
season: notsettable!(season, $season $(, $($skip),+)?),
|
||||||
episode: notsettable!(episode, $episode $(, $($skip),+)?),
|
episode: notsettable!(episode, $episode $(, $($skip),+)?),
|
||||||
|
count: notsettable!(count, 0 $(, $($skip),+)?),
|
||||||
slug: notsettable!(slug, concat!("S/S/E", $id).to_string() $(, $($skip),+)?),
|
slug: notsettable!(slug, concat!("S/S/E", $id).to_string() $(, $($skip),+)?),
|
||||||
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
|
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($skip),+)?),
|
||||||
directory: notsettable!(directory, Path::new(concat!("/S/S/E", $id)).to_owned().into() $(, $($skip),+)?),
|
directory: notsettable!(directory, Path::new(concat!("/S/S/E", $id)).to_owned().into() $(, $($skip),+)?),
|
||||||
relative_media_path: notsettable!(relative_media_path, Path::new(concat!("E/Media", $id)).to_owned().into() $(, $($skip),+)?),
|
relative_media_path: notsettable!(relative_media_path, concat!("E/Media", $id).to_owned() $(, $($skip),+)?),
|
||||||
relative_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("S/S/E/Poster", $id)).to_owned().into()) $(, $($skip),+)?),
|
relative_poster_path: notsettable!(relative_poster_path, Some(concat!("S/S/E/Poster", $id).to_owned()) $(, $($skip),+)?),
|
||||||
}.insert($db).await
|
}.insert($db).await
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -320,9 +321,9 @@ mod tests {
|
|||||||
make_flix_episode!(&db, 1, 1, 2);
|
make_flix_episode!(&db, 1, 1, 2);
|
||||||
make_flix_episode!(&db, 2, 1, 1);
|
make_flix_episode!(&db, 2, 1, 1);
|
||||||
make_flix_episode!(&db, 3, 1, 1);
|
make_flix_episode!(&db, 3, 1, 1);
|
||||||
make_flix_show!(&db, 10);
|
make_flix_show!(&db, 11);
|
||||||
make_flix_season!(&db, 10, 1);
|
make_flix_season!(&db, 11, 1);
|
||||||
make_flix_episode!(&db, 10, 1, 1);
|
make_flix_episode!(&db, 11, 1, 1);
|
||||||
|
|
||||||
assert_episode!(&db, 1, 1, 1, 1, Success);
|
assert_episode!(&db, 1, 1, 1, 1, Success);
|
||||||
assert_episode!(&db, 1, 1, 2, 1, Success);
|
assert_episode!(&db, 1, 1, 2, 1, Success);
|
||||||
@@ -331,10 +332,11 @@ mod tests {
|
|||||||
assert_episode!(&db, 3, 1, 1, 1, Success; show);
|
assert_episode!(&db, 3, 1, 1, 1, Success; show);
|
||||||
assert_episode!(&db, 4, 1, 1, 1, NotNullViolation; season);
|
assert_episode!(&db, 4, 1, 1, 1, NotNullViolation; season);
|
||||||
assert_episode!(&db, 5, 1, 1, 1, NotNullViolation; episode);
|
assert_episode!(&db, 5, 1, 1, 1, NotNullViolation; episode);
|
||||||
assert_episode!(&db, 6, 1, 1, 1, NotNullViolation; slug);
|
assert_episode!(&db, 6, 1, 1, 1, NotNullViolation; count);
|
||||||
assert_episode!(&db, 7, 1, 1, 1, NotNullViolation; library);
|
assert_episode!(&db, 7, 1, 1, 1, NotNullViolation; slug);
|
||||||
assert_episode!(&db, 8, 1, 1, 1, NotNullViolation; directory);
|
assert_episode!(&db, 8, 1, 1, 1, NotNullViolation; library);
|
||||||
assert_episode!(&db, 9, 1, 1, 1, NotNullViolation; relative_media_path);
|
assert_episode!(&db, 9, 1, 1, 1, NotNullViolation; directory);
|
||||||
assert_episode!(&db, 10, 1, 1, 1, Success; relative_poster_path);
|
assert_episode!(&db, 10, 1, 1, 1, NotNullViolation; relative_media_path);
|
||||||
|
assert_episode!(&db, 11, 1, 1, 1, Success; relative_poster_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ pub struct Model {
|
|||||||
/// The movie's directory
|
/// The movie's directory
|
||||||
pub directory: PathBytes,
|
pub directory: PathBytes,
|
||||||
/// The movie's media path
|
/// The movie's media path
|
||||||
pub relative_media_path: PathBytes,
|
pub relative_media_path: String,
|
||||||
/// The movie's poster path
|
/// The movie's poster path
|
||||||
pub relative_poster_path: Option<PathBytes>,
|
pub relative_poster_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
@@ -53,6 +53,24 @@ pub enum Relation {
|
|||||||
on_delete = "Cascade"
|
on_delete = "Cascade"
|
||||||
)]
|
)]
|
||||||
Library,
|
Library,
|
||||||
|
/// The media info for this movie
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::super::info::movies::Entity",
|
||||||
|
from = "Column::Id",
|
||||||
|
to = "super::super::info::movies::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
MediaInfo,
|
||||||
|
/// The watched info for this movie
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::super::watched::movies::Entity",
|
||||||
|
from = "Column::Id",
|
||||||
|
to = "super::super::watched::movies::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
WatchInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Related<super::collections::Entity> for Entity {
|
impl Related<super::collections::Entity> for Entity {
|
||||||
@@ -66,3 +84,15 @@ impl Related<super::libraries::Entity> for Entity {
|
|||||||
Relation::Library.def()
|
Relation::Library.def()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Related<super::super::info::movies::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::MediaInfo.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::super::watched::movies::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::WatchInfo.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ pub struct Model {
|
|||||||
/// The season's directory
|
/// The season's directory
|
||||||
pub directory: PathBytes,
|
pub directory: PathBytes,
|
||||||
/// The season's poster path
|
/// The season's poster path
|
||||||
pub relative_poster_path: Option<PathBytes>,
|
pub relative_poster_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
@@ -44,6 +44,24 @@ pub enum Relation {
|
|||||||
on_delete = "Cascade"
|
on_delete = "Cascade"
|
||||||
)]
|
)]
|
||||||
Library,
|
Library,
|
||||||
|
/// The media info for this show
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::super::info::seasons::Entity",
|
||||||
|
from = "(Column::Show, Column::Season)",
|
||||||
|
to = "(super::super::info::seasons::Column::Show, super::super::info::seasons::Column::Season)",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
MediaInfo,
|
||||||
|
/// The watched info for this show
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::super::watched::seasons::Entity",
|
||||||
|
from = "(Column::Show, Column::Season)",
|
||||||
|
to = "(super::super::watched::seasons::Column::Show, super::super::watched::seasons::Column::Season)",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
WatchInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Related<super::libraries::Entity> for Entity {
|
impl Related<super::libraries::Entity> for Entity {
|
||||||
@@ -51,3 +69,15 @@ impl Related<super::libraries::Entity> for Entity {
|
|||||||
Relation::Library.def()
|
Relation::Library.def()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Related<super::super::info::seasons::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::MediaInfo.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::super::watched::seasons::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::WatchInfo.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ pub struct Model {
|
|||||||
/// The show's directory
|
/// The show's directory
|
||||||
pub directory: PathBytes,
|
pub directory: PathBytes,
|
||||||
/// The show's poster path
|
/// The show's poster path
|
||||||
pub relative_poster_path: Option<PathBytes>,
|
pub relative_poster_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
@@ -51,6 +51,24 @@ pub enum Relation {
|
|||||||
on_delete = "Cascade"
|
on_delete = "Cascade"
|
||||||
)]
|
)]
|
||||||
Library,
|
Library,
|
||||||
|
/// The media info for this show
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::super::info::shows::Entity",
|
||||||
|
from = "Column::Id",
|
||||||
|
to = "super::super::info::shows::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
MediaInfo,
|
||||||
|
/// The watched info for this show
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::super::watched::shows::Entity",
|
||||||
|
from = "Column::Id",
|
||||||
|
to = "super::super::watched::shows::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
WatchInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Related<super::collections::Entity> for Entity {
|
impl Related<super::collections::Entity> for Entity {
|
||||||
@@ -64,3 +82,15 @@ impl Related<super::libraries::Entity> for Entity {
|
|||||||
Relation::Library.def()
|
Relation::Library.def()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Related<super::super::info::shows::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::MediaInfo.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::super::watched::shows::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::WatchInfo.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
use flix_model::id::CollectionId;
|
use flix_model::id::CollectionId;
|
||||||
|
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||||
PrimaryKeyTrait,
|
EnumIter, PrimaryKeyTrait,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The database representation of a flix collection
|
/// The database representation of a flix collection
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ use flix_model::id::MovieId;
|
|||||||
|
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||||
PrimaryKeyTrait,
|
EnumIter, PrimaryKeyTrait,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The database representation of a flix movie
|
/// The database representation of a flix movie
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ mod tests {
|
|||||||
slug: Set(::std::string::String::new()),
|
slug: Set(::std::string::String::new()),
|
||||||
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
||||||
directory: Set(::std::path::PathBuf::new().into()),
|
directory: Set(::std::path::PathBuf::new().into()),
|
||||||
relative_poster_path: Set(None),
|
relative_poster_path: Set(::core::option::Option::None),
|
||||||
}
|
}
|
||||||
.insert($db)
|
.insert($db)
|
||||||
.await
|
.await
|
||||||
@@ -144,8 +144,8 @@ mod tests {
|
|||||||
slug: Set(::std::string::String::new()),
|
slug: Set(::std::string::String::new()),
|
||||||
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
||||||
directory: Set(::std::path::PathBuf::new().into()),
|
directory: Set(::std::path::PathBuf::new().into()),
|
||||||
relative_media_path: Set(::std::path::PathBuf::new().into()),
|
relative_media_path: Set(::std::string::String::new()),
|
||||||
relative_poster_path: Set(None),
|
relative_poster_path: Set(::core::option::Option::None),
|
||||||
}
|
}
|
||||||
.insert($db)
|
.insert($db)
|
||||||
.await
|
.await
|
||||||
@@ -181,7 +181,7 @@ mod tests {
|
|||||||
slug: Set(::std::string::String::new()),
|
slug: Set(::std::string::String::new()),
|
||||||
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
||||||
directory: Set(::std::path::PathBuf::new().into()),
|
directory: Set(::std::path::PathBuf::new().into()),
|
||||||
relative_poster_path: Set(None),
|
relative_poster_path: Set(::core::option::Option::None),
|
||||||
}
|
}
|
||||||
.insert($db)
|
.insert($db)
|
||||||
.await
|
.await
|
||||||
@@ -216,7 +216,7 @@ mod tests {
|
|||||||
slug: Set(::std::string::String::new()),
|
slug: Set(::std::string::String::new()),
|
||||||
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
||||||
directory: Set(::std::path::PathBuf::new().into()),
|
directory: Set(::std::path::PathBuf::new().into()),
|
||||||
relative_poster_path: Set(None),
|
relative_poster_path: Set(::core::option::Option::None),
|
||||||
}
|
}
|
||||||
.insert($db)
|
.insert($db)
|
||||||
.await
|
.await
|
||||||
@@ -245,16 +245,23 @@ mod tests {
|
|||||||
pub(super) use make_flix_episode;
|
pub(super) use make_flix_episode;
|
||||||
macro_rules! have_episode {
|
macro_rules! have_episode {
|
||||||
($db:expr, $lid:literal, $show:literal, $season:literal, $episode:literal) => {
|
($db:expr, $lid:literal, $show:literal, $season:literal, $episode:literal) => {
|
||||||
|
have_episode!(@make, $db, $lid, $show, $season, $episode, 0);
|
||||||
|
};
|
||||||
|
($db:expr, $lid:literal, $show:literal, $season:literal, $episode:literal, >1) => {
|
||||||
|
have_episode!(@make, $db, $lid, $show, $season, $episode, 1);
|
||||||
|
};
|
||||||
|
(@make, $db:expr, $lid:literal, $show:literal, $season:literal, $episode:literal, $count:literal) => {
|
||||||
$crate::entity::tests::make_flix_episode!($db, $show, $season, $episode);
|
$crate::entity::tests::make_flix_episode!($db, $show, $season, $episode);
|
||||||
$crate::entity::content::episodes::ActiveModel {
|
$crate::entity::content::episodes::ActiveModel {
|
||||||
show: Set(::flix_model::id::ShowId::from_raw($show)),
|
show: Set(::flix_model::id::ShowId::from_raw($show)),
|
||||||
season: Set($season),
|
season: Set($season),
|
||||||
episode: Set($episode),
|
episode: Set($episode),
|
||||||
|
count: Set($count),
|
||||||
slug: Set(::std::string::String::new()),
|
slug: Set(::std::string::String::new()),
|
||||||
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
||||||
directory: Set(::std::path::PathBuf::new().into()),
|
directory: Set(::std::path::PathBuf::new().into()),
|
||||||
relative_media_path: Set(::std::path::PathBuf::new().into()),
|
relative_media_path: Set(::std::string::String::new()),
|
||||||
relative_poster_path: Set(None),
|
relative_poster_path: Set(::core::option::Option::None),
|
||||||
}
|
}
|
||||||
.insert($db)
|
.insert($db)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use seamantic::model::duration::Seconds;
|
|||||||
|
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||||
PrimaryKeyTrait,
|
EnumIter, PrimaryKeyTrait,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The database representation of a tmdb episode
|
/// The database representation of a tmdb episode
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
use flix_model::id::{CollectionId, RawId};
|
use flix_model::id::{CollectionId, RawId};
|
||||||
|
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||||
PrimaryKeyTrait,
|
EnumIter, PrimaryKeyTrait,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The database representation of a watched movie
|
/// The database representation of a watched movie
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use flix_model::numbers::{EpisodeNumber, SeasonNumber};
|
|||||||
|
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||||
PrimaryKeyTrait,
|
EnumIter, PrimaryKeyTrait,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The database representation of a watched movie
|
/// The database representation of a watched movie
|
||||||
|
|||||||
@@ -181,12 +181,10 @@ mod tests {
|
|||||||
have_episode!(&db, 1, 1, 1, 1);
|
have_episode!(&db, 1, 1, 1, 1);
|
||||||
assert_episode!(&db, 1, 1, 1, 1, Success);
|
assert_episode!(&db, 1, 1, 1, 1, Success);
|
||||||
assert_episode!(&db, 1, 1, 1, 2, Success);
|
assert_episode!(&db, 1, 1, 1, 2, Success);
|
||||||
have_episode!(&db, 1, 1, 1, 2);
|
have_episode!(&db, 1, 1, 1, 2, >1); // Covers 2 and 3
|
||||||
|
make_flix_episode!(&db, 1, 1, 3);
|
||||||
assert_episode!(&db, 1, 1, 2, 1, Success);
|
assert_episode!(&db, 1, 1, 2, 1, Success);
|
||||||
assert_episode!(&db, 1, 1, 2, 2, Success);
|
assert_episode!(&db, 1, 1, 2, 2, Success);
|
||||||
have_episode!(&db, 1, 1, 1, 3);
|
|
||||||
assert_episode!(&db, 1, 1, 3, 1, Success);
|
|
||||||
assert_episode!(&db, 1, 1, 3, 2, Success);
|
|
||||||
have_season!(&db, 1, 1, 2);
|
have_season!(&db, 1, 1, 2);
|
||||||
have_episode!(&db, 1, 1, 2, 1);
|
have_episode!(&db, 1, 1, 2, 1);
|
||||||
assert_episode!(&db, 1, 2, 1, 1, Success);
|
assert_episode!(&db, 1, 2, 1, 1, Success);
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ use flix_model::id::{MovieId, RawId};
|
|||||||
|
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||||
PrimaryKeyTrait,
|
EnumIter, PrimaryKeyTrait,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The database representation of a watched movie
|
/// The database representation of a watched movie
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use flix_model::numbers::SeasonNumber;
|
|||||||
|
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||||
PrimaryKeyTrait,
|
EnumIter, PrimaryKeyTrait,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The database representation of a watched movie
|
/// The database representation of a watched movie
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ use flix_model::id::{RawId, ShowId};
|
|||||||
|
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||||
PrimaryKeyTrait,
|
EnumIter, PrimaryKeyTrait,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The database representation of a watched movie
|
/// The database representation of a watched movie
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use sea_orm::sea_query;
|
|||||||
use sea_orm::sea_query::{ForeignKeyCreateStatement, Table};
|
use sea_orm::sea_query::{ForeignKeyCreateStatement, Table};
|
||||||
use sea_orm::{DbErr, Iden};
|
use sea_orm::{DbErr, Iden};
|
||||||
use sea_orm_migration::SchemaManager;
|
use sea_orm_migration::SchemaManager;
|
||||||
use sea_orm_migration::schema::{binary, binary_null, integer, integer_null, string};
|
use sea_orm_migration::schema::{binary, integer, integer_null, string, string_null};
|
||||||
|
|
||||||
use crate::migration::m_000001::FlixInfoCollections;
|
use crate::migration::m_000001::FlixInfoCollections;
|
||||||
use crate::migration::m_000003::FlixLibraries;
|
use crate::migration::m_000003::FlixLibraries;
|
||||||
@@ -30,7 +30,7 @@ pub async fn up(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
|
|||||||
.col(string(FlixCollections::Slug))
|
.col(string(FlixCollections::Slug))
|
||||||
.col(integer(FlixCollections::Library))
|
.col(integer(FlixCollections::Library))
|
||||||
.col(binary(FlixCollections::Directory))
|
.col(binary(FlixCollections::Directory))
|
||||||
.col(binary_null(FlixCollections::RelativePosterPath))
|
.col(string_null(FlixCollections::RelativePosterPath))
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKeyCreateStatement::new()
|
ForeignKeyCreateStatement::new()
|
||||||
.name("fk-flix_collections-id")
|
.name("fk-flix_collections-id")
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use sea_orm::sea_query;
|
|||||||
use sea_orm::sea_query::{ForeignKeyCreateStatement, Index, Table};
|
use sea_orm::sea_query::{ForeignKeyCreateStatement, Index, Table};
|
||||||
use sea_orm::{DbErr, Iden};
|
use sea_orm::{DbErr, Iden};
|
||||||
use sea_orm_migration::SchemaManager;
|
use sea_orm_migration::SchemaManager;
|
||||||
use sea_orm_migration::schema::{binary, binary_null, integer, string};
|
use sea_orm_migration::schema::{binary, integer, string, string_null};
|
||||||
|
|
||||||
use crate::migration::m_000001::FlixInfoEpisodes;
|
use crate::migration::m_000001::FlixInfoEpisodes;
|
||||||
use crate::migration::m_000003::FlixLibraries;
|
use crate::migration::m_000003::FlixLibraries;
|
||||||
@@ -13,6 +13,7 @@ pub enum FlixEpisodes {
|
|||||||
Show,
|
Show,
|
||||||
Season,
|
Season,
|
||||||
Episode,
|
Episode,
|
||||||
|
Count,
|
||||||
Slug,
|
Slug,
|
||||||
Library,
|
Library,
|
||||||
Directory,
|
Directory,
|
||||||
@@ -28,11 +29,12 @@ pub async fn up(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
|
|||||||
.col(integer(FlixEpisodes::Show))
|
.col(integer(FlixEpisodes::Show))
|
||||||
.col(integer(FlixEpisodes::Season))
|
.col(integer(FlixEpisodes::Season))
|
||||||
.col(integer(FlixEpisodes::Episode))
|
.col(integer(FlixEpisodes::Episode))
|
||||||
|
.col(integer(FlixEpisodes::Count))
|
||||||
.col(string(FlixEpisodes::Slug))
|
.col(string(FlixEpisodes::Slug))
|
||||||
.col(integer(FlixEpisodes::Library))
|
.col(integer(FlixEpisodes::Library))
|
||||||
.col(binary(FlixEpisodes::Directory))
|
.col(binary(FlixEpisodes::Directory))
|
||||||
.col(binary(FlixEpisodes::RelativeMediaPath))
|
.col(string(FlixEpisodes::RelativeMediaPath))
|
||||||
.col(binary_null(FlixEpisodes::RelativePosterPath))
|
.col(string_null(FlixEpisodes::RelativePosterPath))
|
||||||
.primary_key(
|
.primary_key(
|
||||||
Index::create()
|
Index::create()
|
||||||
.col(FlixEpisodes::Show)
|
.col(FlixEpisodes::Show)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use sea_orm::sea_query;
|
|||||||
use sea_orm::sea_query::{ForeignKeyCreateStatement, Table};
|
use sea_orm::sea_query::{ForeignKeyCreateStatement, Table};
|
||||||
use sea_orm::{DbErr, Iden};
|
use sea_orm::{DbErr, Iden};
|
||||||
use sea_orm_migration::SchemaManager;
|
use sea_orm_migration::SchemaManager;
|
||||||
use sea_orm_migration::schema::{binary, binary_null, integer, integer_null, string};
|
use sea_orm_migration::schema::{binary, integer, integer_null, string, string_null};
|
||||||
|
|
||||||
use crate::migration::m_000001::FlixInfoMovies;
|
use crate::migration::m_000001::FlixInfoMovies;
|
||||||
use crate::migration::m_000003::{FlixCollections, FlixLibraries};
|
use crate::migration::m_000003::{FlixCollections, FlixLibraries};
|
||||||
@@ -31,8 +31,8 @@ pub async fn up(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
|
|||||||
.col(string(FlixMovies::Slug))
|
.col(string(FlixMovies::Slug))
|
||||||
.col(integer(FlixMovies::Library))
|
.col(integer(FlixMovies::Library))
|
||||||
.col(binary(FlixMovies::Directory))
|
.col(binary(FlixMovies::Directory))
|
||||||
.col(binary(FlixMovies::RelativeMediaPath))
|
.col(string(FlixMovies::RelativeMediaPath))
|
||||||
.col(binary_null(FlixMovies::RelativePosterPath))
|
.col(string_null(FlixMovies::RelativePosterPath))
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKeyCreateStatement::new()
|
ForeignKeyCreateStatement::new()
|
||||||
.name("fk-flix_movies-id")
|
.name("fk-flix_movies-id")
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use sea_orm::sea_query;
|
|||||||
use sea_orm::sea_query::{ForeignKeyCreateStatement, Index, Table};
|
use sea_orm::sea_query::{ForeignKeyCreateStatement, Index, Table};
|
||||||
use sea_orm::{DbErr, Iden};
|
use sea_orm::{DbErr, Iden};
|
||||||
use sea_orm_migration::SchemaManager;
|
use sea_orm_migration::SchemaManager;
|
||||||
use sea_orm_migration::schema::{binary, binary_null, integer, string};
|
use sea_orm_migration::schema::{binary, integer, string, string_null};
|
||||||
|
|
||||||
use crate::migration::m_000001::FlixInfoSeasons;
|
use crate::migration::m_000001::FlixInfoSeasons;
|
||||||
use crate::migration::m_000003::FlixLibraries;
|
use crate::migration::m_000003::FlixLibraries;
|
||||||
@@ -28,7 +28,7 @@ pub async fn up(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
|
|||||||
.col(string(FlixSeasons::Slug))
|
.col(string(FlixSeasons::Slug))
|
||||||
.col(integer(FlixSeasons::Library))
|
.col(integer(FlixSeasons::Library))
|
||||||
.col(binary(FlixSeasons::Directory))
|
.col(binary(FlixSeasons::Directory))
|
||||||
.col(binary_null(FlixSeasons::RelativePosterPath))
|
.col(string_null(FlixSeasons::RelativePosterPath))
|
||||||
.primary_key(
|
.primary_key(
|
||||||
Index::create()
|
Index::create()
|
||||||
.col(FlixSeasons::Show)
|
.col(FlixSeasons::Show)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use sea_orm::sea_query;
|
|||||||
use sea_orm::sea_query::{ForeignKeyCreateStatement, Table};
|
use sea_orm::sea_query::{ForeignKeyCreateStatement, Table};
|
||||||
use sea_orm::{DbErr, Iden};
|
use sea_orm::{DbErr, Iden};
|
||||||
use sea_orm_migration::SchemaManager;
|
use sea_orm_migration::SchemaManager;
|
||||||
use sea_orm_migration::schema::{binary, binary_null, integer, integer_null, string};
|
use sea_orm_migration::schema::{binary, integer, integer_null, string, string_null};
|
||||||
|
|
||||||
use crate::migration::m_000001::FlixInfoShows;
|
use crate::migration::m_000001::FlixInfoShows;
|
||||||
use crate::migration::m_000003::{FlixCollections, FlixLibraries};
|
use crate::migration::m_000003::{FlixCollections, FlixLibraries};
|
||||||
@@ -30,7 +30,7 @@ pub async fn up(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
|
|||||||
.col(string(FlixShows::Slug))
|
.col(string(FlixShows::Slug))
|
||||||
.col(integer(FlixShows::Library))
|
.col(integer(FlixShows::Library))
|
||||||
.col(binary(FlixShows::Directory))
|
.col(binary(FlixShows::Directory))
|
||||||
.col(binary_null(FlixShows::RelativePosterPath))
|
.col(string_null(FlixShows::RelativePosterPath))
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKeyCreateStatement::new()
|
ForeignKeyCreateStatement::new()
|
||||||
.name("fk-flix_shows-id")
|
.name("fk-flix_shows-id")
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix"
|
name = "flix"
|
||||||
version = "0.0.9"
|
version = "0.0.12"
|
||||||
|
|
||||||
categories = []
|
categories = []
|
||||||
description = "Mechanisms for interacting with flix media"
|
description = "Mechanisms for interacting with flix media"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix-fs"
|
name = "flix-fs"
|
||||||
version = "0.0.9"
|
version = "0.0.12"
|
||||||
|
|
||||||
categories = []
|
categories = []
|
||||||
description = "Filesystem scanner for flix media"
|
description = "Filesystem scanner for flix media"
|
||||||
@@ -22,7 +22,7 @@ workspace = true
|
|||||||
flix-model = { workspace = true }
|
flix-model = { workspace = true }
|
||||||
|
|
||||||
async-stream = { workspace = true }
|
async-stream = { workspace = true }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true, features = ["std", "perf"] }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
tokio-stream = { workspace = true, features = ["fs"] }
|
tokio-stream = { workspace = true, features = ["fs"] }
|
||||||
|
|||||||
@@ -47,17 +47,17 @@ pub enum Scanner {
|
|||||||
Show {
|
Show {
|
||||||
/// The ID of the parent collection (if any)
|
/// The ID of the parent collection (if any)
|
||||||
parent: Option<CollectionId>,
|
parent: Option<CollectionId>,
|
||||||
/// The ID of the show this episode belongs to
|
/// The ID of the show
|
||||||
id: ShowId,
|
id: ShowId,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
poster_file_name: Option<String>,
|
poster_file_name: Option<String>,
|
||||||
},
|
},
|
||||||
/// A scanned episode
|
/// A scanned episode
|
||||||
Season {
|
Season {
|
||||||
/// The ID of the show this episode belongs to
|
/// The ID of the show this season belongs to
|
||||||
show: ShowId,
|
show: ShowId,
|
||||||
/// The season this episode belongs to
|
/// The number of this season
|
||||||
number: SeasonNumber,
|
season: SeasonNumber,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
poster_file_name: Option<String>,
|
poster_file_name: Option<String>,
|
||||||
},
|
},
|
||||||
@@ -68,7 +68,7 @@ pub enum Scanner {
|
|||||||
/// The season this episode belongs to
|
/// The season this episode belongs to
|
||||||
season: SeasonNumber,
|
season: SeasonNumber,
|
||||||
/// The number(s) of this episode
|
/// The number(s) of this episode
|
||||||
number: EpisodeNumbers,
|
episode: EpisodeNumbers,
|
||||||
/// The file name of the media file
|
/// The file name of the media file
|
||||||
media_file_name: String,
|
media_file_name: String,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
@@ -108,23 +108,23 @@ impl From<show::Scanner> for Scanner {
|
|||||||
},
|
},
|
||||||
show::Scanner::Season {
|
show::Scanner::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Season {
|
} => Self::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
show::Scanner::Episode {
|
show::Scanner::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Episode {
|
} => Self::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
@@ -166,23 +166,23 @@ impl From<generic::Scanner> for Scanner {
|
|||||||
},
|
},
|
||||||
generic::Scanner::Season {
|
generic::Scanner::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Season {
|
} => Self::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
generic::Scanner::Episode {
|
generic::Scanner::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Episode {
|
} => Self::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ pub enum Scanner {
|
|||||||
/// The season this episode belongs to
|
/// The season this episode belongs to
|
||||||
season: SeasonNumber,
|
season: SeasonNumber,
|
||||||
/// The number(s) of this episode
|
/// The number(s) of this episode
|
||||||
number: EpisodeNumbers,
|
episode: EpisodeNumbers,
|
||||||
/// The file name of the media file
|
/// The file name of the media file
|
||||||
media_file_name: String,
|
media_file_name: String,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
@@ -40,7 +40,7 @@ impl Scanner {
|
|||||||
path: &Path,
|
path: &Path,
|
||||||
show: ShowId,
|
show: ShowId,
|
||||||
season: SeasonNumber,
|
season: SeasonNumber,
|
||||||
number: EpisodeNumbers,
|
episode: EpisodeNumbers,
|
||||||
) -> impl Stream<Item = Item> {
|
) -> impl Stream<Item = Item> {
|
||||||
stream!({
|
stream!({
|
||||||
let dirs = match fs::read_dir(path).await {
|
let dirs = match fs::read_dir(path).await {
|
||||||
@@ -137,7 +137,7 @@ impl Scanner {
|
|||||||
event: Ok(Self::Episode {
|
event: Ok(Self::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -51,17 +51,17 @@ pub enum Scanner {
|
|||||||
Show {
|
Show {
|
||||||
/// The ID of the parent collection (if any)
|
/// The ID of the parent collection (if any)
|
||||||
parent: Option<CollectionId>,
|
parent: Option<CollectionId>,
|
||||||
/// The ID of the show this episode belongs to
|
/// The ID of the show
|
||||||
id: ShowId,
|
id: ShowId,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
poster_file_name: Option<String>,
|
poster_file_name: Option<String>,
|
||||||
},
|
},
|
||||||
/// A scanned episode
|
/// A scanned episode
|
||||||
Season {
|
Season {
|
||||||
/// The ID of the show this episode belongs to
|
/// The ID of the show this season belongs to
|
||||||
show: ShowId,
|
show: ShowId,
|
||||||
/// The season this episode belongs to
|
/// The season this episode belongs to
|
||||||
number: SeasonNumber,
|
season: SeasonNumber,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
poster_file_name: Option<String>,
|
poster_file_name: Option<String>,
|
||||||
},
|
},
|
||||||
@@ -72,7 +72,7 @@ pub enum Scanner {
|
|||||||
/// The season this episode belongs to
|
/// The season this episode belongs to
|
||||||
season: SeasonNumber,
|
season: SeasonNumber,
|
||||||
/// The number(s) of this episode
|
/// The number(s) of this episode
|
||||||
number: EpisodeNumbers,
|
episode: EpisodeNumbers,
|
||||||
/// The file name of the media file
|
/// The file name of the media file
|
||||||
media_file_name: String,
|
media_file_name: String,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
@@ -114,23 +114,23 @@ impl From<collection::Scanner> for Scanner {
|
|||||||
},
|
},
|
||||||
collection::Scanner::Season {
|
collection::Scanner::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Season {
|
} => Self::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
collection::Scanner::Episode {
|
collection::Scanner::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Episode {
|
} => Self::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
@@ -170,23 +170,23 @@ impl From<show::Scanner> for Scanner {
|
|||||||
},
|
},
|
||||||
show::Scanner::Season {
|
show::Scanner::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Season {
|
} => Self::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
show::Scanner::Episode {
|
show::Scanner::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Episode {
|
} => Self::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
@@ -211,10 +211,12 @@ impl Scanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let media_folder_re = MEDIA_FOLDER_REGEX.get_or_init(|| {
|
let media_folder_re = MEDIA_FOLDER_REGEX.get_or_init(|| {
|
||||||
Regex::new(r"^[\w ]+ \(\d+\) \[\d+\]$").unwrap_or_else(|_| panic!("regex is invalid"))
|
Regex::new(r"^[[[:alnum:]] -]+ \([[:digit:]]+\) \[[[:digit:]]+\]$")
|
||||||
|
.unwrap_or_else(|err| panic!("regex is invalid: {err}"))
|
||||||
|
});
|
||||||
|
let season_folder_re = SEASON_FOLDER_REGEX.get_or_init(|| {
|
||||||
|
Regex::new(r"^S[[:digit:]]+$").unwrap_or_else(|err| panic!("regex is invalid: {err}"))
|
||||||
});
|
});
|
||||||
let season_folder_re = SEASON_FOLDER_REGEX
|
|
||||||
.get_or_init(|| Regex::new(r"^S\d+$").unwrap_or_else(|_| panic!("regex is invalid")));
|
|
||||||
|
|
||||||
stream!({
|
stream!({
|
||||||
let Some(dir_name) = path.file_name().and_then(OsStr::to_str) else {
|
let Some(dir_name) = path.file_name().and_then(OsStr::to_str) else {
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ pub type Item = crate::Item<Scanner>;
|
|||||||
pub enum Scanner {
|
pub enum Scanner {
|
||||||
/// A scanned episode
|
/// A scanned episode
|
||||||
Season {
|
Season {
|
||||||
/// The ID of the show this episode belongs to
|
/// The ID of the show this season belongs to
|
||||||
show: ShowId,
|
show: ShowId,
|
||||||
/// The season this episode belongs to
|
/// The season this episode belongs to
|
||||||
number: SeasonNumber,
|
season: SeasonNumber,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
poster_file_name: Option<String>,
|
poster_file_name: Option<String>,
|
||||||
},
|
},
|
||||||
@@ -36,7 +36,7 @@ pub enum Scanner {
|
|||||||
/// The season this episode belongs to
|
/// The season this episode belongs to
|
||||||
season: SeasonNumber,
|
season: SeasonNumber,
|
||||||
/// The number(s) of this episode
|
/// The number(s) of this episode
|
||||||
number: EpisodeNumbers,
|
episode: EpisodeNumbers,
|
||||||
/// The file name of the media file
|
/// The file name of the media file
|
||||||
media_file_name: String,
|
media_file_name: String,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
@@ -50,13 +50,13 @@ impl From<episode::Scanner> for Scanner {
|
|||||||
episode::Scanner::Episode {
|
episode::Scanner::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Episode {
|
} => Self::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
@@ -69,7 +69,7 @@ impl Scanner {
|
|||||||
pub fn scan_season(
|
pub fn scan_season(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
show: ShowId,
|
show: ShowId,
|
||||||
number: SeasonNumber,
|
season: SeasonNumber,
|
||||||
) -> impl Stream<Item = Item> {
|
) -> impl Stream<Item = Item> {
|
||||||
stream!({
|
stream!({
|
||||||
let dirs = match fs::read_dir(path).await {
|
let dirs = match fs::read_dir(path).await {
|
||||||
@@ -141,7 +141,7 @@ impl Scanner {
|
|||||||
path: path.to_owned(),
|
path: path.to_owned(),
|
||||||
event: Ok(Self::Season {
|
event: Ok(Self::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
@@ -170,14 +170,14 @@ impl Scanner {
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(season) = s_str.parse::<SeasonNumber>() else {
|
let Ok(season_number) = s_str.parse::<SeasonNumber>() else {
|
||||||
yield Item {
|
yield Item {
|
||||||
path: path.to_owned(),
|
path: path.to_owned(),
|
||||||
event: Err(Error::UnexpectedFolder),
|
event: Err(Error::UnexpectedFolder),
|
||||||
};
|
};
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if season != number {
|
if season_number != season {
|
||||||
yield Item {
|
yield Item {
|
||||||
path: path.to_owned(),
|
path: path.to_owned(),
|
||||||
event: Err(Error::Inconsistent),
|
event: Err(Error::Inconsistent),
|
||||||
@@ -204,9 +204,12 @@ impl Scanner {
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
for await event in
|
for await event in episode::Scanner::scan_episode(
|
||||||
episode::Scanner::scan_episode(&episode_dir, show, number, episode_numbers)
|
&episode_dir,
|
||||||
{
|
show,
|
||||||
|
season_number,
|
||||||
|
episode_numbers,
|
||||||
|
) {
|
||||||
yield event.map(|e| e.into());
|
yield event.map(|e| e.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,17 +24,17 @@ pub enum Scanner {
|
|||||||
Show {
|
Show {
|
||||||
/// The ID of the parent collection (if any)
|
/// The ID of the parent collection (if any)
|
||||||
parent: Option<CollectionId>,
|
parent: Option<CollectionId>,
|
||||||
/// The ID of the show this episode belongs to
|
/// The ID of the show
|
||||||
id: ShowId,
|
id: ShowId,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
poster_file_name: Option<String>,
|
poster_file_name: Option<String>,
|
||||||
},
|
},
|
||||||
/// A scanned episode
|
/// A scanned episode
|
||||||
Season {
|
Season {
|
||||||
/// The ID of the show this episode belongs to
|
/// The ID of the show this season belongs to
|
||||||
show: ShowId,
|
show: ShowId,
|
||||||
/// The season this episode belongs to
|
/// The season this episode belongs to
|
||||||
number: SeasonNumber,
|
season: SeasonNumber,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
poster_file_name: Option<String>,
|
poster_file_name: Option<String>,
|
||||||
},
|
},
|
||||||
@@ -45,7 +45,7 @@ pub enum Scanner {
|
|||||||
/// The season this episode belongs to
|
/// The season this episode belongs to
|
||||||
season: SeasonNumber,
|
season: SeasonNumber,
|
||||||
/// The number(s) of this episode
|
/// The number(s) of this episode
|
||||||
number: EpisodeNumbers,
|
episode: EpisodeNumbers,
|
||||||
/// The file name of the media file
|
/// The file name of the media file
|
||||||
media_file_name: String,
|
media_file_name: String,
|
||||||
/// The file name of the poster file
|
/// The file name of the poster file
|
||||||
@@ -58,23 +58,23 @@ impl From<season::Scanner> for Scanner {
|
|||||||
match value {
|
match value {
|
||||||
season::Scanner::Season {
|
season::Scanner::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Season {
|
} => Self::Season {
|
||||||
show,
|
show,
|
||||||
number,
|
season,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
season::Scanner::Episode {
|
season::Scanner::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
} => Self::Episode {
|
} => Self::Episode {
|
||||||
show,
|
show,
|
||||||
season,
|
season,
|
||||||
number,
|
episode,
|
||||||
media_file_name,
|
media_file_name,
|
||||||
poster_file_name,
|
poster_file_name,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix-model"
|
name = "flix-model"
|
||||||
version = "0.0.9"
|
version = "0.0.12"
|
||||||
|
|
||||||
categories = []
|
categories = []
|
||||||
description = "Core types for flix data"
|
description = "Core types for flix data"
|
||||||
|
|||||||
@@ -58,21 +58,3 @@ impl EpisodeNumbers {
|
|||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl EpisodeNumbers {
|
|
||||||
// /// Get the primary episode number of this episode
|
|
||||||
// pub fn primary_episode_number(&self) -> Option<EpisodeNumber> {
|
|
||||||
// match self {
|
|
||||||
// EpisodeNumbers::Single { number } => Some(*number),
|
|
||||||
// EpisodeNumbers::Multiple { numbers } => numbers.first().copied(),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// Get additional episode numbers of this episode
|
|
||||||
// pub fn additional_episode_numbers(&self) -> &[EpisodeNumber] {
|
|
||||||
// match self {
|
|
||||||
// EpisodeNumbers::Single { number: _ } => &[],
|
|
||||||
// EpisodeNumbers::Multiple { numbers } => numbers.get(1..).unwrap_or(&[]),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix-tmdb"
|
name = "flix-tmdb"
|
||||||
version = "0.0.9"
|
version = "0.0.12"
|
||||||
|
|
||||||
categories = []
|
categories = []
|
||||||
description = "Clients and models for fetching data from TMDB"
|
description = "Clients and models for fetching data from TMDB"
|
||||||
|
|||||||
@@ -150,8 +150,8 @@ mod tests {
|
|||||||
#[cfg(feature = "sea-orm")]
|
#[cfg(feature = "sea-orm")]
|
||||||
fn test_sea_orm() {
|
fn test_sea_orm() {
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||||
PrimaryKeyTrait,
|
EnumIter, PrimaryKeyTrait,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Id;
|
use super::Id;
|
||||||
@@ -184,7 +184,7 @@ mod tests {
|
|||||||
/// Type alias for the raw ID representation
|
/// Type alias for the raw ID representation
|
||||||
pub use self::TmdbRepr as RawId;
|
pub use self::TmdbRepr as RawId;
|
||||||
|
|
||||||
/// A placeholder type used for CollectionId
|
#[doc(hidden)]
|
||||||
pub enum Collection {}
|
pub enum Collection {}
|
||||||
/// Type alias for a collection ID
|
/// Type alias for a collection ID
|
||||||
pub type CollectionId = Id<Collection>;
|
pub type CollectionId = Id<Collection>;
|
||||||
@@ -203,7 +203,7 @@ impl TryFrom<flix_model::id::CollectionId> for CollectionId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A placeholder type used for MovieId
|
#[doc(hidden)]
|
||||||
pub enum Movie {}
|
pub enum Movie {}
|
||||||
/// Type alias for a movie ID
|
/// Type alias for a movie ID
|
||||||
pub type MovieId = Id<Movie>;
|
pub type MovieId = Id<Movie>;
|
||||||
@@ -222,7 +222,7 @@ impl TryFrom<flix_model::id::MovieId> for MovieId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A placeholder type used for ShowId
|
#[doc(hidden)]
|
||||||
pub enum Show {}
|
pub enum Show {}
|
||||||
/// Type alias for a show ID
|
/// Type alias for a show ID
|
||||||
pub type ShowId = Id<Show>;
|
pub type ShowId = Id<Show>;
|
||||||
|
|||||||
Reference in New Issue
Block a user