From 66af29de7f18693980630bd19c6f6f07aab07f8d Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Wed, 14 Dec 2011 01:19:36 +0000 Subject: [PATCH] * use thetvdb for tvseries imdb lookups --- .../filebot/mediainfo/ReleaseInfo.java | 21 +++-- .../filebot/web/OpenSubtitlesXmlRpc.java | 91 ++++++++++--------- .../filebot/web/TheTVDBClient.java | 20 +++- 3 files changed, 76 insertions(+), 56 deletions(-) diff --git a/source/net/sourceforge/filebot/mediainfo/ReleaseInfo.java b/source/net/sourceforge/filebot/mediainfo/ReleaseInfo.java index b95b4c5b..4e49d209 100644 --- a/source/net/sourceforge/filebot/mediainfo/ReleaseInfo.java +++ b/source/net/sourceforge/filebot/mediainfo/ReleaseInfo.java @@ -22,6 +22,8 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -29,7 +31,6 @@ import net.sourceforge.filebot.MediaTypes; import net.sourceforge.filebot.WebServices; import net.sourceforge.filebot.similarity.SeriesNameMatcher; import net.sourceforge.filebot.web.CachedResource; -import net.sourceforge.filebot.web.Movie; import net.sourceforge.filebot.web.SearchResult; import net.sourceforge.filebot.web.TheTVDBClient.TheTVDBSearchResult; @@ -42,8 +43,12 @@ public class ReleaseInfo { // don't allow duplicates Map names = new LinkedHashMap(); - for (SearchResult it : releaseInfo.lookupNameByInfoFile(files, Locale.ENGLISH)) { - names.put(it.getName().toLowerCase(), it.getName()); + try { + for (SearchResult it : releaseInfo.lookupSeriesNameByInfoFile(files, Locale.ENGLISH)) { + names.put(it.getName().toLowerCase(), it.getName()); + } + } catch (Exception e) { + Logger.getLogger(ReleaseInfo.class.getClass().getName()).log(Level.WARNING, "Failed to lookup info by id: " + e.getMessage()); } // match common word sequence and clean detected word sequence from unwanted elements @@ -69,7 +74,7 @@ public class ReleaseInfo { } - public Set lookupNameByInfoFile(Collection files, Locale language) throws Exception { + public Set lookupSeriesNameByInfoFile(Collection files, Locale language) throws Exception { Set names = new LinkedHashSet(); // search for id in sibling nfo files @@ -78,14 +83,14 @@ public class ReleaseInfo { String text = new String(readFile(nfo), "UTF-8"); for (int imdbid : grepImdbId(text)) { - Movie movie = WebServices.OpenSubtitles.getMovieDescriptor(imdbid, language); // movies and tv shows - if (movie != null) { - names.add(movie); + TheTVDBSearchResult series = WebServices.TheTVDB.lookupByIMDbID(imdbid, language); + if (series != null) { + names.add(series); } } for (int tvdbid : grepTheTvdbId(text)) { - TheTVDBSearchResult series = WebServices.TheTVDB.lookup(tvdbid, language); // just tv shows + TheTVDBSearchResult series = WebServices.TheTVDB.lookupByID(tvdbid, language); if (series != null) { names.add(series); } diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java b/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java index 8ed769c0..5814e6ea 100644 --- a/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java +++ b/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java @@ -15,9 +15,9 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Scanner; -import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; @@ -39,12 +39,12 @@ public class OpenSubtitlesXmlRpc { private String token; - + public OpenSubtitlesXmlRpc(String useragent) { this.useragent = useragent; } - + /** * Login as anonymous user */ @@ -52,7 +52,7 @@ public class OpenSubtitlesXmlRpc { login("", "", "en"); } - + /** * This will login user. This method should be called always when starting talking with * server. @@ -69,7 +69,7 @@ public class OpenSubtitlesXmlRpc { token = response.get("token").toString(); } - + /** * This will logout user (ends session id). Call this function is before closing the client program. */ @@ -84,23 +84,23 @@ public class OpenSubtitlesXmlRpc { } } - + public boolean isLoggedOn() { return token != null; } - + @SuppressWarnings("unchecked") public Map getServerInfo() throws XmlRpcFault { return (Map) invoke("ServerInfo", token); } - + public List searchSubtitles(int imdbid, String... sublanguageids) throws XmlRpcFault { return searchSubtitles(singleton(Query.forImdbId(imdbid, sublanguageids))); } - + @SuppressWarnings("unchecked") public List searchSubtitles(Collection queryList) throws XmlRpcFault { List subtitles = new ArrayList(); @@ -119,7 +119,7 @@ public class OpenSubtitlesXmlRpc { return subtitles; } - + @SuppressWarnings("unchecked") public List searchMoviesOnIMDB(String query) throws XmlRpcFault { Map response = invoke("SearchMoviesOnIMDB", token, query); @@ -153,7 +153,7 @@ public class OpenSubtitlesXmlRpc { return movies; } - + @SuppressWarnings("unchecked") public TryUploadResponse tryUploadSubtitles(SubFile... subtitles) throws XmlRpcFault { Map struct = new HashMap(); @@ -171,7 +171,7 @@ public class OpenSubtitlesXmlRpc { return new TryUploadResponse(uploadRequired, Property.asEnumMap(subtitleData)); } - + public URI uploadSubtitles(BaseInfo baseInfo, SubFile... subtitles) throws XmlRpcFault { Map struct = new HashMap(); @@ -189,7 +189,7 @@ public class OpenSubtitlesXmlRpc { return URI.create(response.get("data").toString()); } - + @SuppressWarnings("unchecked") public List detectLanguage(byte[] data) throws XmlRpcFault { // compress and base64 encode @@ -205,7 +205,7 @@ public class OpenSubtitlesXmlRpc { return languages; } - + @SuppressWarnings("unchecked") public Map checkSubHash(Collection hashes) throws XmlRpcFault { Map response = invoke("CheckSubHash", token, hashes); @@ -221,7 +221,7 @@ public class OpenSubtitlesXmlRpc { return subHashMap; } - + @SuppressWarnings("unchecked") public Map checkMovieHash(Collection hashes) throws XmlRpcFault { Map response = invoke("CheckMovieHash", token, hashes); @@ -246,12 +246,12 @@ public class OpenSubtitlesXmlRpc { return movieHashMap; } - + public Map getSubLanguages() throws XmlRpcFault { return getSubLanguages("en"); } - + @SuppressWarnings("unchecked") public Movie getIMDBMovieDetails(int imdbid) throws XmlRpcFault { Map response = invoke("GetIMDBMovieDetails", token, imdbid); @@ -265,12 +265,13 @@ public class OpenSubtitlesXmlRpc { return new Movie(name, year, imdbid); } catch (RuntimeException e) { // ignore, invalid response + Logger.getLogger(getClass().getName()).log(Level.WARNING, String.format("Failed to lookup movie by imdbid %s: %s", imdbid, e.getMessage())); } return null; } - + @SuppressWarnings("unchecked") public Map getSubLanguages(String languageCode) throws XmlRpcFault { Map>> response = (Map>>) invoke("GetSubLanguages", languageCode); @@ -284,12 +285,12 @@ public class OpenSubtitlesXmlRpc { return subLanguageMap; } - + public void noOperation() throws XmlRpcFault { invoke("NoOperation", token); } - + protected Map invoke(String method, Object... arguments) throws XmlRpcFault { try { XmlRpcClient rpc = new XmlRpcClient(getXmlRpcUrl(), false); @@ -308,7 +309,7 @@ public class OpenSubtitlesXmlRpc { } } - + protected URL getXmlRpcUrl() { try { return new URL("http://api.opensubtitles.org/xml-rpc"); @@ -318,7 +319,7 @@ public class OpenSubtitlesXmlRpc { } } - + protected static String encodeData(byte[] data) { try { DeflaterInputStream compressedDataStream = new DeflaterInputStream(new ByteArrayInputStream(data)); @@ -335,7 +336,7 @@ public class OpenSubtitlesXmlRpc { } } - + /** * Check whether status is OK or not * @@ -357,7 +358,7 @@ public class OpenSubtitlesXmlRpc { } } - + public static final class Query extends HashMap { private Query(String imdbid, String... sublanguageids) { @@ -365,119 +366,119 @@ public class OpenSubtitlesXmlRpc { put("sublanguageid", join(sublanguageids, ",")); } - + private Query(String moviehash, String moviebytesize, String... sublanguageids) { put("moviehash", moviehash); put("moviebytesize", moviebytesize); put("sublanguageid", join(sublanguageids, ",")); } - + public static Query forHash(String moviehash, long moviebytesize, String... sublanguageids) { return new Query(moviehash, Long.toString(moviebytesize), sublanguageids); } - + public static Query forImdbId(int imdbid, String... sublanguageids) { return new Query(Integer.toString(imdbid), sublanguageids); } } - + public static final class BaseInfo extends HashMap { public void setIDMovieImdb(int imdb) { put("idmovieimdb", Integer.toString(imdb)); } - + public void setSubLanguageID(String sublanguageid) { put("sublanguageid", sublanguageid); } - + public void setMovieReleaseName(String moviereleasename) { put("moviereleasename", moviereleasename); } - + public void setMovieAka(String movieaka) { put("movieaka", movieaka); } - + public void setSubAuthorComment(String subauthorcomment) { put("subauthorcomment", subauthorcomment); } } - + public static final class SubFile extends HashMap { public void setSubHash(String subhash) { put("subhash", subhash); } - + public void setSubFileName(String subfilename) { put("subfilename", subfilename); } - + public void setMovieHash(String moviehash) { put("moviehash", moviehash); } - + public void setMovieByteSize(long moviebytesize) { put("moviebytesize", Long.toString(moviebytesize)); } - + public void setMovieTimeMS(int movietimems) { put("movietimems", movietimems); } - + public void setMovieFrames(int movieframes) { put("movieframes", movieframes); } - + public void setMovieFPS(double moviefps) { put("moviefps", moviefps); } - + public void setMovieFileName(String moviefilename) { put("moviefilename", moviefilename); } - + public void setSubContent(byte[] data) { put("subcontent", encodeData(data)); } } - + public static final class TryUploadResponse { private final boolean uploadRequired; private final Map subtitleData; - + private TryUploadResponse(boolean uploadRequired, Map subtitleData) { this.uploadRequired = uploadRequired; this.subtitleData = subtitleData; } - + public boolean isUploadRequired() { return uploadRequired; } - + public Map getSubtitleData() { return subtitleData; } diff --git a/source/net/sourceforge/filebot/web/TheTVDBClient.java b/source/net/sourceforge/filebot/web/TheTVDBClient.java index eaae3d36..5cfd6b18 100644 --- a/source/net/sourceforge/filebot/web/TheTVDBClient.java +++ b/source/net/sourceforge/filebot/web/TheTVDBClient.java @@ -184,21 +184,35 @@ public class TheTVDBClient extends AbstractEpisodeListProvider { } - public TheTVDBSearchResult lookup(int id, Locale language) throws Exception { + public TheTVDBSearchResult lookupByID(int id, Locale language) throws Exception { try { URL baseRecordLocation = getResource(MirrorType.XML, "/api/" + apikey + "/series/" + id + "/all/" + language.getLanguage() + ".xml"); - Document baseRecord = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(baseRecordLocation.openStream()); + Document baseRecord = getDocument(baseRecordLocation); String name = selectString("//SeriesName", baseRecord); return new TheTVDBSearchResult(name, id); } catch (FileNotFoundException e) { // illegal series id - Logger.getLogger(getClass().getName()).log(Level.WARNING, "Failed to retrieve base series record", e); + Logger.getLogger(getClass().getName()).log(Level.WARNING, "Failed to retrieve base series record: " + e.getMessage()); return null; } } + public TheTVDBSearchResult lookupByIMDbID(int imdbid, Locale language) throws Exception { + URL query = getResource(MirrorType.XML, "/api/GetSeriesByRemoteID.php?imdbid=" + imdbid + "&language=" + language.getLanguage()); + Document dom = getDocument(query); + + String id = selectString("//seriesid", dom); + String name = selectString("//SeriesName", dom); + + if (id == null || id.isEmpty() || name == null || name.isEmpty()) + return null; + + return new TheTVDBSearchResult(name, Integer.parseInt(id)); + } + + @Override public URI getEpisodeListLink(SearchResult searchResult) { int seriesId = ((TheTVDBSearchResult) searchResult).getSeriesId();