use std::env;
use std::ffi::OsStr;
use std::fs;
use std::path::{Path, PathBuf};
use backend::traits::{Digits};
use tvdb;
#[derive(Clone, Debug)]
pub struct Arguments {
pub automatic: bool,
pub dry_run: bool,
pub log_changes: bool,
pub no_name: bool,
pub tvdb: bool,
pub verbose: bool,
pub directory: String,
pub series_name: String,
pub season_number: usize,
pub episode_count: usize,
pub pad_length: usize,
}
impl Arguments {
pub fn get_targets(&self, directory: &str, episodes: &[PathBuf], episode_index: usize) -> Result<Vec<PathBuf>, String> {
let api = tvdb::Tvdb::new("0629B785CE550C8D");
let series_info = if self.tvdb {
match api.search(self.series_name.as_str(), "en") {
Ok(reply) => Some(reply),
Err(_) => { return Err(String::from("unable to get TVDB series information")); }
}
} else {
None
};
let mut output: Vec<PathBuf> = Vec::new();
let mut current_index = episode_index;
for file in episodes {
let tvdb_title = if self.tvdb {
let reply = series_info.clone().unwrap();
match api.episode(&reply[0], self.season_number as u32, current_index as u32) {
Ok(episode) => episode.episode_name,
Err(_) => { return Err(format!("media-rename: episode '{}' does not exist", file.to_string_lossy())); }
}
} else {
String::new()
};
let new_destination = self.get_destination(Path::new(directory), &file, current_index, &tvdb_title);
output.push(new_destination);
current_index += 1;
}
Ok(output)
}
pub fn get_destination(&self, directory: &Path, file: &Path, episode: usize, title: &str) -> PathBuf {
let mut destination = PathBuf::from(&directory);
let extension = file.extension().unwrap_or(&OsStr::new("")).to_str().unwrap_or("");
let mut filename = if self.no_name {
String::new()
} else {
let mut filename = self.series_name.clone();
filename.push(' ');
filename
};
filename.push_str(&self.season_number.to_string());
filename.push('x');
filename.push_str(episode.to_padded_string('0', self.pad_length).as_str());
if self.tvdb {
filename.push(' ');
filename.push_str(title);
}
if !extension.is_empty() { filename.push('.'); }
filename.push_str(extension);
destination.push(filename);
destination
}
}
pub fn shorten_path(path: &Path) -> PathBuf {
match path.strip_prefix(&env::current_dir().unwrap()) {
Ok(value) => {
let mut path = PathBuf::from(".");
path.push(value);
path
},
Err(_) => match path.strip_prefix(&env::home_dir().unwrap()) {
Ok(value) => {
let mut path = PathBuf::from("~");
path.push(value);
path
},
Err(_) => path.to_path_buf()
},
}
}
pub fn derive_season_number(season: &Path) -> Option<usize> {
let mut directory_name = season.file_name().unwrap().to_str().unwrap().to_lowercase();
match directory_name.as_str() {
"season0" | "season 0" | "specials" => Some(0),
_ => {
directory_name = directory_name.replace("season", "");
directory_name = directory_name.replace(" ", "");
if let Ok(season_number) = directory_name.parse::<usize>() {
Some(season_number)
} else {
None
}
}
}
}
pub fn get_seasons(directory: &str) -> Result<Vec<PathBuf>, &str> {
if let Ok(files) = fs::read_dir(directory) {
let mut seasons = Vec::new();
for entry in files {
if let Ok(entry) = entry {
if let Ok(metadata) = entry.metadata() {
if metadata.is_dir() {
seasons.push(entry.path());
}
} else {
return Err("unable to get metadata");
}
} else {
return Err("unable to get directory entry");
}
}
seasons.sort_by(|a, b| a.to_string_lossy().cmp(&b.to_string_lossy()));
Ok(seasons)
} else {
Err("unable to read directory")
}
}
pub fn get_episodes(directory: &str) -> Result<Vec<PathBuf>, &str> {
if let Ok(files) = fs::read_dir(directory) {
let mut episodes = Vec::new();
for entry in files {
if let Ok(entry) = entry {
if let Ok(metadata) = entry.metadata() {
if metadata.is_file() { episodes.push(entry.path()); }
} else {
return Err("unable to get metadata");
}
} else {
return Err("unable to get file entry");
}
}
episodes.sort_by(|a, b| a.to_string_lossy().cmp(&b.to_string_lossy()));
Ok(episodes)
} else {
Err("unable to read file")
}
}