Throw away flix files in favor of a flix database

This commit is contained in:
2025-09-18 22:41:34 -06:00
parent ba9c3fa03d
commit 06110b91a1
117 changed files with 8645 additions and 1054 deletions
+26
View File
@@ -0,0 +1,26 @@
//! This module contains types relating to flix media IDs
use seamantic::model::id::Id;
/// Type alias for the raw ID representation
pub use seamantic::model::id::SeaOrmRepr as RawId;
#[doc(hidden)]
pub enum Library {}
/// Type alias for a library ID
pub type LibraryId = Id<Library>;
#[doc(hidden)]
pub enum Collection {}
/// Type alias for a collection ID
pub type CollectionId = Id<Collection>;
#[doc(hidden)]
pub enum Movie {}
/// Type alias for a movie ID
pub type MovieId = Id<Movie>;
#[doc(hidden)]
pub enum Show {}
/// Type alias for a show ID
pub type ShowId = Id<Show>;
+6
View File
@@ -0,0 +1,6 @@
//! flix-model provides core types for flix data
#![cfg_attr(docsrs, feature(doc_cfg))]
pub mod id;
pub mod numbers;
+78
View File
@@ -0,0 +1,78 @@
//! This module contains season and episode numbers and related errors
use core::ops::RangeInclusive;
use std::collections::HashSet;
/// Type alias for representing season numbers
pub type SeasonNumber = u32;
/// Type alias for representing episode numbers
pub type EpisodeNumber = u32;
/// Potential errors when building EpisodeNumbers
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// There are no episodes
#[error("zero episodes")]
Zero,
/// There are gaps in the episodes
#[error("noncontiguous episodes")]
Noncontiguous,
}
/// A wrapper for handling single and multi-episode entries
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EpisodeNumbers(RangeInclusive<EpisodeNumber>);
impl TryFrom<&[EpisodeNumber]> for EpisodeNumbers {
type Error = Error;
fn try_from(value: &[EpisodeNumber]) -> Result<Self, Self::Error> {
match value {
[] => Err(Error::Zero),
[n] => Ok(Self(*n..=*n)),
_ => {
// min and max will always exist
let min = value.iter().copied().min().unwrap_or_default();
let max = value.iter().copied().max().unwrap_or_default();
let len = value.len();
if usize::try_from(max.saturating_sub(min).saturating_add(1)) != Ok(len) {
return Err(Error::Noncontiguous);
}
let set: HashSet<_> = value.iter().copied().collect();
if set.len() != len {
return Err(Error::Noncontiguous);
}
Ok(Self(min..=max))
}
}
}
}
impl EpisodeNumbers {
/// Get the range of episodes
pub fn as_range(&self) -> &RangeInclusive<EpisodeNumber> {
&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(&[]),
// }
// }
// }