* support --filter in -rename movie-mode on query-based detection logic

This commit is contained in:
Reinhard Pointner 2013-09-11 15:52:35 +00:00
parent 4799476150
commit 3a8d8d22d5
1 changed files with 211 additions and 227 deletions

View File

@ -1,7 +1,5 @@
package net.sourceforge.filebot.cli;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Collections.addAll;
@ -67,7 +65,6 @@ import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@ -121,7 +118,6 @@ import net.sourceforge.filebot.web.SubtitleProvider;
import net.sourceforge.filebot.web.VideoHashSubtitleService;
import net.sourceforge.tuned.FileUtilities.ParentFilter;
public class CmdlineOperations implements CmdlineInterface {
@Override
@ -139,7 +135,7 @@ public class CmdlineOperations implements CmdlineInterface {
if (getMovieIdentificationService(db) != null) {
// movie mode
return renameMovie(files, action, conflictAction, outputDir, format, getMovieIdentificationService(db), query, locale, strict);
return renameMovie(files, action, conflictAction, outputDir, format, getMovieIdentificationService(db), query, filter, locale, strict);
}
if (getMusicIdentificationService(db) != null || containsOnly(files, AUDIO_FILES)) {
@ -178,11 +174,10 @@ public class CmdlineOperations implements CmdlineInterface {
if (sxe > (max * 0.65) || cws > (max * 0.65)) {
return renameSeries(files, action, conflictAction, outputDir, format, WebServices.TheTVDB, query, SortOrder.forName(sortOrder), filter, locale, strict); // use default episode db
} else {
return renameMovie(files, action, conflictAction, outputDir, format, WebServices.TMDb, query, locale, strict); // use default movie db
return renameMovie(files, action, conflictAction, outputDir, format, WebServices.TMDb, query, filter, locale, strict); // use default movie db
}
}
public List<File> renameSeries(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFormat format, EpisodeListProvider db, String query, SortOrder sortOrder, ExpressionFilter filter, Locale locale, boolean strict) throws Exception {
CLILogger.config(format("Rename episodes using [%s]", db.getName()));
@ -215,7 +210,7 @@ public class CmdlineOperations implements CmdlineInterface {
}
// fetch episode data
Set<Episode> episodes = fetchEpisodeSet(db, seriesNames, sortOrder, locale, strict);
Collection<Episode> episodes = fetchEpisodeSet(db, seriesNames, sortOrder, locale, strict);
if (episodes.size() == 0) {
CLILogger.warning("Failed to fetch episode data: " + seriesNames);
@ -223,17 +218,7 @@ public class CmdlineOperations implements CmdlineInterface {
}
// filter episodes
if (filter != null) {
CLILogger.fine(String.format("Apply Filter: {%s}", filter.getExpression()));
for (Iterator<Episode> itr = episodes.iterator(); itr.hasNext();) {
Episode episode = itr.next();
if (filter.matches(new MediaBindingBean(episode, null, null))) {
CLILogger.finest(String.format("Include [%s]", episode));
} else {
itr.remove();
}
}
}
episodes = applyExpressionFilter(episodes, filter);
matches.addAll(matchEpisodes(filter(batch, VIDEO_FILES), episodes, strict));
matches.addAll(matchEpisodes(filter(batch, SUBTITLE_FILES), episodes, strict));
@ -290,7 +275,6 @@ public class CmdlineOperations implements CmdlineInterface {
return renameAll(renameMap, renameAction, conflictAction);
}
private List<Match<File, Object>> matchEpisodes(Collection<File> files, Collection<Episode> episodes, boolean strict) throws Exception {
// always use strict fail-fast matcher
EpisodeMatcher matcher = new EpisodeMatcher(files, episodes, strict);
@ -303,7 +287,6 @@ public class CmdlineOperations implements CmdlineInterface {
return matches;
}
private Set<Episode> fetchEpisodeSet(final EpisodeListProvider db, final Collection<String> names, final SortOrder sortOrder, final Locale locale, final boolean strict) throws Exception {
Set<SearchResult> shows = new LinkedHashSet<SearchResult>();
Set<Episode> episodes = new LinkedHashSet<Episode>();
@ -335,8 +318,7 @@ public class CmdlineOperations implements CmdlineInterface {
return episodes;
}
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 {
public List<File> renameMovie(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFormat format, MovieIdentificationService service, String query, ExpressionFilter filter, Locale locale, boolean strict) throws Exception {
CLILogger.config(format("Rename movies using [%s]", service.getName()));
// ignore sample files
@ -379,7 +361,7 @@ public class CmdlineOperations implements CmdlineInterface {
}
Analytics.trackEvent(service.getName(), "HashLookup", "Movie", hashLookup.size()); // number of positive hash lookups
} catch (UnsupportedOperationException e) {
// ignore logging => hash lookup only supported by OpenSubtitles
}
}
@ -429,8 +411,15 @@ public class CmdlineOperations implements CmdlineInterface {
}
} else {
CLILogger.fine(format("Looking up movie by query [%s]", query));
Movie result = (Movie) selectSearchResult(query, service.searchMovie(query, locale), strict).get(0);
List<Movie> results = service.searchMovie(query, locale);
results = applyExpressionFilter(results, filter);
if (results.isEmpty()) {
throw new Exception(format("Failed to look up movie by query [%s]", query));
}
// force all mappings
Movie result = (Movie) selectSearchResult(query, results, strict).get(0);
for (File file : files) {
movieByFile.put(file, result);
}
@ -459,6 +448,7 @@ public class CmdlineOperations implements CmdlineInterface {
if (movie == null) {
CLILogger.fine(format("Auto-detect movie from context: [%s]", file));
Collection<Movie> results = detectMovie(file, null, service, locale, strict);
results = applyExpressionFilter(results, filter);
try {
movie = (Movie) selectSearchResult(query, results, strict).get(0);
} catch (Exception e) {
@ -538,7 +528,6 @@ public class CmdlineOperations implements CmdlineInterface {
return renameAll(renameMap, renameAction, conflictAction);
}
public List<File> renameMusic(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFormat format, MusicIdentificationService service) throws Exception {
CLILogger.config(format("Rename music using [%s]", service.getName()));
List<File> audioFiles = filter(files, AUDIO_FILES);
@ -576,7 +565,6 @@ public class CmdlineOperations implements CmdlineInterface {
return renameAll(renameMap, renameAction, conflictAction);
}
private Map<File, Object> getContext(final Collection<Match<File, ?>> matches) {
return new AbstractMap<File, Object>() {
@ -593,7 +581,6 @@ public class CmdlineOperations implements CmdlineInterface {
};
}
private File getDestinationFile(File original, String newName, File outputDir) {
String extension = getExtension(original);
File newFile = new File(extension != null ? newName + '.' + extension : newName);
@ -611,7 +598,6 @@ public class CmdlineOperations implements CmdlineInterface {
return newFile;
}
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>>();
@ -674,7 +660,6 @@ public class CmdlineOperations implements CmdlineInterface {
return destinationList;
}
@Override
public List<File> getSubtitles(Collection<File> files, String db, String query, String languageName, String output, String csn, boolean strict) throws Exception {
final Language language = getLanguage(languageName);
@ -768,7 +753,6 @@ public class CmdlineOperations implements CmdlineInterface {
return subtitleFiles;
}
@Override
public List<File> getMissingSubtitles(Collection<File> files, String db, String query, final String languageName, String output, String csn, boolean strict) throws Exception {
List<File> videoFiles = filter(filter(files, VIDEO_FILES), new FileFilter() {
@ -779,7 +763,6 @@ public class CmdlineOperations implements CmdlineInterface {
// get language code suffix for given language (.eng)
private final String languageCodeSuffix = "." + Language.getISO3LanguageCodeByName(getLanguage(languageName).getName());
@Override
public boolean accept(File video) {
File[] subtitlesByFolder = cache.get(video.getParentFile());
@ -805,7 +788,6 @@ public class CmdlineOperations implements CmdlineInterface {
return getSubtitles(videoFiles, db, query, languageName, output, csn, strict);
}
private Map<File, File> downloadSubtitleBatch(String service, Map<File, SubtitleDescriptor> subtitles, SubtitleFormat outputFormat, Charset outputEncoding) {
Map<File, File> downloads = new HashMap<File, File>();
@ -822,7 +804,6 @@ public class CmdlineOperations implements CmdlineInterface {
return downloads;
}
private File downloadSubtitle(SubtitleDescriptor descriptor, File movieFile, SubtitleFormat outputFormat, Charset outputEncoding) throws Exception {
// fetch subtitle archive
CLILogger.config(format("Fetching [%s]", descriptor.getPath()));
@ -849,7 +830,6 @@ public class CmdlineOperations implements CmdlineInterface {
return destination;
}
private Map<File, SubtitleDescriptor> lookupSubtitleByHash(VideoHashSubtitleService service, Language language, Collection<File> videoFiles) throws Exception {
Map<File, SubtitleDescriptor> subtitleByVideo = new HashMap<File, SubtitleDescriptor>(videoFiles.size());
@ -863,7 +843,6 @@ public class CmdlineOperations implements CmdlineInterface {
return subtitleByVideo;
}
private Map<File, SubtitleDescriptor> lookupSubtitleByFileName(SubtitleProvider service, Collection<String> querySet, Language language, Collection<File> videoFiles, boolean strict) throws Exception {
// search for subtitles
List<SubtitleDescriptor> subtitles = findSubtitles(service, querySet, language.getName());
@ -880,7 +859,6 @@ public class CmdlineOperations implements CmdlineInterface {
return emptyMap();
}
private List<String> detectSeriesQuery(Collection<File> mediaFiles, Locale locale) throws Exception {
// detect series name by common word sequence
List<String> names = detectSeriesNames(mediaFiles, locale);
@ -893,6 +871,21 @@ public class CmdlineOperations implements CmdlineInterface {
return names;
}
private <T> List<T> applyExpressionFilter(Collection<T> input, ExpressionFilter filter) throws Exception {
if (filter == null) {
return new ArrayList<T>(input);
}
CLILogger.fine(String.format("Apply Filter: {%s}", filter.getExpression()));
List<T> output = new ArrayList<T>(input.size());
for (T it : input) {
if (filter.matches(new MediaBindingBean(it, null, null))) {
CLILogger.finest(String.format("Include [%s]", it));
output.add(it);
}
}
return output;
}
public List<SearchResult> findProbableMatches(final String query, Collection<? extends SearchResult> searchResults, boolean strict) {
// auto-select most probable search result
@ -918,7 +911,6 @@ public class CmdlineOperations implements CmdlineInterface {
return probableMatches;
}
public List<SearchResult> selectSearchResult(String query, Collection<? extends SearchResult> searchResults, boolean strict) throws Exception {
List<SearchResult> probableMatches = findProbableMatches(query, searchResults, strict);
@ -943,7 +935,6 @@ public class CmdlineOperations implements CmdlineInterface {
return probableMatches.size() <= 5 ? probableMatches : probableMatches.subList(0, 5); // trust that the correct match is in the Top 3
}
private Language getLanguage(String lang) throws Exception {
// try to look up by language code
Language language = Language.getLanguage(lang);
@ -961,7 +952,6 @@ public class CmdlineOperations implements CmdlineInterface {
return language;
}
@Override
public boolean check(Collection<File> files) throws Exception {
// only check existing hashes
@ -974,7 +964,6 @@ public class CmdlineOperations implements CmdlineInterface {
return result;
}
@Override
public File compute(Collection<File> files, String output, String csn) throws Exception {
// check common parent for all given files
@ -1011,7 +1000,6 @@ public class CmdlineOperations implements CmdlineInterface {
return outputFile;
}
private boolean check(File verificationFile, File root) throws Exception {
HashType type = getHashType(verificationFile);
@ -1049,7 +1037,6 @@ public class CmdlineOperations implements CmdlineInterface {
return status;
}
private void compute(String root, Collection<File> files, File outputFile, HashType hashType, String csn) throws IOException, Exception {
// compute hashes recursively and write to file
VerificationFileWriter out = new VerificationFileWriter(outputFile, hashType.getFormat(), csn != null ? csn : "UTF-8");
@ -1074,7 +1061,6 @@ public class CmdlineOperations implements CmdlineInterface {
}
}
@Override
public List<String> fetchEpisodeList(String query, String expression, String db, String sortOrderName, String languageName) throws Exception {
if (query == null || query.isEmpty())
@ -1097,14 +1083,12 @@ public class CmdlineOperations implements CmdlineInterface {
return episodes;
}
@Override
public String getMediaInfo(File file, String expression) throws Exception {
ExpressionFormat format = new ExpressionFormat(expression != null ? expression : "{fn} [{resolution} {af} {vc} {ac}]");
return format.format(new MediaBindingBean(file, file, null));
}
@Override
public List<File> extract(Collection<File> files, String output, String conflict, FileFilter filter, boolean forceExtractAll) throws Exception {
ConflictAction conflictAction = ConflictAction.forName(conflict);