aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-08-03 20:45:31 +0200
committermetamuffin <metamuffin@disroot.org>2023-08-03 20:45:31 +0200
commitd52233a7a304b7dadda383128eaa42aea02b3b74 (patch)
tree254ab9e7ca527b16afaa6fa1a7ad76fef220f9f6 /tools
parent5b71ccaf2bbe34f1d39d4f38f2b5c2090a9761b1 (diff)
downloadjellything-d52233a7a304b7dadda383128eaa42aea02b3b74.tar
jellything-d52233a7a304b7dadda383128eaa42aea02b3b74.tar.bz2
jellything-d52233a7a304b7dadda383128eaa42aea02b3b74.tar.zst
rename tools crate
Diffstat (limited to 'tools')
-rw-r--r--tools/Cargo.toml23
-rw-r--r--tools/src/bin/import.rs322
-rw-r--r--tools/src/lib.rs6
-rw-r--r--tools/src/tmdb.rs95
4 files changed, 0 insertions, 446 deletions
diff --git a/tools/Cargo.toml b/tools/Cargo.toml
deleted file mode 100644
index 63cb8b6..0000000
--- a/tools/Cargo.toml
+++ /dev/null
@@ -1,23 +0,0 @@
-[package]
-name = "jellytools"
-version = "0.1.0"
-edition = "2021"
-
-[dependencies]
-jellycommon = { path = "../common" }
-jellymatroska = { path = "../matroska" }
-jellyremuxer = { path = "../remuxer" }
-
-log = "0.4.19"
-env_logger = "0.10.0"
-anyhow = "1.0.72"
-clap = { version = "4.3.19", features = ["derive"] }
-reqwest = { version = "0.11.18", features = ["blocking", "json"] }
-
-serde = { version = "1.0.180", features = ["derive"] }
-serde_json = "1.0.104"
-bincode = { version = "2.0.0-rc.3", features = ["serde"] }
-
-[[bin]]
-path = "src/bin/import.rs"
-name = "jellything-import"
diff --git a/tools/src/bin/import.rs b/tools/src/bin/import.rs
deleted file mode 100644
index eada6ad..0000000
--- a/tools/src/bin/import.rs
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- This file is part of jellything (https://codeberg.org/metamuffin/jellything)
- which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
- Copyright (C) 2023 metamuffin <metamuffin.org>
-*/
-use anyhow::Context;
-use clap::{Parser, Subcommand};
-use jellycommon::{AssetLocation, MediaInfo, MediaSource, Node, NodeKind, NodePrivate, NodePublic};
-use jellymatroska::read::EbmlReader;
-use jellyremuxer::import::{import_metadata, seek_index::import_seek_index};
-use jellytools::tmdb::{tmdb_details, tmdb_image, tmdb_search};
-use log::info;
-use std::{
- collections::BTreeMap,
- fs::{remove_file, File},
- io::stdin,
- path::PathBuf,
- process::exit,
-};
-
-#[derive(Parser)]
-struct Args {
- #[arg(short = 'N', long)]
- dry: bool,
- #[clap(subcommand)]
- action: Action,
-}
-
-#[derive(Subcommand)]
-enum Action {
- Create {
- path: PathBuf,
- #[arg(short = 't', long)]
- tmdb_search: Option<String>,
- #[arg(short = 'T', long)]
- tmdb_id: Option<String>,
- #[arg(long)]
- copy: bool,
- #[arg(long)]
- r#move: bool,
- #[arg(short, long)]
- input: Option<PathBuf>,
- #[arg(short, long)]
- series: bool,
- },
- Set {
- #[arg(short = 'I', long)]
- item: PathBuf,
- #[arg(short, long)]
- poster: Option<PathBuf>,
- #[arg(short, long)]
- title: Option<String>,
- #[arg(short = 'D', long)]
- tagline: Option<String>,
- #[arg(short = 'd', long)]
- description: Option<String>,
- #[arg(short = 'c', long)]
- clear_inputs: bool,
- #[arg(short = 'i', long, num_args(0..))]
- input: Vec<PathBuf>,
- },
-}
-
-fn main() -> anyhow::Result<()> {
- env_logger::builder()
- .filter_level(log::LevelFilter::Info)
- .parse_env("LOG")
- .init();
- let args = Args::parse();
-
- match args.action {
- Action::Create {
- path,
- tmdb_id,
- tmdb_search,
- input,
- series,
- copy,
- r#move,
- } => {
- let tmdb_kind = if series { "tv" } else { "movie" };
- let tmdb_key = std::env::var("TMDB_API_KEY").context("tmdb api key required")?;
- let tmdb_id = if let Some(id) = tmdb_id {
- Some(id.parse().unwrap())
- } else {
- let title = tmdb_search.as_ref().unwrap();
- let results = crate::tmdb_search(tmdb_kind, title, &tmdb_key)?;
- info!("results:");
- for (i, r) in results.results.iter().enumerate() {
- info!(
- "\t[{i}] {}: {} ({})",
- r.id,
- r.title.as_ref().or(r.name.as_ref()).unwrap(),
- r.overview.chars().take(100).collect::<String>()
- );
- }
- let res_index = if results.results.len() > 1 {
- stdin()
- .lines()
- .next()
- .unwrap()
- .unwrap()
- .parse::<usize>()
- .unwrap()
- } else {
- 0
- };
- Some(results.results[res_index].id)
- };
-
- let tmdb_details = tmdb_id.map(|id| {
- let td = tmdb_details(tmdb_kind, id, &tmdb_key)
- .context("fetching details")
- .unwrap();
- if td.title.is_some() {
- info!("is this correct? [y/n]");
- if stdin().lines().next().unwrap().unwrap() != "y" {
- exit(0)
- }
- }
- td
- });
-
- let title = tmdb_details
- .as_ref()
- .map(|d| d.title.clone().or(d.name.clone()))
- .flatten()
- .unwrap();
- let ident = make_ident(&title);
- let path = path.join(&ident);
-
- let poster = tmdb_details
- .as_ref()
- .map(|d| {
- d.poster_path
- .as_ref()
- .map(|p| {
- let pu = path.join("poster.jpeg");
- let mut f = File::create(&pu)?;
- tmdb_image(&p, &mut f)?;
- Ok::<_, anyhow::Error>(pu)
- })
- .transpose()
- })
- .transpose()?
- .flatten();
-
- let backdrop = tmdb_details
- .as_ref()
- .map(|d| {
- d.backdrop_path
- .as_ref()
- .map(|p| {
- let pu = path.join("backdrop.jpeg");
- let mut f = File::create(&pu)?;
- tmdb_image(&p, &mut f)?;
- Ok::<_, anyhow::Error>(pu)
- })
- .transpose()
- })
- .transpose()?
- .flatten();
-
- let kind;
- let media;
- let source;
- let mut seek_index = BTreeMap::new();
- let mut source_path_e = None;
-
- if let Some(input) = input {
- let source_path = path.join(format!("source.mkv"));
- if r#move {
- std::fs::rename(&input, &source_path)?;
- } else if copy {
- std::fs::copy(&input, &source_path)?;
- } else {
- if source_path.is_symlink() {
- remove_file(&source_path)?;
- }
- std::os::unix::fs::symlink(&input, &source_path)?;
- }
-
- let (tracks, local_tracks, duration) = {
- let input = File::open(&source_path).unwrap();
- let mut input = EbmlReader::new(input);
- import_metadata(&source_path.to_path_buf(), &mut input)?
- };
- seek_index = {
- let input = File::open(&source_path).unwrap();
- let mut input = EbmlReader::new(input);
- import_seek_index(&mut input)?
- };
-
- kind = NodeKind::Movie;
- media = Some(MediaInfo { duration, tracks });
- source = Some(MediaSource::Local {
- tracks: local_tracks,
- });
- source_path_e = Some(source_path)
- } else {
- kind = NodeKind::Series;
- media = None;
- source = None;
- };
-
- let node = Node {
- private: NodePrivate {
- import: None,
- backdrop: backdrop.clone().map(AssetLocation::Library),
- poster: poster.clone().map(AssetLocation::Library),
- source,
- },
- public: NodePublic {
- parent: None,
- federated: None,
- description: tmdb_details.as_ref().map(|d| d.overview.to_owned()),
- tagline: tmdb_details
- .as_ref()
- .map(|d| d.tagline.to_owned())
- .flatten(),
- title,
- index: None,
- kind,
- children: Vec::new(),
- media,
- },
- };
-
- if args.dry {
- println!("{node:?}")
- } else {
- std::fs::create_dir_all(&path)?;
- for (tn, index) in seek_index {
- info!("writing index {tn} with {} blocks", index.blocks.len());
- bincode::encode_into_std_write(
- index,
- &mut File::create(
- source_path_e
- .as_ref()
- .unwrap()
- .with_extension(&format!("si.{tn}")),
- )?,
- bincode::config::standard(),
- )?;
- }
- let f = File::create(path.join(if series {
- "directory.json".to_string()
- } else {
- format!("{ident}.jelly")
- }))?;
- serde_json::to_writer_pretty(f, &node)?;
- }
-
- Ok(())
- }
- Action::Set { .. } => {
- // let mut iteminfo: ItemInfo = match File::open(item.clone()) {
- // Ok(f) => serde_json::from_reader(f)?,
- // Err(e) => {
- // warn!("could not load item info: {e}");
- // warn!("using the default instead");
- // ItemInfo {
- // common: CommmonInfo {
- // poster: None,
- // backdrop: None,
- // tagline: None,
- // description: None,
- // title: item.to_str().unwrap().to_string(),
- // index: None,
- // },
- // duration: 0.0,
- // tracks: Default::default(),
- // }
- // }
- // };
-
- // if let Some(title) = title {
- // iteminfo.title = title;
- // }
- // if let Some(poster) = poster {
- // iteminfo.poster = Some(poster);
- // }
- // if let Some(d) = description {
- // iteminfo.description = Some(d);
- // }
- // if let Some(d) = tagline {
- // iteminfo.tagline = Some(d);
- // }
- // if clear_inputs {
- // iteminfo.tracks = Default::default()
- // }
-
- // // for input_path in input {
- // // let input = File::open(input_path.clone()).unwrap();
- // // let mut input = EbmlReader::new(input);
- // // import_read(&input_path, &mut input, &mut iteminfo)?;
- // // }
-
- // let k = serde_json::to_string_pretty(&iteminfo)?;
- // if args.dry {
- // println!("{k}")
- // } else {
- // let mut f = File::create(item)?;
- // f.write_all(k.as_bytes())?;
- // }
- Ok(())
- }
- }
-}
-
-fn make_ident(s: &str) -> String {
- let mut out = String::new();
- for s in s.chars() {
- match s {
- 'a'..='z' => out.push(s),
- 'A'..='Z' => out.push(s.to_ascii_lowercase()),
- '-' | ' ' | '_' => out.push('-'),
- _ => (),
- }
- }
- out
-}
diff --git a/tools/src/lib.rs b/tools/src/lib.rs
deleted file mode 100644
index c5dca31..0000000
--- a/tools/src/lib.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- This file is part of jellything (https://codeberg.org/metamuffin/jellything)
- which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
- Copyright (C) 2023 metamuffin <metamuffin.org>
-*/
-pub mod tmdb;
diff --git a/tools/src/tmdb.rs b/tools/src/tmdb.rs
deleted file mode 100644
index 5f21afd..0000000
--- a/tools/src/tmdb.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- This file is part of jellything (https://codeberg.org/metamuffin/jellything)
- which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
- Copyright (C) 2023 metamuffin <metamuffin.org>
-*/
-use log::info;
-use serde::Deserialize;
-use std::io::Write;
-
-#[derive(Debug, Clone, Deserialize)]
-pub struct TmdbQuery {
- pub page: usize,
- pub results: Vec<TmdbQueryResult>,
- pub total_pages: usize,
- pub total_results: usize,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-pub struct TmdbQueryResult {
- pub adult: bool,
- pub backdrop_path: Option<String>,
- pub genre_ids: Vec<u64>,
- pub id: u64,
- pub original_language: Option<String>,
- pub original_title: Option<String>,
- pub overview: String,
- pub popularity: f64,
- pub poster_path: Option<String>,
- pub release_date: Option<String>,
- pub title: Option<String>,
- pub name: Option<String>,
- pub vote_average: f64,
- pub vote_count: usize,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-pub struct TmdbDetails {
- pub adult: bool,
- pub backdrop_path: Option<String>,
- pub genres: Vec<TmdbGenre>,
- pub id: u64,
- pub original_language: Option<String>,
- pub original_title: Option<String>,
- pub overview: String,
- pub popularity: f64,
- pub poster_path: Option<String>,
- pub release_date: Option<String>,
- pub title: Option<String>,
- pub name: Option<String>,
- pub vote_average: f64,
- pub vote_count: usize,
- pub budget: Option<usize>,
- pub homepage: Option<String>,
- pub imdb_id: Option<String>,
- pub production_companies: Vec<TmdbProductionCompany>,
- pub revenue: Option<usize>,
- pub tagline: Option<String>,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-pub struct TmdbGenre {
- pub id: u64,
- pub name: String,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-pub struct TmdbProductionCompany {
- pub id: u64,
- pub name: String,
- pub logo_path: Option<String>,
-}
-
-pub fn tmdb_search(kind: &str, query: &str, key: &str) -> anyhow::Result<TmdbQuery> {
- info!("searching tmdb: {query:?}");
- Ok(reqwest::blocking::get(&format!(
- "https://api.themoviedb.org/3/search/{kind}?query={}&api_key={key}",
- query.replace(" ", "+")
- ))?
- .json::<TmdbQuery>()?)
-}
-
-pub fn tmdb_details(kind: &str, id: u64, key: &str) -> anyhow::Result<TmdbDetails> {
- info!("fetching details: {id:?}");
- Ok(reqwest::blocking::get(&format!(
- "https://api.themoviedb.org/3/{kind}/{id}?api_key={key}"
- ))?
- .json()?)
-}
-
-pub fn tmdb_image(path: &str, out: &mut impl Write) -> anyhow::Result<()> {
- info!("downloading image {path:?}");
- let mut res = reqwest::blocking::get(&format!("https://image.tmdb.org/t/p/original{path}"))?;
- res.copy_to(out)?;
- Ok(())
-}