diff --git a/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy b/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy index bda93902..7b1d98b4 100644 --- a/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy +++ b/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy @@ -205,7 +205,7 @@ def detectSeriesName(files, locale = Locale.ENGLISH) { return names == null || names.isEmpty() ? null : names.toList()[0] } -def detectMovie(movieFile, strict = true, queryLookupService = TheMovieDB, hashLookupService = null, locale = Locale.ENGLISH) { +def detectMovie(movieFile, strict = true, queryLookupService = TheMovieDB, hashLookupService = OpenSubtitles, locale = Locale.ENGLISH) { def movies = MediaDetection.detectMovie(movieFile, hashLookupService, queryLookupService, locale, strict) return movies == null || movies.isEmpty() ? null : movies.toList()[0] } diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java b/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java index e00e8354..f0fa4857 100644 --- a/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java +++ b/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java @@ -281,7 +281,8 @@ public class OpenSubtitlesClient implements SubtitleProvider, VideoHashSubtitleS for (int bn = 0; bn < ceil((float) hashes.size() / batchSize); bn++) { List batch = hashes.subList(bn * batchSize, min((bn * batchSize) + batchSize, hashes.size())); - for (Entry it : xmlrpc.checkMovieHash(batch).entrySet()) { + int minSeenCount = 20; // make sure we don't get mismatches by making sure the hash has not been confirmed numerous times + for (Entry it : xmlrpc.checkMovieHash(batch, minSeenCount).entrySet()) { result.put(hashMap.get(it.getKey()), it.getValue()); getCache().putData("getMovieDescriptor", it.getKey(), locale, it.getValue()); } diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java b/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java index 088a8250..33d04934 100644 --- a/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java +++ b/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java @@ -223,23 +223,45 @@ public class OpenSubtitlesXmlRpc { @SuppressWarnings("unchecked") - public Map checkMovieHash(Collection hashes) throws XmlRpcFault { - Map response = invoke("CheckMovieHash", token, hashes); - - Map movieHashData = (Map) response.get("data"); + public Map checkMovieHash(Collection hashes, int minSeenCount) throws XmlRpcFault { Map movieHashMap = new HashMap(); - for (Entry entry : movieHashData.entrySet()) { - // empty associative arrays are deserialized as array, not as map - if (entry.getValue() instanceof Map) { - Map info = (Map) entry.getValue(); - - String hash = info.get("MovieHash"); - String name = info.get("MovieName"); - int year = Integer.parseInt(info.get("MovieYear")); - int imdb = Integer.parseInt(info.get("MovieImdbID")); - - movieHashMap.put(hash, new Movie(name, year, imdb, -1)); + Map response = invoke("CheckMovieHash2", token, hashes); + Object payload = response.get("data"); + + if (payload instanceof Map) { + Map movieHashData = (Map) payload; + for (Entry entry : movieHashData.entrySet()) { + // empty associative arrays are deserialized as array, not as map + if (entry.getValue() instanceof List) { + String hash = entry.getKey(); + List matches = new ArrayList(); + + List hashMatches = (List) entry.getValue(); + for (Object match : hashMatches) { + if (match instanceof Map) { + Map info = (Map) match; + int seenCount = Integer.parseInt(info.get("SeenCount")); + + // require minimum SeenCount before this hash match is considered trusted + if (seenCount >= minSeenCount) { + String name = info.get("MovieName"); + int year = Integer.parseInt(info.get("MovieYear")); + int imdb = Integer.parseInt(info.get("MovieImdbID")); + + matches.add(new Movie(name, year, imdb, -1)); + } + } + } + + if (matches.size() == 1) { + // perfect unambiguous match + movieHashMap.put(hash, matches.get(0)); + } else if (matches.size() > 1) { + // multiple hash matches => ignore all + Logger.getLogger(getClass().getName()).log(Level.WARNING, "Ignore hash match due to hash collision: " + matches); + } + } } } diff --git a/test/net/sourceforge/filebot/web/OpenSubtitlesXmlRpcTest.java b/test/net/sourceforge/filebot/web/OpenSubtitlesXmlRpcTest.java index 4f8c3e1d..a13d37e1 100644 --- a/test/net/sourceforge/filebot/web/OpenSubtitlesXmlRpcTest.java +++ b/test/net/sourceforge/filebot/web/OpenSubtitlesXmlRpcTest.java @@ -10,15 +10,15 @@ import java.nio.ByteBuffer; import java.util.List; import java.util.Map; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - import net.sourceforge.filebot.web.OpenSubtitlesSubtitleDescriptor.Property; import net.sourceforge.filebot.web.OpenSubtitlesXmlRpc.Query; import net.sourceforge.filebot.web.OpenSubtitlesXmlRpc.SubFile; import net.sourceforge.filebot.web.OpenSubtitlesXmlRpc.TryUploadResponse; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + public class OpenSubtitlesXmlRpcTest { @@ -35,7 +35,7 @@ public class OpenSubtitlesXmlRpcTest { @Test public void search() throws Exception { List list = xmlrpc.searchMoviesOnIMDB("babylon 5"); - Movie sample = (Movie) list.get(0); + Movie sample = list.get(0); // check sample entry assertEquals("Babylon 5", sample.getName()); @@ -131,7 +131,7 @@ public class OpenSubtitlesXmlRpcTest { @Test public void checkMovieHash() throws Exception { - Map results = xmlrpc.checkMovieHash(singleton("d7aa0275cace4410")); + Map results = xmlrpc.checkMovieHash(singleton("d7aa0275cace4410"), 0); Movie movie = results.get("d7aa0275cace4410"); assertEquals("Iron Man", movie.getName()); @@ -142,7 +142,7 @@ public class OpenSubtitlesXmlRpcTest { @Test public void checkMovieHashInvalid() throws Exception { - Map results = xmlrpc.checkMovieHash(singleton("0123456789abcdef")); + Map results = xmlrpc.checkMovieHash(singleton("0123456789abcdef"), 0); // no movie info assertTrue(results.isEmpty());