|
|
|
@ -22,7 +22,6 @@ import java.util.ArrayList;
|
|
|
|
|
import java.util.Collection;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.LinkedHashMap;
|
|
|
|
|
import java.util.LinkedHashSet;
|
|
|
|
|
import java.util.List;
|
|
|
|
@ -80,11 +79,12 @@ import net.sourceforge.tuned.FileUtilities.FolderFilter;
|
|
|
|
|
public class CmdlineOperations implements CmdlineInterface {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<File> rename(Collection<File> files, String action, String output, String expression, String db, String query, String sortOrder, String lang, boolean strict) throws Exception {
|
|
|
|
|
public List<File> rename(Collection<File> files, String action, String conflict, String output, String expression, String db, String query, String sortOrder, String lang, boolean strict) throws Exception {
|
|
|
|
|
ExpressionFormat format = (expression != null) ? new ExpressionFormat(expression) : null;
|
|
|
|
|
File outputDir = (output != null && output.length() > 0) ? new File(output) : null;
|
|
|
|
|
Locale locale = getLanguage(lang).toLocale();
|
|
|
|
|
RenameAction renameAction = StandardRenameAction.forName(action);
|
|
|
|
|
ConflictAction conflictAction = ConflictAction.forName(conflict);
|
|
|
|
|
|
|
|
|
|
List<File> mediaFiles = filter(files, VIDEO_FILES, SUBTITLE_FILES);
|
|
|
|
|
if (mediaFiles.isEmpty()) {
|
|
|
|
@ -93,12 +93,12 @@ public class CmdlineOperations implements CmdlineInterface {
|
|
|
|
|
|
|
|
|
|
if (getEpisodeListProvider(db) != null) {
|
|
|
|
|
// tv series mode
|
|
|
|
|
return renameSeries(files, renameAction, outputDir, format, getEpisodeListProvider(db), query, SortOrder.forName(sortOrder), locale, strict);
|
|
|
|
|
return renameSeries(files, renameAction, conflictAction, outputDir, format, getEpisodeListProvider(db), query, SortOrder.forName(sortOrder), locale, strict);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (getMovieIdentificationService(db) != null) {
|
|
|
|
|
// movie mode
|
|
|
|
|
return renameMovie(files, renameAction, outputDir, format, getMovieIdentificationService(db), query, locale, strict);
|
|
|
|
|
return renameMovie(files, renameAction, conflictAction, outputDir, format, getMovieIdentificationService(db), query, locale, strict);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// auto-determine mode
|
|
|
|
@ -129,14 +129,15 @@ public class CmdlineOperations implements CmdlineInterface {
|
|
|
|
|
|
|
|
|
|
CLILogger.finest(format("Filename pattern: [%.02f] SxE, [%.02f] CWS", sxe / max, cws / max));
|
|
|
|
|
if (sxe >= (max * 0.65) || cws >= (max * 0.65)) {
|
|
|
|
|
return renameSeries(files, renameAction, outputDir, format, getEpisodeListProviders()[0], query, SortOrder.forName(sortOrder), locale, strict); // use default episode db
|
|
|
|
|
return renameSeries(files, renameAction, conflictAction, outputDir, format, WebServices.TVRage, query, SortOrder.forName(sortOrder), locale, strict); // use default episode db
|
|
|
|
|
} else {
|
|
|
|
|
return renameMovie(files, renameAction, outputDir, format, getMovieIdentificationServices()[0], query, locale, strict); // use default movie db
|
|
|
|
|
return renameMovie(files, renameAction, conflictAction, outputDir, format, WebServices.OpenSubtitles, query, locale, strict); // use default movie db
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public List<File> renameSeries(Collection<File> files, RenameAction renameAction, File outputDir, ExpressionFormat format, EpisodeListProvider db, String query, SortOrder sortOrder, Locale locale, boolean strict) throws Exception {
|
|
|
|
|
public List<File> renameSeries(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFormat format, EpisodeListProvider db, String query, SortOrder sortOrder, Locale locale,
|
|
|
|
|
boolean strict) throws Exception {
|
|
|
|
|
CLILogger.config(format("Rename episodes using [%s]", db.getName()));
|
|
|
|
|
List<File> mediaFiles = filter(files, VIDEO_FILES, SUBTITLE_FILES);
|
|
|
|
|
|
|
|
|
@ -199,7 +200,7 @@ public class CmdlineOperations implements CmdlineInterface {
|
|
|
|
|
|
|
|
|
|
// rename episodes
|
|
|
|
|
Analytics.trackEvent("CLI", "Rename", "Episode", renameMap.size());
|
|
|
|
|
return renameAll(renameMap, renameAction);
|
|
|
|
|
return renameAll(renameMap, renameAction, conflictAction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -272,7 +273,8 @@ public class CmdlineOperations implements CmdlineInterface {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public List<File> renameMovie(Collection<File> files, RenameAction renameAction, File outputDir, ExpressionFormat format, MovieIdentificationService service, String query, Locale locale, boolean strict) throws Exception {
|
|
|
|
|
public List<File> renameMovie(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFormat format, MovieIdentificationService service, String query, Locale locale, boolean strict)
|
|
|
|
|
throws Exception {
|
|
|
|
|
CLILogger.config(format("Rename movies using [%s]", service.getName()));
|
|
|
|
|
|
|
|
|
|
// handle movie files
|
|
|
|
@ -422,17 +424,19 @@ public class CmdlineOperations implements CmdlineInterface {
|
|
|
|
|
|
|
|
|
|
// rename movies
|
|
|
|
|
Analytics.trackEvent("CLI", "Rename", "Movie", renameMap.size());
|
|
|
|
|
return renameAll(renameMap, renameAction);
|
|
|
|
|
return renameAll(renameMap, renameAction, conflictAction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public List<File> renameAll(Map<File, File> renameMap, RenameAction renameAction) throws Exception {
|
|
|
|
|
// perform some sanity checks
|
|
|
|
|
Set<File> destinationSet = new HashSet<File>();
|
|
|
|
|
public List<File> renameAll(Map<File, File> renameMap, RenameAction renameAction, ConflictAction conflictAction) throws Exception {
|
|
|
|
|
// rename files
|
|
|
|
|
final List<Entry<File, File>> renameLog = new ArrayList<Entry<File, File>>();
|
|
|
|
|
|
|
|
|
|
for (Entry<File, File> mapping : renameMap.entrySet()) {
|
|
|
|
|
File source = mapping.getKey();
|
|
|
|
|
File destination = mapping.getValue();
|
|
|
|
|
try {
|
|
|
|
|
for (Entry<File, File> it : renameMap.entrySet()) {
|
|
|
|
|
try {
|
|
|
|
|
File source = it.getKey();
|
|
|
|
|
File destination = it.getValue();
|
|
|
|
|
|
|
|
|
|
// resolve destination
|
|
|
|
|
if (!destination.isAbsolute()) {
|
|
|
|
@ -440,27 +444,28 @@ public class CmdlineOperations implements CmdlineInterface {
|
|
|
|
|
destination = new File(source.getParentFile(), destination.getPath());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (destinationSet.contains(destination))
|
|
|
|
|
throw new IllegalArgumentException("Conflict detected: " + mapping.getValue());
|
|
|
|
|
|
|
|
|
|
if (destination.exists() && !source.equals(destination))
|
|
|
|
|
throw new IllegalArgumentException("File already exists: " + mapping.getValue());
|
|
|
|
|
|
|
|
|
|
destinationSet.add(destination);
|
|
|
|
|
if (!destination.equals(source) && destination.exists()) {
|
|
|
|
|
if (conflictAction == ConflictAction.FAIL) {
|
|
|
|
|
throw new Exception("File already exists: " + destination);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// rename files
|
|
|
|
|
final List<Entry<File, File>> renameLog = new ArrayList<Entry<File, File>>();
|
|
|
|
|
if (conflictAction == ConflictAction.OVERRIDE) {
|
|
|
|
|
if (!destination.delete()) {
|
|
|
|
|
throw new Exception("Failed to override file: " + destination);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
for (Entry<File, File> it : renameMap.entrySet()) {
|
|
|
|
|
try {
|
|
|
|
|
// rename file, throw exception on failure
|
|
|
|
|
File destination = renameAction.rename(it.getKey(), it.getValue());
|
|
|
|
|
if (!destination.equals(source) && !destination.exists()) {
|
|
|
|
|
destination = renameAction.rename(source, destination);
|
|
|
|
|
CLILogger.info(format("[%s] Renamed [%s] to [%s]", renameAction, it.getKey(), it.getValue()));
|
|
|
|
|
} else {
|
|
|
|
|
CLILogger.info(format("Skipped [%s] because [%s] already exists", source, destination));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remember successfully renamed matches for history entry and possible revert
|
|
|
|
|
renameLog.add(new SimpleImmutableEntry<File, File>(it.getKey(), destination));
|
|
|
|
|
renameLog.add(new SimpleImmutableEntry<File, File>(source, destination));
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
CLILogger.warning(format("[%s] Failed to rename [%s]", renameAction, it.getKey()));
|
|
|
|
|
throw e;
|
|
|
|
|