package org.lodder.subtools.multisubdownloader.subtitleproviders.opensubtitles; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.Vector; import org.lodder.subtools.multisubdownloader.subtitleproviders.opensubtitles.model.OpenSubtitlesMovieDescriptor; import org.lodder.subtools.multisubdownloader.subtitleproviders.opensubtitles.model.OpenSubtitlesSubtitleDescriptor; import org.lodder.subtools.sublibrary.data.XmlRPC; import org.lodder.subtools.sublibrary.util.NamedMatcher; import org.lodder.subtools.sublibrary.util.NamedPattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JOpenSubtitlesApi extends XmlRPC { private static final Logger LOGGER = LoggerFactory.getLogger(JOpenSubtitlesApi.class); public JOpenSubtitlesApi(String useragent) throws Exception { super(useragent, "http://api.opensubtitles.org/xml-rpc"); if (!isLoggedOn()) loginAnonymous(); } public void loginAnonymous() throws Exception { login("", ""); } public void login(String username, String password) throws Exception { login(username, password, "en"); } @SuppressWarnings("unchecked") public synchronized void login(String username, String password, String language) throws Exception { Map<String, String> response = (Map<String, String>) invoke("LogIn", new Object[] {username, password, language, getUserAgent()}); setToken(response.get("token")); } public synchronized void logout() throws MalformedURLException { try { invoke("LogOut", new Object[] {getToken()}); } catch (Exception localXmlRpcFault) {} finally { setToken(null); } } @SuppressWarnings("unchecked") public Map<String, String> getServerInfo() throws Exception { return (Map<String, String>) invoke("ServerInfo", new Object[] {getToken()}); } @SuppressWarnings("unchecked") public List<OpenSubtitlesMovieDescriptor> searchMoviesOnIMDB(String title) throws Exception { List<OpenSubtitlesMovieDescriptor> movies = new ArrayList<OpenSubtitlesMovieDescriptor>(); Map<String, List<Map<String, String>>> response = (Map<String, List<Map<String, String>>>) invoke("SearchMoviesOnIMDB", new Object[] { getToken(), title}); List<Map<String, String>> movieData = (List<Map<String, String>>) response.get("data"); NamedPattern np = NamedPattern.compile( "(?<moviename>[\\w\\s:&().,_-]+)[\\.|\\[|\\(| ]{1}(?<year>19\\d{2}|20\\d{2})", 2); for (Map<String, String> movie : movieData) { Scanner titleScanner = new Scanner((String) movie.get("title")); titleScanner.useDelimiter("(Â)|(\\s+aka\\s+)"); NamedMatcher nm = np.matcher(titleScanner.next().trim()); int imdbid = 0; int year = 0; if (nm.find()) { try { imdbid = Integer.parseInt((String) movie.get("id")); year = Integer.parseInt(nm.group("year")); } catch (Exception e) { LOGGER.error("searchMoviesOnImdb parse imdbid and year", e); } movies.add(new OpenSubtitlesMovieDescriptor(nm.group("moviename"), year, imdbid)); } titleScanner.close(); } return movies; } public OpenSubtitlesMovieDescriptor getIMDBMovieDetails(int imdbid) throws Exception { Map<?, ?> response = invoke("GetIMDBMovieDetails", new Object[] {getToken(), Integer.valueOf(imdbid)}); try { Map<?, ?> data = (Map<?, ?>) response.get("data"); String name = (String) data.get("title"); int year = Integer.parseInt((String) data.get("year")); return new OpenSubtitlesMovieDescriptor(name, year, imdbid); } catch (RuntimeException localRuntimeException) {} return null; } public synchronized boolean isLoggedOn() { return getToken() != null; } public List<OpenSubtitlesSubtitleDescriptor> searchSubtitles(String moviehash, String moviebytesize, String[] languages) throws Exception { Map<String, Object> queryList = new HashMap<String, Object>(); queryList.put("moviehash", moviehash); queryList.put("moviebytesize", moviebytesize); return searchSubtitles(queryList, languages); } public List<OpenSubtitlesSubtitleDescriptor> searchSubtitles(int imdbid, String[] languages) throws Exception { Map<String, Object> queryList = new HashMap<String, Object>(); queryList.put("imdbid", Integer.valueOf(imdbid)); return searchSubtitles(queryList, languages); } public List<OpenSubtitlesSubtitleDescriptor> searchSubtitles(String query, String[] languages) throws Exception { Map<String, Object> queryList = new HashMap<String, Object>(); queryList.put("query", query); return searchSubtitles(queryList, languages); } public List<OpenSubtitlesSubtitleDescriptor> searchSubtitles(String query, int season, List<Integer> episode, String[] languages) throws Exception { Map<String, Object> queryList = new HashMap<String, Object>(); queryList.put("query", query); queryList.put("season", Integer.valueOf(season)); queryList.put("episode", episode.get(0)); return searchSubtitles(queryList, languages); } @SuppressWarnings("unchecked") public List<OpenSubtitlesSubtitleDescriptor> searchSubtitles(Map<String, Object> queryList, String[] languages) throws Exception { List<OpenSubtitlesSubtitleDescriptor> subtitles = new ArrayList<OpenSubtitlesSubtitleDescriptor>(); StringBuilder result = new StringBuilder(); String separator = ","; if (languages.length > 0) { result.append(OS_LANGS.get(languages[0])); for (int i = 1; i < languages.length; i++) { result.append(separator); result.append(OS_LANGS.get(languages[i])); } } queryList.put("sublanguageid", result.toString()); Vector<Object> params = new Vector<Object>(); params.add(getToken()); params.add(new Object[] {queryList}); Map<String, ?> response = (Map<String, ?>) invoke("SearchSubtitles", params); try { if (response.get("data") instanceof Object[]) { Object[] data = (Object[]) response.get("data"); for (Object o : data) { subtitles.add(parseOSSubtitle((Map<String, String>) o)); } } } catch (Exception localException) { LOGGER.error("searhSubtitles parsing", localException); } return subtitles; } private OpenSubtitlesSubtitleDescriptor parseOSSubtitle(Map<String, String> subtitle) { OpenSubtitlesSubtitleDescriptor oss = new OpenSubtitlesSubtitleDescriptor(); oss.setUserNickName(subtitle.get("UserNickName")); oss.setSubFormat(subtitle.get("SubFormat")); oss.setIDSubtitle(Integer.parseInt(subtitle.get("IDSubtitle"))); oss.setIDMovie(Integer.parseInt(subtitle.get("IDMovie"))); oss.setSubBad(subtitle.get("SubBad")); oss.setUserID(Integer.parseInt(subtitle.get("UserID"))); oss.setZipDownloadLink(subtitle.get("ZipDownloadLink")); oss.setSubSize(Long.parseLong(subtitle.get("SubSize"))); oss.setSubFileName(subtitle.get("SubFileName")); oss.setSubDownloadLink(subtitle.get("SubDownloadLink")); oss.setUserRank(subtitle.get("UserRank")); oss.setSubActualCD(subtitle.get("SubActualCD")); oss.setMovieImdbRating(subtitle.get("MovieImdbRating")); oss.setSubAuthorComment(subtitle.get("SubAuthorComment")); oss.setSubRating(subtitle.get("SubRating")); oss.setSubtitlesLink(subtitle.get("SubtitlesLink")); oss.setSubHearingImpaired(subtitle.get("SubHearingImpaired")); oss.setSubHash(subtitle.get("SubHash")); oss.setIDSubMovieFile(Integer.parseInt(subtitle.get("IDSubMovieFile"))); oss.setISO639(subtitle.get("ISO639")); oss.setSubDownloadsCnt(Integer.parseInt(subtitle.get("SubDownloadsCnt"))); oss.setMovieHash(subtitle.get("MovieHash")); oss.setSubSumCD(Integer.parseInt(subtitle.get("SubSumCD"))); oss.setSubComments(subtitle.get("SubComments")); oss.setMovieByteSize(Long.parseLong(subtitle.get("MovieByteSize"))); oss.setLanguageName(subtitle.get("LanguageName")); oss.setMovieYear(Integer.parseInt(subtitle.get("MovieYear"))); oss.setSubLanguageID(subtitle.get("SubLanguageID")); oss.setMovieReleaseName(subtitle.get("MovieReleaseName")); oss.setMovieTimeMS(subtitle.get("MovieTimeMS")); oss.setMatchedBy(subtitle.get("MatchedBy")); oss.setMovieName(subtitle.get("MovieName")); oss.setSubAddDate(subtitle.get("SubAddDate")); oss.setIDMovieImdb(Integer.parseInt(subtitle.get("IDMovieImdb"))); oss.setMovieNameEng(subtitle.get("MovieNameEng")); oss.setIDSubtitle(Integer.parseInt(subtitle.get("IDSubtitleFile"))); return oss; } private static final Map<String, String> OS_LANGS = Collections .unmodifiableMap(new HashMap<String, String>() { /** * */ private static final long serialVersionUID = 1683941675464726802L; { put("en", "eng"); put("fr", "fre"); put("hu", "hun"); put("cs", "cze"); put("pl", "pol"); put("sk", "slo"); put("pt", "por"); put("pt-br", "pob"); put("es", "spa"); put("el", "ell"); put("ar", "ara"); put("sq", "alb"); put("hy", "arm"); put("ay", "ass"); put("bs", "bos"); put("bg", "bul"); put("ca", "cat"); put("zh", "chi"); put("hr", "hrv"); put("da", "dan"); put("nl", "dut"); put("eo", "epo"); put("et", "est"); put("fi", "fin"); put("gl", "glg"); put("ka", "geo"); put("de", "ger"); put("he", "heb"); put("hi", "hin"); put("is", "ice"); put("id", "ind"); put("it", "ita"); put("ja", "jpn"); put("kk", "kaz"); put("ko", "kor"); put("lv", "lav"); put("lt", "lit"); put("lb", "ltz"); put("mk", "mac"); put("ms", "may"); put("no", "nor"); put("oc", "oci"); put("fa", "per"); put("ro", "rum"); put("ru", "rus"); put("sr", "scc"); put("sl", "slv"); put("sv", "swe"); put("th", "tha"); put("tr", "tur"); put("uk", "ukr"); put("vi", "vie"); } }); }