mirror of
https://github.com/SinTan1729/movie-rename.git
synced 2024-12-25 19:58:36 -06:00
new: Reuse same name for subtitle files and such
This commit is contained in:
parent
4d04f51251
commit
e9314ccdda
2 changed files with 135 additions and 100 deletions
194
src/functions.rs
194
src/functions.rs
|
@ -21,7 +21,9 @@ pub async fn process_file(
|
|||
tmdb: &Client,
|
||||
pattern: &str,
|
||||
dry_run: bool,
|
||||
) -> (String, bool) {
|
||||
movie_list: Option<&HashMap<String, String>>,
|
||||
) -> (String, String, bool) {
|
||||
// The last bool tells whether the entry should be added to the movie_list or not
|
||||
// Set RenderConfig for the menu items
|
||||
inquire::set_global_render_config(get_render_config());
|
||||
|
||||
|
@ -35,6 +37,34 @@ pub async fn process_file(
|
|||
}
|
||||
}
|
||||
|
||||
// Split the filename into parts for a couple of checks and some later use
|
||||
let filename_parts: Vec<&str> = filename.rsplit('.').collect();
|
||||
let filename_without_ext = if filename_parts.len() >= 3 && filename_parts[1].len() == 2 {
|
||||
filename.rsplitn(3, '.').last().unwrap().to_string()
|
||||
} else {
|
||||
filename.rsplit_once('.').unwrap().0.to_string()
|
||||
};
|
||||
|
||||
// Check if the filename (without extension) has already been processed
|
||||
// If yes, we'll use the older results
|
||||
let mut preprocessed = false;
|
||||
let mut new_name_base = match movie_list {
|
||||
None => String::new(),
|
||||
Some(list) => {
|
||||
if list.contains_key(&filename_without_ext) {
|
||||
preprocessed = true;
|
||||
list[&filename_without_ext].clone()
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Check if it should be ignored
|
||||
if preprocessed && new_name_base.is_empty() {
|
||||
return (filename_without_ext, "".to_string(), false);
|
||||
}
|
||||
|
||||
// Parse the filename for metadata
|
||||
let metadata = Metadata::from(file_base.as_str()).expect(" Could not parse filename!");
|
||||
|
||||
|
@ -44,96 +74,98 @@ pub async fn process_file(
|
|||
println!(" Processing {}...", file_base);
|
||||
} else {
|
||||
println!(" Ignoring {}...", file_base);
|
||||
return ("n/a".to_string(), false);
|
||||
return (filename_without_ext, "".to_string(), false);
|
||||
}
|
||||
|
||||
// Search using the TMDb API
|
||||
let year = metadata.year().map(|y| y as u16);
|
||||
let search = MovieSearch::new(metadata.title().to_string()).with_year(year);
|
||||
let reply = search.execute(tmdb).await;
|
||||
// Only do the TMDb API stuff if it's not preprocessed
|
||||
if !preprocessed {
|
||||
// Search using the TMDb API
|
||||
let year = metadata.year().map(|y| y as u16);
|
||||
let search = MovieSearch::new(metadata.title().to_string()).with_year(year);
|
||||
let reply = search.execute(tmdb).await;
|
||||
|
||||
let results = match reply {
|
||||
Ok(res) => Ok(res.results),
|
||||
Err(e) => {
|
||||
eprintln!(" There was an error while searching {}!", file_base);
|
||||
Err(e)
|
||||
}
|
||||
};
|
||||
let results = match reply {
|
||||
Ok(res) => Ok(res.results),
|
||||
Err(e) => {
|
||||
eprintln!(" There was an error while searching {}!", file_base);
|
||||
Err(e)
|
||||
}
|
||||
};
|
||||
|
||||
let mut movie_list: Vec<MovieEntry> = Vec::new();
|
||||
// Create movie entry from the result
|
||||
if results.is_ok() {
|
||||
for result in results.unwrap() {
|
||||
let mut movie_details = MovieEntry::from(result);
|
||||
// Get director's name, if needed
|
||||
if pattern.contains("{director}") {
|
||||
let credits_search = MovieCredits::new(movie_details.id);
|
||||
let credits_reply = credits_search.execute(tmdb).await;
|
||||
if credits_reply.is_ok() {
|
||||
let mut crew = credits_reply.unwrap().crew;
|
||||
// Only keep the director(s)
|
||||
crew.retain(|x| x.job == *"Director");
|
||||
if !crew.is_empty() {
|
||||
let directors: Vec<String> =
|
||||
crew.iter().map(|x| x.person.name.clone()).collect();
|
||||
let mut directors_text = directors.join(", ");
|
||||
if let Some(pos) = directors_text.rfind(',') {
|
||||
directors_text.replace_range(pos..pos + 2, " and ");
|
||||
let mut movie_list: Vec<MovieEntry> = Vec::new();
|
||||
// Create movie entry from the result
|
||||
if results.is_ok() {
|
||||
for result in results.unwrap() {
|
||||
let mut movie_details = MovieEntry::from(result);
|
||||
// Get director's name, if needed
|
||||
if pattern.contains("{director}") {
|
||||
let credits_search = MovieCredits::new(movie_details.id);
|
||||
let credits_reply = credits_search.execute(tmdb).await;
|
||||
if credits_reply.is_ok() {
|
||||
let mut crew = credits_reply.unwrap().crew;
|
||||
// Only keep the director(s)
|
||||
crew.retain(|x| x.job == *"Director");
|
||||
if !crew.is_empty() {
|
||||
let directors: Vec<String> =
|
||||
crew.iter().map(|x| x.person.name.clone()).collect();
|
||||
let mut directors_text = directors.join(", ");
|
||||
if let Some(pos) = directors_text.rfind(',') {
|
||||
directors_text.replace_range(pos..pos + 2, " and ");
|
||||
}
|
||||
movie_details.director = directors_text;
|
||||
}
|
||||
movie_details.director = directors_text;
|
||||
}
|
||||
}
|
||||
}
|
||||
movie_list.push(movie_details);
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing is found, skip
|
||||
if movie_list.is_empty() {
|
||||
eprintln!(" Could not find any entries matching {}!", file_base);
|
||||
return ("".to_string(), true);
|
||||
}
|
||||
|
||||
// Choose from the possible entries
|
||||
let choice = match Select::new(
|
||||
format!(" Possible choices for {}:", file_base).as_str(),
|
||||
movie_list,
|
||||
)
|
||||
.prompt()
|
||||
{
|
||||
Ok(movie) => movie,
|
||||
Err(error) => {
|
||||
println!(" {error}");
|
||||
return ("".to_string(), true);
|
||||
}
|
||||
};
|
||||
|
||||
// Handle the case for subtitle files
|
||||
let mut is_subtitle = false;
|
||||
if ["srt", "ssa"].contains(&extension.as_str()) {
|
||||
// Try to detect if there's already language info in the filename, else ask user to choose
|
||||
let filename_parts: Vec<&str> = filename.rsplit('.').collect();
|
||||
if filename_parts.len() >= 3 && filename_parts[1].len() == 2 {
|
||||
println!(
|
||||
" Keeping language {} as detected in the subtitle file's extension...",
|
||||
get_long_lang(filename_parts[1])
|
||||
);
|
||||
extension = format!("{}.{}", filename_parts[1], extension);
|
||||
} else {
|
||||
let lang_list = Language::generate_list();
|
||||
let lang_choice =
|
||||
Select::new(" Choose the language for the subtitle file:", lang_list)
|
||||
.prompt()
|
||||
.expect(" Invalid choice!");
|
||||
if lang_choice.short != *"none" {
|
||||
extension = format!("{}.{}", lang_choice.short, extension);
|
||||
movie_list.push(movie_details);
|
||||
}
|
||||
}
|
||||
is_subtitle = true;
|
||||
|
||||
// If nothing is found, skip
|
||||
if movie_list.is_empty() {
|
||||
eprintln!(" Could not find any entries matching {}!", file_base);
|
||||
return (filename_without_ext, "".to_string(), true);
|
||||
}
|
||||
|
||||
// Choose from the possible entries
|
||||
let choice = match Select::new(
|
||||
format!(" Possible choices for {}:", file_base).as_str(),
|
||||
movie_list,
|
||||
)
|
||||
.prompt()
|
||||
{
|
||||
Ok(movie) => movie,
|
||||
Err(error) => {
|
||||
println!(" {error}");
|
||||
return (filename_without_ext, "".to_string(), false);
|
||||
}
|
||||
};
|
||||
|
||||
// Handle the case for subtitle files
|
||||
if ["srt", "ssa"].contains(&extension.as_str()) {
|
||||
// Try to detect if there's already language info in the filename, else ask user to choose
|
||||
if filename_parts.len() >= 3 && filename_parts[1].len() == 2 {
|
||||
println!(
|
||||
" Keeping language {} as detected in the subtitle file's extension...",
|
||||
get_long_lang(filename_parts[1])
|
||||
);
|
||||
extension = format!("{}.{}", filename_parts[1], extension);
|
||||
} else {
|
||||
let lang_list = Language::generate_list();
|
||||
let lang_choice =
|
||||
Select::new(" Choose the language for the subtitle file:", lang_list)
|
||||
.prompt()
|
||||
.expect(" Invalid choice!");
|
||||
if lang_choice.short != *"none" {
|
||||
extension = format!("{}.{}", lang_choice.short, extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the new name
|
||||
new_name_base = choice.rename_format(pattern.to_string());
|
||||
}
|
||||
|
||||
// Create the new name
|
||||
let new_name_base = choice.rename_format(pattern.to_string());
|
||||
// Add extension and stuff to the new name
|
||||
let mut new_name_with_ext = new_name_base.clone();
|
||||
if !extension.is_empty() {
|
||||
new_name_with_ext = format!("{}.{}", new_name_with_ext, extension);
|
||||
|
@ -157,7 +189,7 @@ pub async fn process_file(
|
|||
}
|
||||
}
|
||||
}
|
||||
(new_name_base, is_subtitle)
|
||||
(filename_without_ext, new_name_base, true)
|
||||
}
|
||||
|
||||
// Function to process the passed arguments
|
||||
|
|
41
src/main.rs
41
src/main.rs
|
@ -1,5 +1,5 @@
|
|||
use load_file::{self, load_str};
|
||||
use std::{env, fs, path::Path, process::exit};
|
||||
use std::{collections::HashMap, env, fs, path::Path, process::exit};
|
||||
use tmdb_api::Client;
|
||||
|
||||
// Import all the modules
|
||||
|
@ -43,13 +43,12 @@ async fn main() {
|
|||
// Iterate over entries
|
||||
for entry in entries {
|
||||
// Check if the file/directory exists on disk and run necessary commands
|
||||
// TODO: Detect subtitle files with same name/metadata and process them automatically without repeated input
|
||||
match settings["directory"] {
|
||||
// Normal file
|
||||
false => {
|
||||
if Path::new(entry.as_str()).is_file() {
|
||||
// Process the filename for movie entries
|
||||
process_file(&entry, &tmdb, pattern, settings["dry_run"]).await;
|
||||
process_file(&entry, &tmdb, pattern, settings["dry_run"], None).await;
|
||||
} else {
|
||||
eprintln!("The file {} wasn't found on disk, skipping...", entry);
|
||||
continue;
|
||||
|
@ -59,26 +58,28 @@ async fn main() {
|
|||
true => {
|
||||
if Path::new(entry.as_str()).is_dir() {
|
||||
println!("Processing files inside the directory {}...", entry);
|
||||
let mut movie_count = 0;
|
||||
let mut movie_name = String::new();
|
||||
let mut movie_list = HashMap::new();
|
||||
|
||||
if let Ok(files_in_dir) = fs::read_dir(entry.as_str()) {
|
||||
for file in files_in_dir {
|
||||
if file.is_ok() {
|
||||
let (movie_name_temp, is_subtitle) = process_file(
|
||||
&format!("{}", file.unwrap().path().display()),
|
||||
&tmdb,
|
||||
pattern,
|
||||
settings["dry_run"],
|
||||
)
|
||||
.await;
|
||||
let filename = file.unwrap().path().display().to_string();
|
||||
let (filename_without_ext, movie_name_temp, add_to_list) =
|
||||
process_file(
|
||||
&filename,
|
||||
&tmdb,
|
||||
pattern,
|
||||
settings["dry_run"],
|
||||
Some(&movie_list),
|
||||
)
|
||||
.await;
|
||||
|
||||
if movie_name_temp == *"n/a" {
|
||||
continue;
|
||||
}
|
||||
// if movie_name_temp.is_empty() {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if !is_subtitle {
|
||||
movie_count += 1;
|
||||
movie_name = movie_name_temp;
|
||||
if add_to_list {
|
||||
movie_list.insert(filename_without_ext, movie_name_temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,8 +87,10 @@ async fn main() {
|
|||
eprintln!("There was an error accessing the directory {}!", entry);
|
||||
continue;
|
||||
}
|
||||
if movie_count == 1 {
|
||||
if movie_list.len() == 1 {
|
||||
let entry_clean = entry.trim_end_matches('/');
|
||||
let movie_name = movie_list.into_values().next().unwrap();
|
||||
|
||||
if entry_clean == movie_name {
|
||||
println!("[directory] '{}' already has correct name.", entry_clean);
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue