aboutsummaryrefslogtreecommitdiff
path: root/tool
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-02-02 16:02:42 +0100
committermetamuffin <metamuffin@disroot.org>2025-02-02 16:02:42 +0100
commit4d3ec68b9cbac493ee76981527cb0e780fac9432 (patch)
tree3f0df02f4c1a119e70663e0e3b4a485d81bc92b3 /tool
parent64c962b50d4fbd4605087fc97eac1a032bb826ce (diff)
downloadjellything-4d3ec68b9cbac493ee76981527cb0e780fac9432.tar
jellything-4d3ec68b9cbac493ee76981527cb0e780fac9432.tar.bz2
jellything-4d3ec68b9cbac493ee76981527cb0e780fac9432.tar.zst
trakt metadata source
Diffstat (limited to 'tool')
-rw-r--r--tool/src/add.rs224
-rw-r--r--tool/src/bin/generate_completions.rs5
-rw-r--r--tool/src/cli.rs16
3 files changed, 84 insertions, 161 deletions
diff --git a/tool/src/add.rs b/tool/src/add.rs
index fdaa14e..6e79381 100644
--- a/tool/src/add.rs
+++ b/tool/src/add.rs
@@ -1,7 +1,12 @@
+/*
+ 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) 2025 metamuffin <metamuffin.org>
+*/
use crate::cli::Action;
-use anyhow::{anyhow, bail, Context};
-use dialoguer::{theme::ColorfulTheme, FuzzySelect, Input, MultiSelect};
-use jellybase::{CONF, SECRETS};
+use anyhow::anyhow;
+use dialoguer::{theme::ColorfulTheme, Confirm, FuzzySelect, Input};
+use jellybase::SECRETS;
use jellycommon::TraktKind;
use jellyimport::trakt::Trakt;
use log::warn;
@@ -9,76 +14,35 @@ use std::{
fmt::Display,
path::{Path, PathBuf},
};
+use tokio::fs::rename;
pub async fn add(action: Action) -> anyhow::Result<()> {
match action {
- Action::Add {
- id,
- media,
- library_path,
- } => {
+ Action::Add { media } => {
let theme = ColorfulTheme::default();
- let possible_kinds = [
- TraktKind::Movie,
- TraktKind::Season,
- TraktKind::Show,
- TraktKind::Episode,
- ];
- let trakt_kind: Vec<usize> = MultiSelect::with_theme(&theme)
- .with_prompt("Media Kind")
- .items(&possible_kinds)
- .defaults(&[true, false, false, false])
- .interact()
- .unwrap();
- let search_kinds = trakt_kind
- .iter()
- .map(|&i| possible_kinds[i])
- .collect::<Vec<_>>();
-
- let library_path = if let Some(library_path) = library_path {
- library_path
- } else {
- let mut directories = Vec::new();
- find_folders(&CONF.media_path, &PathBuf::new(), &mut directories)
- .context("listing library directories")?;
-
- let mut default = 0;
- for k in possible_kinds {
- match k {
- TraktKind::Movie => {
- if let Some(i) = directories
- .iter()
- .position(|d| d.0.to_str().unwrap().contains("movies"))
- {
- default = i
- };
- }
- TraktKind::Show => {
- if let Some(i) = directories
- .iter()
- .position(|d| d.0.to_str().unwrap().contains("shows"))
- {
- default = i
- };
- }
- _ => (),
- }
- }
-
- let target_dir_index = FuzzySelect::with_theme(&theme)
- .items(&directories)
- .default(default)
- .with_prompt("Library Path")
- .interact()
- .unwrap();
- directories[target_dir_index].0.clone()
- };
+ // let possible_kinds = [
+ // TraktKind::Movie,
+ // TraktKind::Season,
+ // TraktKind::Show,
+ // TraktKind::Episode,
+ // ];
+ // let trakt_kind: Vec<usize> = MultiSelect::with_theme(&theme)
+ // .with_prompt("Media Kind")
+ // .items(&possible_kinds)
+ // .defaults(&[true, false, false, false])
+ // .interact()
+ // .unwrap();
+ // let search_kinds = trakt_kind
+ // .iter()
+ // .map(|&i| possible_kinds[i])
+ // .collect::<Vec<_>>();
+ let search_kinds = [TraktKind::Show, TraktKind::Season, TraktKind::Movie];
- let (last_search, trakt_object, trakt_kind) = loop {
+ let (trakt_object, trakt_kind) = loop {
let name: String = Input::with_theme(&theme)
.with_prompt("Search by title")
- .default(media.as_ref().map(|p| path_to_query(p)).unwrap_or_default())
+ .default(path_to_query(&media))
.interact_text()
.unwrap();
@@ -105,60 +69,32 @@ pub async fn add(action: Action) -> anyhow::Result<()> {
.unwrap();
if let Some(o) = correct {
- break (name, results[o].inner.inner().to_owned(), results[o].r#type);
+ break (results[o].inner.inner().to_owned(), results[o].r#type);
}
};
- let id = id.unwrap_or_else(|| {
- trakt_object.ids.slug.unwrap_or_else(|| {
- let o: String = Input::with_theme(&theme)
- .with_prompt("Node ID")
- .validate_with(validate_id)
- .default(make_id(&last_search))
- .interact_text()
- .unwrap();
- o
- })
- });
-
- // TODO
- let _ = id;
- let _ = library_path;
- let _ = trakt_kind;
-
- // let mut sources = Vec::new();
- // sources.push(ImportSource::Trakt {
- // id: trakt_object.ids.trakt.unwrap(),
- // kind: trakt_kind,
- // });
- // if let Some(media) = media {
- // sources.push(ImportSource::Media {
- // path: media,
- // ignore_metadata: true,
- // ignore_attachments: false,
- // ignore_chapters: false,
- // })
- // }
-
- // let impo = ImportOptions { id, sources };
+ assert_eq!(trakt_kind, TraktKind::Movie);
- // let ypath = CONF
- // .library_path
- // .join(library_path)
- // .join(&impo.id)
- // .with_extension("yaml");
+ let stem = media.file_name().unwrap().to_string_lossy().to_string();
+ let stem = stem.split_once(".").unwrap_or((stem.as_str(), "")).0;
+ let mut newpath = media.parent().unwrap().join(format!(
+ "{stem}.trakt-{}.mkv",
+ trakt_object.ids.trakt.unwrap()
+ ));
+ let mut n = 1;
+ while newpath.exists() {
+ newpath = media.parent().unwrap().join(format!("{stem}.alt-{n}.mkv",));
+ n += 1;
+ }
- // if Confirm::with_theme(&theme)
- // .with_prompt(format!("Write {:?}?", ypath))
- // .default(true)
- // .interact()
- // .unwrap()
- // {
- // File::create(ypath)
- // .await?
- // .write_all(serde_yaml::to_string(&impo)?.as_bytes())
- // .await?;
- // }
+ if Confirm::with_theme(&theme)
+ .with_prompt(format!("Rename {media:?} -> {newpath:?}?"))
+ .default(true)
+ .interact()
+ .unwrap()
+ {
+ rename(media, newpath).await?;
+ }
Ok(())
}
@@ -166,46 +102,30 @@ pub async fn add(action: Action) -> anyhow::Result<()> {
}
}
-fn validate_id(s: &String) -> anyhow::Result<()> {
- if &make_id(s) == s {
- Ok(())
- } else {
- bail!("invalid id")
- }
-}
-fn make_id(s: &str) -> String {
- let mut out = String::new();
- for s in s.chars() {
- match s {
- 'a'..='z' | '0'..='9' => out.push(s),
- 'A'..='Z' => out.push(s.to_ascii_lowercase()),
- '-' | ' ' | '_' | ':' => out.push('-'),
- _ => (),
- }
- }
- out
-}
+// fn validate_id(s: &String) -> anyhow::Result<()> {
+// if &make_id(s) == s {
+// Ok(())
+// } else {
+// bail!("invalid id")
+// }
+// }
+// fn make_id(s: &str) -> String {
+// let mut out = String::new();
+// for s in s.chars() {
+// match s {
+// 'a'..='z' | '0'..='9' => out.push(s),
+// 'A'..='Z' => out.push(s.to_ascii_lowercase()),
+// '-' | ' ' | '_' | ':' => out.push('-'),
+// _ => (),
+// }
+// }
+// out
+// }
fn path_to_query(path: &Path) -> String {
- path.file_stem()
- .unwrap()
- .to_str()
- .unwrap()
- .to_string()
- .replace("-", " ")
- .replace(".", " ")
-}
-
-fn find_folders(base: &Path, path: &Path, out: &mut Vec<PathDisplay>) -> anyhow::Result<()> {
- out.push(PathDisplay(path.to_owned()));
- for entry in base.join(path).read_dir()? {
- let entry = entry?;
- let child_path = path.join(entry.file_name());
- if entry.path().is_dir() {
- find_folders(base, &child_path, out)?;
- }
- }
- Ok(())
+ let stem = path.file_name().unwrap().to_string_lossy().to_string();
+ let stem = stem.split_once(".").unwrap_or((stem.as_str(), "")).0;
+ stem.replace("-", " ")
}
pub struct PathDisplay(PathBuf);
diff --git a/tool/src/bin/generate_completions.rs b/tool/src/bin/generate_completions.rs
index 9f0917f..1afce29 100644
--- a/tool/src/bin/generate_completions.rs
+++ b/tool/src/bin/generate_completions.rs
@@ -1,3 +1,8 @@
+/*
+ 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) 2025 metamuffin <metamuffin.org>
+*/
use clap::{CommandFactory, Parser, ValueEnum};
use clap_complete::{generate_to, Shell};
use jellytool::cli;
diff --git a/tool/src/cli.rs b/tool/src/cli.rs
index 2e12c81..b51b135 100644
--- a/tool/src/cli.rs
+++ b/tool/src/cli.rs
@@ -1,3 +1,8 @@
+/*
+ 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) 2025 metamuffin <metamuffin.org>
+*/
use clap::{arg, Parser, ValueEnum};
use std::path::PathBuf;
@@ -7,17 +12,10 @@ pub type Args = Action;
#[clap(version, about)]
/// Tool for administering a Jellything instance
pub enum Action {
- /// Interactive wizard for adding new nodes
+ /// Interactive wizard for renaming files
Add {
- /// ID of the new node; inferred if not specified
- #[arg(short, long)]
- id: Option<String>,
/// Path to the media of this node.
- #[arg(short, long)]
- media: Option<PathBuf>,
- /// Path of the new node within the library
- #[arg(short, long)]
- library_path: Option<PathBuf>,
+ media: PathBuf,
},
/// Migrate the database by export or import to JSON
Migrate {