You've already forked flix
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
cf4327389a
|
Generated
+715
-338
File diff suppressed because it is too large
Load Diff
+17
-13
@@ -3,40 +3,44 @@ resolver = "2"
|
|||||||
members = ["crates/*"]
|
members = ["crates/*"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
edition = "2024"
|
|
||||||
rust-version = "1.89.0"
|
|
||||||
license-file = "LICENSE.md"
|
license-file = "LICENSE.md"
|
||||||
|
|
||||||
|
edition = "2024"
|
||||||
|
rust-version = "1.89.0"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
flix = { path = "crates/flix", version = "=0.0.18", default-features = false }
|
||||||
|
flix-cli = { path = "crates/cli", version = "=0.0.18", default-features = false }
|
||||||
|
flix-db = { path = "crates/db", version = "=0.0.18", default-features = false }
|
||||||
|
flix-fs = { path = "crates/fs", version = "=0.0.18", default-features = false }
|
||||||
|
flix-model = { path = "crates/model", version = "=0.0.18", default-features = false }
|
||||||
|
flix-tmdb = { path = "crates/tmdb", version = "=0.0.18", default-features = false }
|
||||||
|
|
||||||
|
seamantic = { version = "^0.0.13", default-features = false }
|
||||||
|
|
||||||
|
sea-orm = { version = "=2.0.0-rc.38", default-features = false }
|
||||||
|
sea-orm-migration = { version = "=2.0.0-rc.38", 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 }
|
||||||
bytes = { version = "^1", default-features = false }
|
bytes = { version = "^1", default-features = false }
|
||||||
chrono = { version = "^0.4", default-features = false }
|
chrono = { version = "^0.4", default-features = false }
|
||||||
clap = { version = "^4", default-features = false }
|
clap = { version = "^4", default-features = false }
|
||||||
either = { version = "^1", default-features = false }
|
either = { version = "^1", default-features = false }
|
||||||
flix = { path = "crates/flix", version = "=0.0.17", default-features = false }
|
|
||||||
flix-cli = { path = "crates/cli", version = "=0.0.17", default-features = false }
|
|
||||||
flix-db = { path = "crates/db", version = "=0.0.17", default-features = false }
|
|
||||||
flix-fs = { path = "crates/fs", version = "=0.0.17", default-features = false }
|
|
||||||
flix-model = { path = "crates/model", version = "=0.0.17", default-features = false }
|
|
||||||
flix-tmdb = { path = "crates/tmdb", version = "=0.0.17", default-features = false }
|
|
||||||
futures = { version = "^0.3", default-features = false }
|
futures = { version = "^0.3", default-features = false }
|
||||||
governor = { version = "^0.10", default-features = false }
|
governor = { version = "^0.10", default-features = false }
|
||||||
itertools = { version = "^0.14", default-features = false }
|
itertools = { version = "^0.14", default-features = false }
|
||||||
nonzero_ext = { version = "^0.3", default-features = false }
|
nonzero_ext = { version = "^0.3", default-features = false }
|
||||||
redb = { version = "^3", default-features = false }
|
redb = { version = "^4", default-features = false }
|
||||||
regex = { version = "^1", default-features = false }
|
regex = { version = "^1", default-features = false }
|
||||||
reqwest = { version = "^0.13", default-features = false }
|
reqwest = { version = "^0.13", default-features = false }
|
||||||
sea-orm = { version = "2.0.0-rc.27", default-features = false }
|
|
||||||
sea-orm-migration = { version = "2.0.0-rc.27", default-features = false }
|
|
||||||
seamantic = { version = "^0.0.12", default-features = false }
|
|
||||||
serde = { version = "^1", default-features = false }
|
serde = { version = "^1", default-features = false }
|
||||||
serde_json = { version = "^1", default-features = false }
|
serde_json = { version = "^1", default-features = false }
|
||||||
serde_test = { version = "^1", default-features = false }
|
serde_test = { version = "^1", default-features = false }
|
||||||
thiserror = { version = "^2", default-features = false }
|
thiserror = { version = "^2", default-features = false }
|
||||||
tokio = { version = "^1", default-features = false }
|
tokio = { version = "^1", default-features = false }
|
||||||
tokio-stream = { version = "^0.1", default-features = false }
|
tokio-stream = { version = "^0.1", default-features = false }
|
||||||
toml = { version = "^0.9", default-features = false }
|
toml = { version = "^1", default-features = false }
|
||||||
tracing = { version = "^0.1", default-features = false }
|
tracing = { version = "^0.1", default-features = false }
|
||||||
tracing-subscriber = { version = "^0.3", default-features = false }
|
tracing-subscriber = { version = "^0.3", default-features = false }
|
||||||
url = { version = "^2", default-features = false }
|
url = { version = "^2", default-features = false }
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix-cli"
|
name = "flix-cli"
|
||||||
version = "0.0.17"
|
version = "0.0.18"
|
||||||
edition.workspace = true
|
license-file.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
description = "CLI for interacting with a flix database"
|
description = "CLI for interacting with a flix database"
|
||||||
repository = "https://github.com/QuantumShade/flix"
|
repository = "https://github.com/QuantumShade/flix"
|
||||||
license-file.workspace = true
|
|
||||||
categories = ["command-line-utilities"]
|
categories = ["command-line-utilities"]
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
@@ -53,4 +55,6 @@ unwrap_used = "deny"
|
|||||||
|
|
||||||
[lints.rust]
|
[lints.rust]
|
||||||
arithmetic_overflow = "forbid"
|
arithmetic_overflow = "forbid"
|
||||||
|
missing_docs = "forbid"
|
||||||
unsafe_code = "forbid"
|
unsafe_code = "forbid"
|
||||||
|
unused_doc_comments = "forbid"
|
||||||
|
|||||||
@@ -87,23 +87,6 @@ pub enum Command {
|
|||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: UpdateCommand,
|
command: UpdateCommand,
|
||||||
},
|
},
|
||||||
/// Delete an existing item in the database
|
|
||||||
Delete {
|
|
||||||
#[command(subcommand)]
|
|
||||||
command: DeleteCommand,
|
|
||||||
},
|
|
||||||
/// Create a toml backup of the database
|
|
||||||
Backup {
|
|
||||||
/// Change the destination
|
|
||||||
#[arg(short, long, value_name = "FILE", default_value = "./flix.toml")]
|
|
||||||
output: PathBuf,
|
|
||||||
},
|
|
||||||
/// Create a database from a toml backup
|
|
||||||
Restore {
|
|
||||||
/// Change the source
|
|
||||||
#[arg(short, long, value_name = "FILE", default_value = "./flix.toml")]
|
|
||||||
input: PathBuf,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
@@ -146,18 +129,3 @@ impl From<tmdb::Command> for UpdateCommand {
|
|||||||
Self::Tmdb { command: value }
|
Self::Tmdb { command: value }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
|
||||||
pub enum DeleteCommand {
|
|
||||||
/// Use the TMDB backend
|
|
||||||
Tmdb {
|
|
||||||
#[command(subcommand)]
|
|
||||||
command: tmdb::Command,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<tmdb::Command> for DeleteCommand {
|
|
||||||
fn from(value: tmdb::Command) -> Self {
|
|
||||||
Self::Tmdb { command: value }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-24
@@ -1,4 +1,5 @@
|
|||||||
use std::path::PathBuf;
|
//! flix-cli
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use flix::tmdb::{self, CachePolicy, Client, RedbCache};
|
use flix::tmdb::{self, CachePolicy, Client, RedbCache};
|
||||||
@@ -8,7 +9,7 @@ use clap::Parser;
|
|||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
use cli::{AddCommand, Cli, Command, DeleteCommand, UpdateCommand};
|
use cli::{AddCommand, Cli, Command, UpdateCommand};
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
use config::Config;
|
use config::Config;
|
||||||
@@ -48,9 +49,6 @@ async fn main() -> Result<()> {
|
|||||||
exec_add(client, database_path, command, overrides).await?
|
exec_add(client, database_path, command, overrides).await?
|
||||||
}
|
}
|
||||||
Command::Update { command } => exec_update(client, database_path, command).await?,
|
Command::Update { command } => exec_update(client, database_path, command).await?,
|
||||||
Command::Delete { command } => exec_delete(client, database_path, command).await?,
|
|
||||||
Command::Backup { output } => exec_backup(database_path, output).await?,
|
|
||||||
Command::Restore { input } => exec_restore(database_path, input).await?,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -93,22 +91,3 @@ async fn exec_update(client: Client, database_path: String, command: UpdateComma
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn exec_delete(client: Client, database_path: String, command: DeleteCommand) -> Result<()> {
|
|
||||||
_ = client;
|
|
||||||
_ = database_path;
|
|
||||||
_ = command;
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn exec_backup(database_path: String, output: PathBuf) -> Result<()> {
|
|
||||||
_ = database_path;
|
|
||||||
_ = output;
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn exec_restore(database_path: String, input: PathBuf) -> Result<()> {
|
|
||||||
_ = database_path;
|
|
||||||
_ = input;
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|||||||
+544
-2
@@ -568,9 +568,551 @@ pub async fn add(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update(client: Client, database: &DatabaseConnection, command: Command) -> Result<()> {
|
pub async fn update(client: Client, db: &DatabaseConnection, command: Command) -> Result<()> {
|
||||||
_ = client;
|
_ = client;
|
||||||
_ = database;
|
_ = db;
|
||||||
_ = command;
|
_ = command;
|
||||||
unimplemented!("updates")
|
unimplemented!("updates")
|
||||||
|
|
||||||
|
// match command {
|
||||||
|
// Command::Collection { id } => {
|
||||||
|
// let id = TmdbCollectionId::from_raw(id);
|
||||||
|
|
||||||
|
// let collection = entity::tmdb::collections::Entity::find_by_id(id)
|
||||||
|
// .one(db)
|
||||||
|
// .await?;
|
||||||
|
// if collection.is_some() {
|
||||||
|
// bail!("collection already exists");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let collection = client
|
||||||
|
// .collections()
|
||||||
|
// .get_details(id, None)
|
||||||
|
// .await
|
||||||
|
// .with_context(|| format!("collections().get_details({})", id.into_raw()))?;
|
||||||
|
|
||||||
|
// let title = overrides.title.unwrap_or(collection.title);
|
||||||
|
|
||||||
|
// let sort_title = overrides
|
||||||
|
// .sort_title
|
||||||
|
// .unwrap_or_else(|| text::make_sortable_title(&title));
|
||||||
|
// let fs_slug = overrides
|
||||||
|
// .fs_slug
|
||||||
|
// .unwrap_or_else(|| text::make_fs_slug(&title));
|
||||||
|
// let web_slug = overrides
|
||||||
|
// .web_slug
|
||||||
|
// .unwrap_or_else(|| text::make_web_slug(&title));
|
||||||
|
|
||||||
|
// let result: Result<CollectionId, TransactionError<DbErr>> = db
|
||||||
|
// .transaction(|txn| {
|
||||||
|
// let title = title.clone();
|
||||||
|
// Box::pin(async move {
|
||||||
|
// let flix = entity::info::collections::ActiveModel {
|
||||||
|
// id: NotSet,
|
||||||
|
// title: Set(title),
|
||||||
|
// overview: Set(collection.overview),
|
||||||
|
// sort_title: Set(sort_title),
|
||||||
|
// fs_slug: Set(fs_slug),
|
||||||
|
// web_slug: Set(web_slug),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// entity::tmdb::collections::ActiveModel {
|
||||||
|
// tmdb_id: Set(id),
|
||||||
|
// flix_id: Set(flix.id),
|
||||||
|
// last_update: Set(Utc::now()),
|
||||||
|
// movie_count: Set(collection.movies.len().try_into().unwrap_or(0)),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// Ok(flix.id)
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// .await;
|
||||||
|
|
||||||
|
// let flix_id = match result {
|
||||||
|
// Ok(id) => id,
|
||||||
|
// Err(TransactionError::Connection(err)) => Err(err)?,
|
||||||
|
// Err(TransactionError::Transaction(err)) => Err(err)?,
|
||||||
|
// };
|
||||||
|
// println!("Created Collection: {} [{}]", title, flix_id.into_raw());
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// Command::Movie { id } => {
|
||||||
|
// let id = TmdbMovieId::from_raw(id);
|
||||||
|
|
||||||
|
// let movie = entity::tmdb::movies::Entity::find_by_id(id).one(db).await?;
|
||||||
|
// if movie.is_some() {
|
||||||
|
// bail!("movie already exists");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let movie = client
|
||||||
|
// .movies()
|
||||||
|
// .get_details(id, None)
|
||||||
|
// .await
|
||||||
|
// .with_context(|| format!("movies().get_details({})", id.into_raw()))?;
|
||||||
|
|
||||||
|
// let title = overrides.title.unwrap_or(movie.title);
|
||||||
|
// let year = movie.release_date.year();
|
||||||
|
|
||||||
|
// let sort_title = overrides
|
||||||
|
// .sort_title
|
||||||
|
// .unwrap_or_else(|| text::make_sortable_title(&title));
|
||||||
|
// let fs_slug = overrides
|
||||||
|
// .fs_slug
|
||||||
|
// .unwrap_or_else(|| text::make_fs_slug_year(&title, year));
|
||||||
|
// let web_slug = overrides
|
||||||
|
// .web_slug
|
||||||
|
// .unwrap_or_else(|| text::make_web_slug_year(&title, year));
|
||||||
|
|
||||||
|
// let result: Result<MovieId, TransactionError<DbErr>> = db
|
||||||
|
// .transaction(|txn| {
|
||||||
|
// let title = title.clone();
|
||||||
|
// Box::pin(async move {
|
||||||
|
// let flix = entity::info::movies::ActiveModel {
|
||||||
|
// id: NotSet,
|
||||||
|
// title: Set(title),
|
||||||
|
// tagline: Set(movie.tagline),
|
||||||
|
// overview: Set(movie.overview),
|
||||||
|
// date: Set(movie.release_date),
|
||||||
|
// sort_title: Set(sort_title),
|
||||||
|
// fs_slug: Set(fs_slug),
|
||||||
|
// web_slug: Set(web_slug),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// entity::tmdb::movies::ActiveModel {
|
||||||
|
// tmdb_id: Set(id),
|
||||||
|
// flix_id: Set(flix.id),
|
||||||
|
// last_update: Set(Utc::now()),
|
||||||
|
// runtime: Set(movie.runtime.into()),
|
||||||
|
// collection_id: Set(movie.collection.map(|c| c.id)),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// Ok(flix.id)
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// .await;
|
||||||
|
|
||||||
|
// let flix_id = match result {
|
||||||
|
// Ok(id) => id,
|
||||||
|
// Err(TransactionError::Connection(err)) => Err(err)?,
|
||||||
|
// Err(TransactionError::Transaction(err)) => Err(err)?,
|
||||||
|
// };
|
||||||
|
// println!(
|
||||||
|
// "Created Movie: {} ({}) [{}]",
|
||||||
|
// title,
|
||||||
|
// year,
|
||||||
|
// flix_id.into_raw(),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// Command::Show { id } => {
|
||||||
|
// let id = TmdbShowId::from_raw(id);
|
||||||
|
|
||||||
|
// let show = entity::tmdb::shows::Entity::find_by_id(id).one(db).await?;
|
||||||
|
// if show.is_some() {
|
||||||
|
// bail!("show already exists");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let show = client
|
||||||
|
// .shows()
|
||||||
|
// .get_details(id, None)
|
||||||
|
// .await
|
||||||
|
// .with_context(|| format!("shows().get_details({})", id.into_raw()))?;
|
||||||
|
// let mut seasons = Vec::new();
|
||||||
|
// let mut episodes = HashMap::new();
|
||||||
|
|
||||||
|
// for season in 1..=show.number_of_seasons {
|
||||||
|
// let season = SeasonNumber::new(season);
|
||||||
|
// let season = match client
|
||||||
|
// .seasons()
|
||||||
|
// .get_details(id, season, None)
|
||||||
|
// .await
|
||||||
|
// .with_context(|| {
|
||||||
|
// format!("seasons().get_details({}, {})", id.into_raw(), season)
|
||||||
|
// }) {
|
||||||
|
// Ok(season) => season,
|
||||||
|
// Err(err) => {
|
||||||
|
// eprintln!("{err:?}");
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// if season.air_date > Utc::now().naive_utc().date() {
|
||||||
|
// eprintln!(
|
||||||
|
// "skipping season ({}, {})",
|
||||||
|
// id.into_raw(),
|
||||||
|
// season.season_number
|
||||||
|
// );
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let Ok(number_of_episodes) = u32::try_from(season.episodes.len()) else {
|
||||||
|
// bail!(
|
||||||
|
// "could not convert {} to an EpisodeNumber",
|
||||||
|
// season.episodes.len()
|
||||||
|
// )
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let mut season_episodes = Vec::new();
|
||||||
|
// for episode in 1..=number_of_episodes {
|
||||||
|
// let episode = EpisodeNumber::new(episode);
|
||||||
|
// let Ok(episode) = client
|
||||||
|
// .episodes()
|
||||||
|
// .get_details(id, season.season_number, episode, None)
|
||||||
|
// .await
|
||||||
|
// else {
|
||||||
|
// eprintln!(
|
||||||
|
// "skipping episode ({}, {}, {})",
|
||||||
|
// id.into_raw(),
|
||||||
|
// season.season_number,
|
||||||
|
// episode
|
||||||
|
// );
|
||||||
|
// break;
|
||||||
|
// };
|
||||||
|
// season_episodes.push(episode);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// episodes.insert(season.season_number, season_episodes);
|
||||||
|
// seasons.push(season);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let title = overrides.title.unwrap_or(show.title);
|
||||||
|
// let year = show.first_air_date.year();
|
||||||
|
|
||||||
|
// let sort_title = overrides
|
||||||
|
// .sort_title
|
||||||
|
// .unwrap_or_else(|| text::make_sortable_title(&title));
|
||||||
|
// let fs_slug = overrides
|
||||||
|
// .fs_slug
|
||||||
|
// .unwrap_or_else(|| text::make_fs_slug_year(&title, year));
|
||||||
|
// let web_slug = overrides
|
||||||
|
// .web_slug
|
||||||
|
// .unwrap_or_else(|| text::make_web_slug_year(&title, year));
|
||||||
|
|
||||||
|
// let result: Result<ShowId, TransactionError<DbErr>> = db
|
||||||
|
// .transaction(|txn| {
|
||||||
|
// let title = title.clone();
|
||||||
|
// Box::pin(async move {
|
||||||
|
// let flix = entity::info::shows::ActiveModel {
|
||||||
|
// id: NotSet,
|
||||||
|
// title: Set(title),
|
||||||
|
// tagline: Set(show.tagline),
|
||||||
|
// overview: Set(show.overview),
|
||||||
|
// date: Set(show.first_air_date),
|
||||||
|
// sort_title: Set(sort_title),
|
||||||
|
// fs_slug: Set(fs_slug),
|
||||||
|
// web_slug: Set(web_slug),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// entity::tmdb::shows::ActiveModel {
|
||||||
|
// tmdb_id: Set(id),
|
||||||
|
// flix_id: Set(flix.id),
|
||||||
|
// last_update: Set(Utc::now()),
|
||||||
|
// number_of_seasons: Set(show.number_of_seasons),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// for season in seasons {
|
||||||
|
// entity::info::seasons::ActiveModel {
|
||||||
|
// show_id: Set(flix.id),
|
||||||
|
// season_number: Set(season.season_number),
|
||||||
|
// title: Set(season.title),
|
||||||
|
// overview: Set(season.overview),
|
||||||
|
// date: Set(season.air_date),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// entity::tmdb::seasons::ActiveModel {
|
||||||
|
// tmdb_show: Set(id),
|
||||||
|
// tmdb_season: Set(season.season_number),
|
||||||
|
// flix_show: Set(flix.id),
|
||||||
|
// flix_season: Set(season.season_number),
|
||||||
|
// last_update: Set(Utc::now()),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (season, episodes) in episodes {
|
||||||
|
// for episode in episodes {
|
||||||
|
// entity::info::episodes::ActiveModel {
|
||||||
|
// show_id: Set(flix.id),
|
||||||
|
// season_number: Set(season),
|
||||||
|
// episode_number: Set(episode.episode_number),
|
||||||
|
// title: Set(episode.title),
|
||||||
|
// overview: Set(episode.overview),
|
||||||
|
// date: Set(episode.air_date),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// entity::tmdb::episodes::ActiveModel {
|
||||||
|
// tmdb_show: Set(id),
|
||||||
|
// tmdb_season: Set(season),
|
||||||
|
// tmdb_episode: Set(episode.episode_number),
|
||||||
|
// flix_show: Set(flix.id),
|
||||||
|
// flix_season: Set(season),
|
||||||
|
// flix_episode: Set(episode.episode_number),
|
||||||
|
// last_update: Set(Utc::now()),
|
||||||
|
// runtime: Set(episode.runtime.into()),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Ok(flix.id)
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// .await;
|
||||||
|
|
||||||
|
// let flix_id = match result {
|
||||||
|
// Ok(id) => id,
|
||||||
|
// Err(TransactionError::Connection(err)) => Err(err)?,
|
||||||
|
// Err(TransactionError::Transaction(err)) => Err(err)?,
|
||||||
|
// };
|
||||||
|
// println!(
|
||||||
|
// "Created Show: {} ({}) [{}]",
|
||||||
|
// title,
|
||||||
|
// year,
|
||||||
|
// flix_id.into_raw()
|
||||||
|
// );
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// Command::Season { id, season } => {
|
||||||
|
// let id = TmdbShowId::from_raw(id);
|
||||||
|
// let season_number = season;
|
||||||
|
|
||||||
|
// let Some(show) = entity::tmdb::shows::Entity::find_by_id(id).one(db).await? else {
|
||||||
|
// bail!("show does not exists");
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let season = entity::tmdb::seasons::Entity::find_by_id((id, season))
|
||||||
|
// .one(db)
|
||||||
|
// .await?;
|
||||||
|
// if season.is_some() {
|
||||||
|
// bail!("season already exists");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let season = client
|
||||||
|
// .seasons()
|
||||||
|
// .get_details(id, season_number, None)
|
||||||
|
// .await
|
||||||
|
// .with_context(|| {
|
||||||
|
// format!(
|
||||||
|
// "seasons().get_details({}, {})",
|
||||||
|
// id.into_raw(),
|
||||||
|
// season_number
|
||||||
|
// )
|
||||||
|
// })?;
|
||||||
|
// let mut episodes = Vec::new();
|
||||||
|
|
||||||
|
// let Ok(number_of_episodes) = u32::try_from(season.episodes.len()) else {
|
||||||
|
// bail!(
|
||||||
|
// "could not convert {} to an EpisodeNumber",
|
||||||
|
// season.episodes.len()
|
||||||
|
// )
|
||||||
|
// };
|
||||||
|
|
||||||
|
// for episode in 1..=number_of_episodes {
|
||||||
|
// let episode = EpisodeNumber::new(episode);
|
||||||
|
// let Ok(episode) = client
|
||||||
|
// .episodes()
|
||||||
|
// .get_details(id, season.season_number, episode, None)
|
||||||
|
// .await
|
||||||
|
// else {
|
||||||
|
// eprintln!(
|
||||||
|
// "skipping episode ({}, {}, {})",
|
||||||
|
// id.into_raw(),
|
||||||
|
// season.season_number,
|
||||||
|
// episode
|
||||||
|
// );
|
||||||
|
// break;
|
||||||
|
// };
|
||||||
|
// episodes.push(episode);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let result: Result<(), TransactionError<DbErr>> = db
|
||||||
|
// .transaction(|txn| {
|
||||||
|
// Box::pin(async move {
|
||||||
|
// entity::info::seasons::ActiveModel {
|
||||||
|
// show_id: Set(show.flix_id),
|
||||||
|
// season_number: Set(season_number),
|
||||||
|
// title: Set(season.title),
|
||||||
|
// overview: Set(season.overview),
|
||||||
|
// date: Set(season.air_date),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// entity::tmdb::seasons::ActiveModel {
|
||||||
|
// tmdb_show: Set(show.tmdb_id),
|
||||||
|
// tmdb_season: Set(season_number),
|
||||||
|
// flix_show: Set(show.flix_id),
|
||||||
|
// flix_season: Set(season_number),
|
||||||
|
// last_update: Set(Utc::now()),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// for episode in episodes {
|
||||||
|
// entity::info::episodes::ActiveModel {
|
||||||
|
// show_id: Set(show.flix_id),
|
||||||
|
// season_number: Set(season_number),
|
||||||
|
// episode_number: Set(episode.episode_number),
|
||||||
|
// title: Set(episode.title),
|
||||||
|
// overview: Set(episode.overview),
|
||||||
|
// date: Set(episode.air_date),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// entity::tmdb::episodes::ActiveModel {
|
||||||
|
// tmdb_show: Set(show.tmdb_id),
|
||||||
|
// tmdb_season: Set(season_number),
|
||||||
|
// tmdb_episode: Set(episode.episode_number),
|
||||||
|
// flix_show: Set(show.flix_id),
|
||||||
|
// flix_season: Set(season_number),
|
||||||
|
// flix_episode: Set(episode.episode_number),
|
||||||
|
// last_update: Set(Utc::now()),
|
||||||
|
// runtime: Set(episode.runtime.into()),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// .await;
|
||||||
|
|
||||||
|
// match result {
|
||||||
|
// Ok(_) => (),
|
||||||
|
// Err(TransactionError::Connection(err)) => Err(err)?,
|
||||||
|
// Err(TransactionError::Transaction(err)) => Err(err)?,
|
||||||
|
// };
|
||||||
|
// println!(
|
||||||
|
// "Created Season: {} S{}",
|
||||||
|
// show.flix_id.into_raw(),
|
||||||
|
// season_number
|
||||||
|
// );
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// Command::Episode {
|
||||||
|
// id,
|
||||||
|
// season,
|
||||||
|
// episode,
|
||||||
|
// episodes,
|
||||||
|
// } => {
|
||||||
|
// let id = TmdbShowId::from_raw(id);
|
||||||
|
// let season_number = season;
|
||||||
|
|
||||||
|
// let Some(show) = entity::tmdb::shows::Entity::find_by_id(id).one(db).await? else {
|
||||||
|
// bail!("show does not exists");
|
||||||
|
// };
|
||||||
|
// let Some(_) = entity::tmdb::seasons::Entity::find_by_id((id, season))
|
||||||
|
// .one(db)
|
||||||
|
// .await?
|
||||||
|
// else {
|
||||||
|
// bail!("season does not exists");
|
||||||
|
// };
|
||||||
|
|
||||||
|
// async fn fetch_episode(
|
||||||
|
// client: &Client,
|
||||||
|
// db: &DatabaseConnection,
|
||||||
|
// flix_id: ShowId,
|
||||||
|
// tmdb_id: TmdbShowId,
|
||||||
|
// id: TmdbShowId,
|
||||||
|
// season: SeasonNumber,
|
||||||
|
// episode: EpisodeNumber,
|
||||||
|
// ) -> Result<()> {
|
||||||
|
// let episode_number = episode;
|
||||||
|
|
||||||
|
// let episode = entity::tmdb::episodes::Entity::find_by_id((id, season, episode))
|
||||||
|
// .one(db)
|
||||||
|
// .await?;
|
||||||
|
// if episode.is_some() {
|
||||||
|
// bail!("episode already exists");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let episode = client
|
||||||
|
// .episodes()
|
||||||
|
// .get_details(id, season, episode_number, None)
|
||||||
|
// .await
|
||||||
|
// .with_context(|| {
|
||||||
|
// format!("episodes().get_details({}, {})", id.into_raw(), season)
|
||||||
|
// })?;
|
||||||
|
|
||||||
|
// let result: Result<(), TransactionError<DbErr>> = db
|
||||||
|
// .transaction(|txn| {
|
||||||
|
// Box::pin(async move {
|
||||||
|
// entity::info::episodes::ActiveModel {
|
||||||
|
// show_id: Set(flix_id),
|
||||||
|
// season_number: Set(season),
|
||||||
|
// episode_number: Set(episode_number),
|
||||||
|
// title: Set(episode.title),
|
||||||
|
// overview: Set(episode.overview),
|
||||||
|
// date: Set(episode.air_date),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// entity::tmdb::episodes::ActiveModel {
|
||||||
|
// tmdb_show: Set(tmdb_id),
|
||||||
|
// tmdb_season: Set(season),
|
||||||
|
// tmdb_episode: Set(episode_number),
|
||||||
|
// flix_show: Set(flix_id),
|
||||||
|
// flix_season: Set(season),
|
||||||
|
// flix_episode: Set(episode_number),
|
||||||
|
// last_update: Set(Utc::now()),
|
||||||
|
// runtime: Set(episode.runtime.into()),
|
||||||
|
// }
|
||||||
|
// .insert(txn)
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// .await;
|
||||||
|
|
||||||
|
// match result {
|
||||||
|
// Ok(_) => (),
|
||||||
|
// Err(TransactionError::Connection(err)) => Err(err)?,
|
||||||
|
// Err(TransactionError::Transaction(err)) => Err(err)?,
|
||||||
|
// };
|
||||||
|
// println!(
|
||||||
|
// "Created Episode: {} S{}E{}",
|
||||||
|
// flix_id.into_raw(),
|
||||||
|
// season,
|
||||||
|
// episode_number
|
||||||
|
// );
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let flix_id = show.flix_id;
|
||||||
|
// let tmdb_id = show.tmdb_id;
|
||||||
|
|
||||||
|
// fetch_episode(&client, db, flix_id, tmdb_id, id, season_number, episode).await?;
|
||||||
|
// for episode in episodes {
|
||||||
|
// fetch_episode(&client, db, flix_id, tmdb_id, id, season_number, episode).await?;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix-db"
|
name = "flix-db"
|
||||||
version = "0.0.17"
|
version = "0.0.18"
|
||||||
edition.workspace = true
|
license-file.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
description = "Types for storing persistent data about media"
|
description = "Types for storing persistent data about media"
|
||||||
repository = "https://github.com/QuantumShade/flix"
|
repository = "https://github.com/QuantumShade/flix"
|
||||||
license-file.workspace = true
|
|
||||||
categories = []
|
categories = []
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
@@ -15,7 +17,6 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
flix-model = { workspace = true }
|
flix-model = { workspace = true }
|
||||||
flix-tmdb = { workspace = true, features = ["sea-orm"], optional = true }
|
|
||||||
sea-orm = { workspace = true, features = [
|
sea-orm = { workspace = true, features = [
|
||||||
"entity-registry",
|
"entity-registry",
|
||||||
"schema-sync",
|
"schema-sync",
|
||||||
@@ -24,6 +25,8 @@ sea-orm = { workspace = true, features = [
|
|||||||
sea-orm-migration = { workspace = true }
|
sea-orm-migration = { workspace = true }
|
||||||
seamantic = { workspace = true, features = ["sqlite"] }
|
seamantic = { workspace = true, features = ["sqlite"] }
|
||||||
|
|
||||||
|
flix-tmdb = { workspace = true, features = ["sea-orm"], optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
sea-orm-migration = { workspace = true, features = ["runtime-tokio-rustls"] }
|
sea-orm-migration = { workspace = true, features = ["runtime-tokio-rustls"] }
|
||||||
tokio = { version = "^1", default-features = false, features = [
|
tokio = { version = "^1", default-features = false, features = [
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix"
|
name = "flix"
|
||||||
version = "0.0.17"
|
version = "0.0.18"
|
||||||
edition.workspace = true
|
license-file.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
description = "Mechanisms for interacting with flix media"
|
description = "Mechanisms for interacting with flix media"
|
||||||
repository = "https://github.com/QuantumShade/flix"
|
repository = "https://github.com/QuantumShade/flix"
|
||||||
license-file.workspace = true
|
|
||||||
categories = []
|
categories = []
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
flix-db = { workspace = true }
|
flix-db = { workspace = true }
|
||||||
flix-fs = { workspace = true, optional = true }
|
|
||||||
flix-model = { workspace = true }
|
flix-model = { workspace = true }
|
||||||
|
|
||||||
|
flix-fs = { workspace = true, optional = true }
|
||||||
flix-tmdb = { workspace = true, optional = true }
|
flix-tmdb = { workspace = true, optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix-fs"
|
name = "flix-fs"
|
||||||
version = "0.0.17"
|
version = "0.0.18"
|
||||||
edition.workspace = true
|
license-file.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
description = "Filesystem scanner for flix media"
|
description = "Filesystem scanner for flix media"
|
||||||
repository = "https://github.com/QuantumShade/flix"
|
repository = "https://github.com/QuantumShade/flix"
|
||||||
license-file.workspace = true
|
|
||||||
categories = []
|
categories = []
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix-model"
|
name = "flix-model"
|
||||||
version = "0.0.17"
|
version = "0.0.18"
|
||||||
edition.workspace = true
|
license-file.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
description = "Core types for flix data"
|
description = "Core types for flix data"
|
||||||
repository = "https://github.com/QuantumShade/flix"
|
repository = "https://github.com/QuantumShade/flix"
|
||||||
license-file.workspace = true
|
|
||||||
categories = []
|
categories = []
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
@@ -15,9 +17,10 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
seamantic = { workspace = true }
|
seamantic = { workspace = true }
|
||||||
serde = { workspace = true, features = ["derive", "std"], optional = true }
|
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
|
serde = { workspace = true, features = ["derive", "std"], optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
serde = ["dep:serde"]
|
serde = ["dep:serde"]
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flix-tmdb"
|
name = "flix-tmdb"
|
||||||
version = "0.0.17"
|
version = "0.0.18"
|
||||||
edition.workspace = true
|
license-file.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
description = "Clients and models for fetching data from TMDB"
|
description = "Clients and models for fetching data from TMDB"
|
||||||
repository = "https://github.com/QuantumShade/flix"
|
repository = "https://github.com/QuantumShade/flix"
|
||||||
license-file.workspace = true
|
|
||||||
categories = []
|
categories = []
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
@@ -20,13 +22,14 @@ governor = { workspace = true, features = ["jitter", "std"] }
|
|||||||
nonzero_ext = { workspace = true }
|
nonzero_ext = { workspace = true }
|
||||||
redb = { workspace = true }
|
redb = { workspace = true }
|
||||||
reqwest = { workspace = true, features = ["query", "rustls"] }
|
reqwest = { workspace = true, features = ["query", "rustls"] }
|
||||||
sea-orm = { workspace = true, optional = true }
|
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
url-macro = { workspace = true }
|
url-macro = { workspace = true }
|
||||||
|
|
||||||
|
sea-orm = { workspace = true, optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_test = { workspace = true }
|
serde_test = { workspace = true }
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ cargo run -- add tmdb show 1920 # Twin Peaks (1990)
|
|||||||
# Movie Collections #
|
# Movie Collections #
|
||||||
#####################
|
#####################
|
||||||
|
|
||||||
|
# Avatar: The Last Airbender
|
||||||
|
cargo run -- add tmdb collection 1136366 # Avatar: The Last Airbender - Collection
|
||||||
|
cargo run -- add tmdb movie 980431 # Avatar: Aang, The Last Airbender (2026)
|
||||||
|
|
||||||
# Disney Live-Action Remakes
|
# Disney Live-Action Remakes
|
||||||
cargo run -- add flix collection "Disney Live-Action Remakes" "Live-action or photorealistic remakes produced by Walt Disney Pictures of its animated films."
|
cargo run -- add flix collection "Disney Live-Action Remakes" "Live-action or photorealistic remakes produced by Walt Disney Pictures of its animated films."
|
||||||
cargo run -- add tmdb movie 447273 # Snow White (2025)
|
cargo run -- add tmdb movie 447273 # Snow White (2025)
|
||||||
@@ -74,6 +78,16 @@ cargo run -- add tmdb movie 1263256 # Happy Gilmore 2 (2025)
|
|||||||
cargo run -- add tmdb collection 1461530 # The Minecraft Movie Collection
|
cargo run -- add tmdb collection 1461530 # The Minecraft Movie Collection
|
||||||
cargo run -- add tmdb movie 950387 # A Minecraft Movie (2025)
|
cargo run -- add tmdb movie 950387 # A Minecraft Movie (2025)
|
||||||
|
|
||||||
|
# Super Mario
|
||||||
|
cargo run -- add tmdb collection 1434561 # The Super Mario Collection
|
||||||
|
cargo run -- add tmdb movie 502356 # The Super Mario Bros. Movie (2023)
|
||||||
|
cargo run -- add tmdb movie 1226863 # The Super Mario Galaxy Movie (2026)
|
||||||
|
|
||||||
|
# Zootopia
|
||||||
|
cargo run -- add tmdb collection 1084247 # Zootopia Collection
|
||||||
|
cargo run -- add tmdb movie 269149 # Zootopia (2016)
|
||||||
|
cargo run -- add tmdb movie 1084242 # Zootopia 2 (2025)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# Show Collections #
|
# Show Collections #
|
||||||
@@ -106,6 +120,7 @@ cargo run -- add tmdb show 95 # Buffy the Vampire Slayer (1997)
|
|||||||
##########
|
##########
|
||||||
# Movies #
|
# Movies #
|
||||||
##########
|
##########
|
||||||
|
cargo run -- add tmdb movie 286217 # The Martian (2015)
|
||||||
cargo run -- add tmdb movie 940551 # Migration (2023)
|
cargo run -- add tmdb movie 940551 # Migration (2023)
|
||||||
|
|
||||||
|
|
||||||
@@ -115,6 +130,7 @@ cargo run -- add tmdb movie 940551 # Migration (2023)
|
|||||||
cargo run -- add tmdb show 62110 # Assassination Classroom (2015)
|
cargo run -- add tmdb show 62110 # Assassination Classroom (2015)
|
||||||
cargo run -- add tmdb show 1429 # Attack on Titan (2013)
|
cargo run -- add tmdb show 1429 # Attack on Titan (2013)
|
||||||
cargo run -- add tmdb show 42009 # Black Mirror (2011)
|
cargo run -- add tmdb show 42009 # Black Mirror (2011)
|
||||||
|
cargo run -- add tmdb season 42009 0 # Black Mirror Specials
|
||||||
cargo run -- add tmdb show 1911 # Bones (2005)
|
cargo run -- add tmdb show 1911 # Bones (2005)
|
||||||
cargo run -- add tmdb show 48891 # Brooklyn Nine-Nine (2013)
|
cargo run -- add tmdb show 48891 # Brooklyn Nine-Nine (2013)
|
||||||
cargo run -- add flix episode "brooklyn-nine-nine-2013" 8 10 "The Last Day (Part 2)" "The squad takes stock of its eight years together and looks toward the future." "2021-09-16"
|
cargo run -- add flix episode "brooklyn-nine-nine-2013" 8 10 "The Last Day (Part 2)" "The squad takes stock of its eight years together and looks toward the future." "2021-09-16"
|
||||||
@@ -132,6 +148,7 @@ cargo run -- add tmdb show 60846 # Log Horizon (2013)
|
|||||||
cargo run -- add tmdb show 64432 # The Magicians (2015)
|
cargo run -- add tmdb show 64432 # The Magicians (2015)
|
||||||
cargo run -- add tmdb show 5920 # The Mentalist (2008)
|
cargo run -- add tmdb show 5920 # The Mentalist (2008)
|
||||||
cargo run -- add tmdb show 12786 # Murdoch Mysteries (2008)
|
cargo run -- add tmdb show 12786 # Murdoch Mysteries (2008)
|
||||||
|
cargo run -- add tmdb season 12786 0 # Murdoch Mysteries Specials
|
||||||
cargo run -- add tmdb show 65930 # My Hero Academia (2016)
|
cargo run -- add tmdb show 65930 # My Hero Academia (2016)
|
||||||
cargo run -- add tmdb show 2288 # Prison Break (2005)
|
cargo run -- add tmdb show 2288 # Prison Break (2005)
|
||||||
cargo run -- add tmdb show 95396 # Severance (2022)
|
cargo run -- add tmdb show 95396 # Severance (2022)
|
||||||
|
|||||||
Reference in New Issue
Block a user