You've already forked flix
Compare commits
5 Commits
0.0.9
...
508c4ed32f
| Author | SHA1 | Date | |
|---|---|---|---|
|
508c4ed32f
|
|||
|
dd688fdc83
|
|||
|
0d34174a13
|
|||
|
8411c75377
|
|||
|
6eec67a0fd
|
Generated
+292
-354
File diff suppressed because it is too large
Load Diff
+9
-10
@@ -35,17 +35,17 @@ overflow-checks = true
|
||||
strip = "debuginfo"
|
||||
|
||||
[workspace.dependencies]
|
||||
flix = { path = "crates/flix", version = "=0.0.9", default-features = false }
|
||||
flix-cli = { path = "crates/cli", version = "=0.0.9", default-features = false }
|
||||
flix-db = { path = "crates/db", version = "=0.0.9", default-features = false }
|
||||
flix-fs = { path = "crates/fs", version = "=0.0.9", default-features = false }
|
||||
flix-model = { path = "crates/model", version = "=0.0.9", default-features = false }
|
||||
flix-tmdb = { path = "crates/tmdb", 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.12", default-features = false }
|
||||
flix-db = { path = "crates/db", version = "=0.0.12", default-features = false }
|
||||
flix-fs = { path = "crates/fs", version = "=0.0.12", default-features = false }
|
||||
flix-model = { path = "crates/model", version = "=0.0.12", 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-migration = { 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.16", default-features = false }
|
||||
|
||||
anyhow = { version = "^1", default-features = false }
|
||||
async-stream = { version = "^0.3", default-features = false }
|
||||
@@ -53,7 +53,6 @@ chrono = { version = "^0.4", default-features = false }
|
||||
clap = { version = "^4", default-features = false, features = ["std"] }
|
||||
futures = { version = "^0.3", default-features = false }
|
||||
governor = { version = "^0.10", default-features = false }
|
||||
home = { version = "^0.5", default-features = false }
|
||||
nonzero_ext = { version = "^0.3", default-features = false }
|
||||
regex = { version = "^1", default-features = false }
|
||||
reqwest = { version = "^0.12", default-features = false }
|
||||
|
||||
@@ -11,4 +11,5 @@ Libraries and tools for dealing with media metadata
|
||||
- fmt: `cargo fmt --check`
|
||||
- docs: `RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features`
|
||||
- install: `cargo install --path crates/cli`
|
||||
- semver: `cargo semver-checks --all-features`
|
||||
- publish: `cargo publish --dry-run --workspace`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix-cli"
|
||||
version = "0.0.9"
|
||||
version = "0.0.12"
|
||||
|
||||
categories = ["command-line-utilities"]
|
||||
description = "CLI for interacting with a flix database"
|
||||
@@ -51,7 +51,6 @@ clap = { workspace = true, features = [
|
||||
"usage",
|
||||
] }
|
||||
futures = { workspace = true }
|
||||
home = { workspace = true }
|
||||
sea-orm = { workspace = true, features = ["runtime-tokio"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
tokio = { workspace = true, features = ["rt", "fs", "macros"] }
|
||||
|
||||
@@ -24,7 +24,7 @@ impl Cli {
|
||||
pub fn config_path(&self) -> PathBuf {
|
||||
fn expect_home_dir() -> PathBuf {
|
||||
#[allow(clippy::expect_used)]
|
||||
home::home_dir().expect("you do not have a home directory")
|
||||
std::env::home_dir().expect("you do not have a home directory")
|
||||
}
|
||||
|
||||
match self.config.strip_prefix("~/") {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix-db"
|
||||
version = "0.0.9"
|
||||
version = "0.0.12"
|
||||
|
||||
categories = []
|
||||
description = "Types for storing persistent data about media"
|
||||
|
||||
@@ -7,7 +7,7 @@ use sea_orm_migration::MigratorTrait as _;
|
||||
pub struct Connection(DatabaseConnection);
|
||||
|
||||
impl Connection {
|
||||
/// Helper function for apllying database migrations while wrapping a
|
||||
/// Helper function for applying database migrations while wrapping a
|
||||
/// [DatabaseConnection] in a newtype
|
||||
pub async fn try_from(database: DatabaseConnection) -> Result<Self, DbErr> {
|
||||
crate::migration::Migrator::up(&database, None).await?;
|
||||
|
||||
@@ -25,7 +25,7 @@ pub struct Model {
|
||||
/// The collection's directory
|
||||
pub directory: PathBytes,
|
||||
/// The collection's poster path
|
||||
pub relative_poster_path: Option<PathBytes>,
|
||||
pub relative_poster_path: Option<String>,
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
@@ -51,6 +51,24 @@ pub enum Relation {
|
||||
on_delete = "Cascade"
|
||||
)]
|
||||
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 {
|
||||
@@ -64,3 +82,15 @@ impl Related<super::libraries::Entity> for Entity {
|
||||
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
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub episode: EpisodeNumber,
|
||||
/// The number of additional contained episodes
|
||||
pub count: u8,
|
||||
/// The episode's slug
|
||||
pub slug: String,
|
||||
/// The episode's library
|
||||
@@ -30,9 +32,9 @@ pub struct Model {
|
||||
/// The episode's directory
|
||||
pub directory: PathBytes,
|
||||
/// The episode's media path
|
||||
pub relative_media_path: PathBytes,
|
||||
pub relative_media_path: String,
|
||||
/// The episode's poster path
|
||||
pub relative_poster_path: Option<PathBytes>,
|
||||
pub relative_poster_path: Option<String>,
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
@@ -49,6 +51,24 @@ pub enum Relation {
|
||||
on_delete = "Cascade"
|
||||
)]
|
||||
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 {
|
||||
@@ -56,3 +76,15 @@ impl Related<super::libraries::Entity> for Entity {
|
||||
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.library, LibraryId::from_raw($lid));
|
||||
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),+)?) => {
|
||||
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),+)?),
|
||||
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($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
|
||||
};
|
||||
}
|
||||
@@ -129,8 +129,8 @@ mod tests {
|
||||
assert_eq!(model.slug, concat!("M/", $id).to_string());
|
||||
assert_eq!(model.library, LibraryId::from_raw($lid));
|
||||
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_poster_path, noneable!(relative_poster_path, Path::new(concat!("M/Poster", $id)).to_owned().into() $(, $($skip),+)?));
|
||||
assert_eq!(model.relative_media_path, concat!("M/Media", $id));
|
||||
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),+)?) => {
|
||||
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),+)?),
|
||||
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($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_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("M/Poster", $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(concat!("M/Poster", $id).to_owned()) $(, $($skip),+)?),
|
||||
}.insert($db).await
|
||||
};
|
||||
}
|
||||
@@ -187,7 +187,7 @@ mod tests {
|
||||
assert_eq!(model.slug, concat!("S/", $id).to_string());
|
||||
assert_eq!(model.library, LibraryId::from_raw($lid));
|
||||
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),+)?) => {
|
||||
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),+)?),
|
||||
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($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
|
||||
};
|
||||
}
|
||||
@@ -242,7 +242,7 @@ mod tests {
|
||||
assert_eq!(model.slug, concat!("S/S", $id).to_string());
|
||||
assert_eq!(model.library, LibraryId::from_raw($lid));
|
||||
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),+)?) => {
|
||||
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),+)?),
|
||||
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($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
|
||||
};
|
||||
}
|
||||
@@ -292,8 +292,8 @@ mod tests {
|
||||
assert_eq!(model.slug, concat!("S/S/E", $id).to_string());
|
||||
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.relative_media_path, Path::new(concat!("E/Media", $id)).to_owned().into());
|
||||
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_media_path, concat!("E/Media", $id));
|
||||
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),+)?) => {
|
||||
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),+)?),
|
||||
season: notsettable!(season, $season $(, $($skip),+)?),
|
||||
episode: notsettable!(episode, $episode $(, $($skip),+)?),
|
||||
count: notsettable!(count, 0 $(, $($skip),+)?),
|
||||
slug: notsettable!(slug, concat!("S/S/E", $id).to_string() $(, $($skip),+)?),
|
||||
library: notsettable!(library, LibraryId::from_raw($lid) $(, $($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_poster_path: notsettable!(relative_poster_path, Some(Path::new(concat!("S/S/E/Poster", $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(concat!("S/S/E/Poster", $id).to_owned()) $(, $($skip),+)?),
|
||||
}.insert($db).await
|
||||
};
|
||||
}
|
||||
@@ -320,9 +321,9 @@ mod tests {
|
||||
make_flix_episode!(&db, 1, 1, 2);
|
||||
make_flix_episode!(&db, 2, 1, 1);
|
||||
make_flix_episode!(&db, 3, 1, 1);
|
||||
make_flix_show!(&db, 10);
|
||||
make_flix_season!(&db, 10, 1);
|
||||
make_flix_episode!(&db, 10, 1, 1);
|
||||
make_flix_show!(&db, 11);
|
||||
make_flix_season!(&db, 11, 1);
|
||||
make_flix_episode!(&db, 11, 1, 1);
|
||||
|
||||
assert_episode!(&db, 1, 1, 1, 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, 4, 1, 1, 1, NotNullViolation; season);
|
||||
assert_episode!(&db, 5, 1, 1, 1, NotNullViolation; episode);
|
||||
assert_episode!(&db, 6, 1, 1, 1, NotNullViolation; slug);
|
||||
assert_episode!(&db, 7, 1, 1, 1, NotNullViolation; library);
|
||||
assert_episode!(&db, 8, 1, 1, 1, NotNullViolation; directory);
|
||||
assert_episode!(&db, 9, 1, 1, 1, NotNullViolation; relative_media_path);
|
||||
assert_episode!(&db, 10, 1, 1, 1, Success; relative_poster_path);
|
||||
assert_episode!(&db, 6, 1, 1, 1, NotNullViolation; count);
|
||||
assert_episode!(&db, 7, 1, 1, 1, NotNullViolation; slug);
|
||||
assert_episode!(&db, 8, 1, 1, 1, NotNullViolation; library);
|
||||
assert_episode!(&db, 9, 1, 1, 1, NotNullViolation; directory);
|
||||
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
|
||||
pub directory: PathBytes,
|
||||
/// The movie's media path
|
||||
pub relative_media_path: PathBytes,
|
||||
pub relative_media_path: String,
|
||||
/// The movie's poster path
|
||||
pub relative_poster_path: Option<PathBytes>,
|
||||
pub relative_poster_path: Option<String>,
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
@@ -53,6 +53,24 @@ pub enum Relation {
|
||||
on_delete = "Cascade"
|
||||
)]
|
||||
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 {
|
||||
@@ -66,3 +84,15 @@ impl Related<super::libraries::Entity> for Entity {
|
||||
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
|
||||
pub directory: PathBytes,
|
||||
/// The season's poster path
|
||||
pub relative_poster_path: Option<PathBytes>,
|
||||
pub relative_poster_path: Option<String>,
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
@@ -44,6 +44,24 @@ pub enum Relation {
|
||||
on_delete = "Cascade"
|
||||
)]
|
||||
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 {
|
||||
@@ -51,3 +69,15 @@ impl Related<super::libraries::Entity> for Entity {
|
||||
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
|
||||
pub directory: PathBytes,
|
||||
/// The show's poster path
|
||||
pub relative_poster_path: Option<PathBytes>,
|
||||
pub relative_poster_path: Option<String>,
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
@@ -51,6 +51,24 @@ pub enum Relation {
|
||||
on_delete = "Cascade"
|
||||
)]
|
||||
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 {
|
||||
@@ -64,3 +82,15 @@ impl Related<super::libraries::Entity> for Entity {
|
||||
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 sea_orm::{
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
||||
PrimaryKeyTrait,
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||
EnumIter, PrimaryKeyTrait,
|
||||
};
|
||||
|
||||
/// The database representation of a flix collection
|
||||
|
||||
@@ -4,8 +4,8 @@ use flix_model::id::MovieId;
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use sea_orm::{
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
||||
PrimaryKeyTrait,
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||
EnumIter, PrimaryKeyTrait,
|
||||
};
|
||||
|
||||
/// The database representation of a flix movie
|
||||
|
||||
@@ -108,7 +108,7 @@ mod tests {
|
||||
slug: Set(::std::string::String::new()),
|
||||
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
||||
directory: Set(::std::path::PathBuf::new().into()),
|
||||
relative_poster_path: Set(None),
|
||||
relative_poster_path: Set(::core::option::Option::None),
|
||||
}
|
||||
.insert($db)
|
||||
.await
|
||||
@@ -144,8 +144,8 @@ mod tests {
|
||||
slug: Set(::std::string::String::new()),
|
||||
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
||||
directory: Set(::std::path::PathBuf::new().into()),
|
||||
relative_media_path: Set(::std::path::PathBuf::new().into()),
|
||||
relative_poster_path: Set(None),
|
||||
relative_media_path: Set(::std::string::String::new()),
|
||||
relative_poster_path: Set(::core::option::Option::None),
|
||||
}
|
||||
.insert($db)
|
||||
.await
|
||||
@@ -181,7 +181,7 @@ mod tests {
|
||||
slug: Set(::std::string::String::new()),
|
||||
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
||||
directory: Set(::std::path::PathBuf::new().into()),
|
||||
relative_poster_path: Set(None),
|
||||
relative_poster_path: Set(::core::option::Option::None),
|
||||
}
|
||||
.insert($db)
|
||||
.await
|
||||
@@ -216,7 +216,7 @@ mod tests {
|
||||
slug: Set(::std::string::String::new()),
|
||||
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
||||
directory: Set(::std::path::PathBuf::new().into()),
|
||||
relative_poster_path: Set(None),
|
||||
relative_poster_path: Set(::core::option::Option::None),
|
||||
}
|
||||
.insert($db)
|
||||
.await
|
||||
@@ -245,16 +245,23 @@ mod tests {
|
||||
pub(super) use make_flix_episode;
|
||||
macro_rules! have_episode {
|
||||
($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::content::episodes::ActiveModel {
|
||||
show: Set(::flix_model::id::ShowId::from_raw($show)),
|
||||
season: Set($season),
|
||||
episode: Set($episode),
|
||||
count: Set($count),
|
||||
slug: Set(::std::string::String::new()),
|
||||
library: Set(::flix_model::id::LibraryId::from_raw($lid)),
|
||||
directory: Set(::std::path::PathBuf::new().into()),
|
||||
relative_media_path: Set(::std::path::PathBuf::new().into()),
|
||||
relative_poster_path: Set(None),
|
||||
relative_media_path: Set(::std::string::String::new()),
|
||||
relative_poster_path: Set(::core::option::Option::None),
|
||||
}
|
||||
.insert($db)
|
||||
.await
|
||||
|
||||
@@ -7,8 +7,8 @@ use seamantic::model::duration::Seconds;
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use sea_orm::{
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
||||
PrimaryKeyTrait,
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||
EnumIter, PrimaryKeyTrait,
|
||||
};
|
||||
|
||||
/// The database representation of a tmdb episode
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
use flix_model::id::{CollectionId, RawId};
|
||||
|
||||
use sea_orm::{
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
||||
PrimaryKeyTrait,
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||
EnumIter, PrimaryKeyTrait,
|
||||
};
|
||||
|
||||
/// The database representation of a watched movie
|
||||
|
||||
@@ -5,8 +5,8 @@ use flix_model::numbers::{EpisodeNumber, SeasonNumber};
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use sea_orm::{
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
||||
PrimaryKeyTrait,
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||
EnumIter, PrimaryKeyTrait,
|
||||
};
|
||||
|
||||
/// The database representation of a watched movie
|
||||
|
||||
@@ -181,12 +181,10 @@ mod tests {
|
||||
have_episode!(&db, 1, 1, 1, 1);
|
||||
assert_episode!(&db, 1, 1, 1, 1, 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, 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_episode!(&db, 1, 1, 2, 1);
|
||||
assert_episode!(&db, 1, 2, 1, 1, Success);
|
||||
|
||||
@@ -4,8 +4,8 @@ use flix_model::id::{MovieId, RawId};
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use sea_orm::{
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
||||
PrimaryKeyTrait,
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||
EnumIter, PrimaryKeyTrait,
|
||||
};
|
||||
|
||||
/// The database representation of a watched movie
|
||||
|
||||
@@ -5,8 +5,8 @@ use flix_model::numbers::SeasonNumber;
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use sea_orm::{
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
||||
PrimaryKeyTrait,
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||
EnumIter, PrimaryKeyTrait,
|
||||
};
|
||||
|
||||
/// The database representation of a watched movie
|
||||
|
||||
@@ -4,8 +4,8 @@ use flix_model::id::{RawId, ShowId};
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use sea_orm::{
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
||||
PrimaryKeyTrait,
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||
EnumIter, PrimaryKeyTrait,
|
||||
};
|
||||
|
||||
/// 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::{DbErr, Iden};
|
||||
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_000003::FlixLibraries;
|
||||
@@ -30,7 +30,7 @@ pub async fn up(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
|
||||
.col(string(FlixCollections::Slug))
|
||||
.col(integer(FlixCollections::Library))
|
||||
.col(binary(FlixCollections::Directory))
|
||||
.col(binary_null(FlixCollections::RelativePosterPath))
|
||||
.col(string_null(FlixCollections::RelativePosterPath))
|
||||
.foreign_key(
|
||||
ForeignKeyCreateStatement::new()
|
||||
.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::{DbErr, Iden};
|
||||
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_000003::FlixLibraries;
|
||||
@@ -13,6 +13,7 @@ pub enum FlixEpisodes {
|
||||
Show,
|
||||
Season,
|
||||
Episode,
|
||||
Count,
|
||||
Slug,
|
||||
Library,
|
||||
Directory,
|
||||
@@ -28,11 +29,12 @@ pub async fn up(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
|
||||
.col(integer(FlixEpisodes::Show))
|
||||
.col(integer(FlixEpisodes::Season))
|
||||
.col(integer(FlixEpisodes::Episode))
|
||||
.col(integer(FlixEpisodes::Count))
|
||||
.col(string(FlixEpisodes::Slug))
|
||||
.col(integer(FlixEpisodes::Library))
|
||||
.col(binary(FlixEpisodes::Directory))
|
||||
.col(binary(FlixEpisodes::RelativeMediaPath))
|
||||
.col(binary_null(FlixEpisodes::RelativePosterPath))
|
||||
.col(string(FlixEpisodes::RelativeMediaPath))
|
||||
.col(string_null(FlixEpisodes::RelativePosterPath))
|
||||
.primary_key(
|
||||
Index::create()
|
||||
.col(FlixEpisodes::Show)
|
||||
|
||||
@@ -4,7 +4,7 @@ use sea_orm::sea_query;
|
||||
use sea_orm::sea_query::{ForeignKeyCreateStatement, Table};
|
||||
use sea_orm::{DbErr, Iden};
|
||||
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_000003::{FlixCollections, FlixLibraries};
|
||||
@@ -31,8 +31,8 @@ pub async fn up(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
|
||||
.col(string(FlixMovies::Slug))
|
||||
.col(integer(FlixMovies::Library))
|
||||
.col(binary(FlixMovies::Directory))
|
||||
.col(binary(FlixMovies::RelativeMediaPath))
|
||||
.col(binary_null(FlixMovies::RelativePosterPath))
|
||||
.col(string(FlixMovies::RelativeMediaPath))
|
||||
.col(string_null(FlixMovies::RelativePosterPath))
|
||||
.foreign_key(
|
||||
ForeignKeyCreateStatement::new()
|
||||
.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::{DbErr, Iden};
|
||||
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_000003::FlixLibraries;
|
||||
@@ -28,7 +28,7 @@ pub async fn up(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
|
||||
.col(string(FlixSeasons::Slug))
|
||||
.col(integer(FlixSeasons::Library))
|
||||
.col(binary(FlixSeasons::Directory))
|
||||
.col(binary_null(FlixSeasons::RelativePosterPath))
|
||||
.col(string_null(FlixSeasons::RelativePosterPath))
|
||||
.primary_key(
|
||||
Index::create()
|
||||
.col(FlixSeasons::Show)
|
||||
|
||||
@@ -4,7 +4,7 @@ use sea_orm::sea_query;
|
||||
use sea_orm::sea_query::{ForeignKeyCreateStatement, Table};
|
||||
use sea_orm::{DbErr, Iden};
|
||||
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_000003::{FlixCollections, FlixLibraries};
|
||||
@@ -30,7 +30,7 @@ pub async fn up(manager: &SchemaManager<'_>) -> Result<(), DbErr> {
|
||||
.col(string(FlixShows::Slug))
|
||||
.col(integer(FlixShows::Library))
|
||||
.col(binary(FlixShows::Directory))
|
||||
.col(binary_null(FlixShows::RelativePosterPath))
|
||||
.col(string_null(FlixShows::RelativePosterPath))
|
||||
.foreign_key(
|
||||
ForeignKeyCreateStatement::new()
|
||||
.name("fk-flix_shows-id")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix"
|
||||
version = "0.0.9"
|
||||
version = "0.0.12"
|
||||
|
||||
categories = []
|
||||
description = "Mechanisms for interacting with flix media"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix-fs"
|
||||
version = "0.0.9"
|
||||
version = "0.0.12"
|
||||
|
||||
categories = []
|
||||
description = "Filesystem scanner for flix media"
|
||||
@@ -22,7 +22,7 @@ workspace = true
|
||||
flix-model = { workspace = true }
|
||||
|
||||
async-stream = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
regex = { workspace = true, features = ["std", "perf"] }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-stream = { workspace = true, features = ["fs"] }
|
||||
|
||||
@@ -47,17 +47,17 @@ pub enum Scanner {
|
||||
Show {
|
||||
/// The ID of the parent collection (if any)
|
||||
parent: Option<CollectionId>,
|
||||
/// The ID of the show this episode belongs to
|
||||
/// The ID of the show
|
||||
id: ShowId,
|
||||
/// The file name of the poster file
|
||||
poster_file_name: Option<String>,
|
||||
},
|
||||
/// A scanned episode
|
||||
Season {
|
||||
/// The ID of the show this episode belongs to
|
||||
/// The ID of the show this season belongs to
|
||||
show: ShowId,
|
||||
/// The season this episode belongs to
|
||||
number: SeasonNumber,
|
||||
/// The number of this season
|
||||
season: SeasonNumber,
|
||||
/// The file name of the poster file
|
||||
poster_file_name: Option<String>,
|
||||
},
|
||||
@@ -68,7 +68,7 @@ pub enum Scanner {
|
||||
/// The season this episode belongs to
|
||||
season: SeasonNumber,
|
||||
/// The number(s) of this episode
|
||||
number: EpisodeNumbers,
|
||||
episode: EpisodeNumbers,
|
||||
/// The file name of the media file
|
||||
media_file_name: String,
|
||||
/// The file name of the poster file
|
||||
@@ -108,23 +108,23 @@ impl From<show::Scanner> for Scanner {
|
||||
},
|
||||
show::Scanner::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
} => Self::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
},
|
||||
show::Scanner::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
} => Self::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
},
|
||||
@@ -166,23 +166,23 @@ impl From<generic::Scanner> for Scanner {
|
||||
},
|
||||
generic::Scanner::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
} => Self::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
},
|
||||
generic::Scanner::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
} => Self::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
},
|
||||
|
||||
@@ -26,7 +26,7 @@ pub enum Scanner {
|
||||
/// The season this episode belongs to
|
||||
season: SeasonNumber,
|
||||
/// The number(s) of this episode
|
||||
number: EpisodeNumbers,
|
||||
episode: EpisodeNumbers,
|
||||
/// The file name of the media file
|
||||
media_file_name: String,
|
||||
/// The file name of the poster file
|
||||
@@ -40,7 +40,7 @@ impl Scanner {
|
||||
path: &Path,
|
||||
show: ShowId,
|
||||
season: SeasonNumber,
|
||||
number: EpisodeNumbers,
|
||||
episode: EpisodeNumbers,
|
||||
) -> impl Stream<Item = Item> {
|
||||
stream!({
|
||||
let dirs = match fs::read_dir(path).await {
|
||||
@@ -137,7 +137,7 @@ impl Scanner {
|
||||
event: Ok(Self::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
}),
|
||||
|
||||
@@ -51,17 +51,17 @@ pub enum Scanner {
|
||||
Show {
|
||||
/// The ID of the parent collection (if any)
|
||||
parent: Option<CollectionId>,
|
||||
/// The ID of the show this episode belongs to
|
||||
/// The ID of the show
|
||||
id: ShowId,
|
||||
/// The file name of the poster file
|
||||
poster_file_name: Option<String>,
|
||||
},
|
||||
/// A scanned episode
|
||||
Season {
|
||||
/// The ID of the show this episode belongs to
|
||||
/// The ID of the show this season belongs to
|
||||
show: ShowId,
|
||||
/// The season this episode belongs to
|
||||
number: SeasonNumber,
|
||||
season: SeasonNumber,
|
||||
/// The file name of the poster file
|
||||
poster_file_name: Option<String>,
|
||||
},
|
||||
@@ -72,7 +72,7 @@ pub enum Scanner {
|
||||
/// The season this episode belongs to
|
||||
season: SeasonNumber,
|
||||
/// The number(s) of this episode
|
||||
number: EpisodeNumbers,
|
||||
episode: EpisodeNumbers,
|
||||
/// The file name of the media file
|
||||
media_file_name: String,
|
||||
/// The file name of the poster file
|
||||
@@ -114,23 +114,23 @@ impl From<collection::Scanner> for Scanner {
|
||||
},
|
||||
collection::Scanner::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
} => Self::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
},
|
||||
collection::Scanner::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
} => Self::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
},
|
||||
@@ -170,23 +170,23 @@ impl From<show::Scanner> for Scanner {
|
||||
},
|
||||
show::Scanner::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
} => Self::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
},
|
||||
show::Scanner::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
} => Self::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
},
|
||||
@@ -211,10 +211,12 @@ impl Scanner {
|
||||
}
|
||||
|
||||
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!({
|
||||
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 {
|
||||
/// A scanned episode
|
||||
Season {
|
||||
/// The ID of the show this episode belongs to
|
||||
/// The ID of the show this season belongs to
|
||||
show: ShowId,
|
||||
/// The season this episode belongs to
|
||||
number: SeasonNumber,
|
||||
season: SeasonNumber,
|
||||
/// The file name of the poster file
|
||||
poster_file_name: Option<String>,
|
||||
},
|
||||
@@ -36,7 +36,7 @@ pub enum Scanner {
|
||||
/// The season this episode belongs to
|
||||
season: SeasonNumber,
|
||||
/// The number(s) of this episode
|
||||
number: EpisodeNumbers,
|
||||
episode: EpisodeNumbers,
|
||||
/// The file name of the media file
|
||||
media_file_name: String,
|
||||
/// The file name of the poster file
|
||||
@@ -50,13 +50,13 @@ impl From<episode::Scanner> for Scanner {
|
||||
episode::Scanner::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
} => Self::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
},
|
||||
@@ -69,7 +69,7 @@ impl Scanner {
|
||||
pub fn scan_season(
|
||||
path: &Path,
|
||||
show: ShowId,
|
||||
number: SeasonNumber,
|
||||
season: SeasonNumber,
|
||||
) -> impl Stream<Item = Item> {
|
||||
stream!({
|
||||
let dirs = match fs::read_dir(path).await {
|
||||
@@ -141,7 +141,7 @@ impl Scanner {
|
||||
path: path.to_owned(),
|
||||
event: Ok(Self::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
}),
|
||||
};
|
||||
@@ -170,14 +170,14 @@ impl Scanner {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Ok(season) = s_str.parse::<SeasonNumber>() else {
|
||||
let Ok(season_number) = s_str.parse::<SeasonNumber>() else {
|
||||
yield Item {
|
||||
path: path.to_owned(),
|
||||
event: Err(Error::UnexpectedFolder),
|
||||
};
|
||||
continue;
|
||||
};
|
||||
if season != number {
|
||||
if season_number != season {
|
||||
yield Item {
|
||||
path: path.to_owned(),
|
||||
event: Err(Error::Inconsistent),
|
||||
@@ -204,9 +204,12 @@ impl Scanner {
|
||||
continue;
|
||||
};
|
||||
|
||||
for await event in
|
||||
episode::Scanner::scan_episode(&episode_dir, show, number, episode_numbers)
|
||||
{
|
||||
for await event in episode::Scanner::scan_episode(
|
||||
&episode_dir,
|
||||
show,
|
||||
season_number,
|
||||
episode_numbers,
|
||||
) {
|
||||
yield event.map(|e| e.into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,17 @@ pub enum Scanner {
|
||||
Show {
|
||||
/// The ID of the parent collection (if any)
|
||||
parent: Option<CollectionId>,
|
||||
/// The ID of the show this episode belongs to
|
||||
/// The ID of the show
|
||||
id: ShowId,
|
||||
/// The file name of the poster file
|
||||
poster_file_name: Option<String>,
|
||||
},
|
||||
/// A scanned episode
|
||||
Season {
|
||||
/// The ID of the show this episode belongs to
|
||||
/// The ID of the show this season belongs to
|
||||
show: ShowId,
|
||||
/// The season this episode belongs to
|
||||
number: SeasonNumber,
|
||||
season: SeasonNumber,
|
||||
/// The file name of the poster file
|
||||
poster_file_name: Option<String>,
|
||||
},
|
||||
@@ -45,7 +45,7 @@ pub enum Scanner {
|
||||
/// The season this episode belongs to
|
||||
season: SeasonNumber,
|
||||
/// The number(s) of this episode
|
||||
number: EpisodeNumbers,
|
||||
episode: EpisodeNumbers,
|
||||
/// The file name of the media file
|
||||
media_file_name: String,
|
||||
/// The file name of the poster file
|
||||
@@ -58,23 +58,23 @@ impl From<season::Scanner> for Scanner {
|
||||
match value {
|
||||
season::Scanner::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
} => Self::Season {
|
||||
show,
|
||||
number,
|
||||
season,
|
||||
poster_file_name,
|
||||
},
|
||||
season::Scanner::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
} => Self::Episode {
|
||||
show,
|
||||
season,
|
||||
number,
|
||||
episode,
|
||||
media_file_name,
|
||||
poster_file_name,
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix-model"
|
||||
version = "0.0.9"
|
||||
version = "0.0.12"
|
||||
|
||||
categories = []
|
||||
description = "Core types for flix data"
|
||||
|
||||
@@ -58,21 +58,3 @@ impl EpisodeNumbers {
|
||||
&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]
|
||||
name = "flix-tmdb"
|
||||
version = "0.0.9"
|
||||
version = "0.0.12"
|
||||
|
||||
categories = []
|
||||
description = "Clients and models for fetching data from TMDB"
|
||||
|
||||
@@ -150,8 +150,8 @@ mod tests {
|
||||
#[cfg(feature = "sea-orm")]
|
||||
fn test_sea_orm() {
|
||||
use sea_orm::{
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EnumIter,
|
||||
PrimaryKeyTrait,
|
||||
ActiveModelBehavior, DeriveEntityModel, DerivePrimaryKey, DeriveRelation, EntityTrait,
|
||||
EnumIter, PrimaryKeyTrait,
|
||||
};
|
||||
|
||||
use super::Id;
|
||||
@@ -184,7 +184,7 @@ mod tests {
|
||||
/// Type alias for the raw ID representation
|
||||
pub use self::TmdbRepr as RawId;
|
||||
|
||||
/// A placeholder type used for CollectionId
|
||||
#[doc(hidden)]
|
||||
pub enum Collection {}
|
||||
/// Type alias for a collection ID
|
||||
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 {}
|
||||
/// Type alias for a movie ID
|
||||
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 {}
|
||||
/// Type alias for a show ID
|
||||
pub type ShowId = Id<Show>;
|
||||
|
||||
Reference in New Issue
Block a user