diff --git a/source/net/filebot/cli/CmdlineOperations.java b/source/net/filebot/cli/CmdlineOperations.java index 80d9055f..0c3488be 100644 --- a/source/net/filebot/cli/CmdlineOperations.java +++ b/source/net/filebot/cli/CmdlineOperations.java @@ -419,7 +419,12 @@ public class CmdlineOperations implements CmdlineInterface { // unknown hash, try via imdb id from nfo file if (movie == null) { log.fine(format("Auto-detect movie from context: [%s]", file)); - List options = detectMovie(file, service, locale, strict); + List options = detectMovieWithYear(file, service, locale, strict); + + // ignore files that cannot yield any acceptable matches (e.g. movie files without year in strict mode) + if (options == null) { + continue; + } // apply filter if defined options = applyExpressionFilter(options, filter); @@ -447,15 +452,8 @@ public class CmdlineOperations implements CmdlineInterface { // check if we managed to lookup the movie descriptor if (movie != null) { - // get file list for movie - SortedSet movieParts = filesByMovie.get(movie); - - if (movieParts == null) { - movieParts = new TreeSet(); - filesByMovie.put(movie, movieParts); - } - - movieParts.add(file); + // add to file list for movie + filesByMovie.computeIfAbsent(movie, k -> new TreeSet()).add(file); } } @@ -1182,13 +1180,7 @@ public class CmdlineOperations implements CmdlineInterface { log.finest("Extracting files " + selection); // extract files selected by the given filter - archive.extract(outputMapper.getOutputDir(), new FileFilter() { - - @Override - public boolean accept(File entry) { - return selection.contains(outputMapper.getOutputFile(entry)); - } - }); + archive.extract(outputMapper.getOutputDir(), outputMapper.newPathFilter(selection)); for (FileInfo it : selection) { extractedFiles.add(it.toFile()); diff --git a/source/net/filebot/cli/ScriptShellBaseClass.java b/source/net/filebot/cli/ScriptShellBaseClass.java index 6af464df..4cdd4e96 100644 --- a/source/net/filebot/cli/ScriptShellBaseClass.java +++ b/source/net/filebot/cli/ScriptShellBaseClass.java @@ -273,8 +273,8 @@ public abstract class ScriptShellBaseClass extends Script { // 3. run full-fledged movie detection try { - List options = MediaDetection.detectMovie(file, WebServices.TheMovieDB, Locale.US, strict); - if (options.size() > 0) { + List options = MediaDetection.detectMovieWithYear(file, WebServices.TheMovieDB, Locale.US, strict); + if (options != null && options.size() > 0) { return options.get(0); } } catch (Exception e) { diff --git a/source/net/filebot/media/MediaDetection.java b/source/net/filebot/media/MediaDetection.java index c867ba1a..da9f02f3 100644 --- a/source/net/filebot/media/MediaDetection.java +++ b/source/net/filebot/media/MediaDetection.java @@ -123,7 +123,7 @@ public class MediaDetection { } // require a good S00E00 match - return MediaDetection.isEpisode(String.join("/", file.getParent(), file.getName()), strict); + return isEpisode(String.join("/", file.getParent(), file.getName()), strict); } public static boolean isMovie(File file, boolean strict) { @@ -677,6 +677,22 @@ public class MediaDetection { return sortMoviesBySimilarity(options, terms); } + public static List detectMovieWithYear(File movieFile, MovieIdentificationService service, Locale locale, boolean strict) throws Exception { + // in non-strict mode, process all movie files as best as possible + if (!strict) { + return detectMovie(movieFile, service, locale, strict); + } + + // in strict mode, only process movies that follow the name (year) pattern, so we can confirm each match by checking the movie year + List year = parseMovieYear(getRelativePathTail(movieFile, 3).getPath()); + if (year.isEmpty() || isEpisode(movieFile, true)) { + return null; + } + + // allow only movie matches where the the movie year matches the year pattern in the filename + return detectMovie(movieFile, service, locale, strict).stream().filter(m -> year.contains(m.getYear())).collect(toList()); + } + public static SimilarityMetric getMovieMatchMetric() { return new MetricAvg(new SequenceMatchSimilarity(), new NameSimilarityMetric(), new SequenceMatchSimilarity(0, true), new StringEqualsMetric() { diff --git a/source/net/filebot/ui/rename/MovieMatcher.java b/source/net/filebot/ui/rename/MovieMatcher.java index 3332f9ca..41b4177a 100644 --- a/source/net/filebot/ui/rename/MovieMatcher.java +++ b/source/net/filebot/ui/rename/MovieMatcher.java @@ -159,19 +159,14 @@ class MovieMatcher implements AutoCompleteMatcher { try { List>>> tasks = movieMatchFiles.stream().filter(f -> movieByFile.get(f) == null).map(f -> { return workerThreadPool.submit(() -> { - if (strict) { - // in strict mode, only process movies that follow the name (year) pattern - List year = parseMovieYear(getRelativePathTail(f, 3).getPath()); - if (year.isEmpty() || isEpisode(f, true)) { - return (Map>) EMPTY_MAP; - } + List options = detectMovieWithYear(f, service, locale, strict); - // allow only movie matches where the the movie year matches the year pattern in the filename - return singletonMap(f, detectMovie(f, service, locale, strict).stream().filter(m -> year.contains(m.getYear())).collect(toList())); - } else { - // in non-strict mode just allow all options - return singletonMap(f, detectMovie(f, service, locale, strict)); + // ignore files that cannot yield any acceptable matches (e.g. movie files without year in strict mode) + if (options == null) { + return (Map>) EMPTY_MAP; } + + return singletonMap(f, options); }); }).collect(toList());