pct.droid.base.providers.subs.OpenSubsProvider.java Source code

Java tutorial

Introduction

Here is the source code for pct.droid.base.providers.subs.OpenSubsProvider.java

Source

/*
 * This file is part of Popcorn Time.
 *
 * Popcorn Time is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Popcorn Time is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Popcorn Time. If not, see <http://www.gnu.org/licenses/>.
 */

package pct.droid.base.providers.subs;

import org.apache.http.MethodNotSupportedException;
import org.xmlrpc.android.XMLRPCCallback;
import org.xmlrpc.android.XMLRPCClient;
import org.xmlrpc.android.XMLRPCException;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import pct.droid.base.providers.media.models.Episode;
import pct.droid.base.providers.media.models.Movie;
import pct.droid.base.providers.media.models.Show;

public class OpenSubsProvider extends SubsProvider {

    protected String mApiUrl = "http://api.opensubtitles.org/xml-rpc";
    protected String mUserAgent = "Popcorn Time v1";//"Popcorn Time Android v1";

    @Override
    public void getList(Movie movie, Callback callback) {
        // Movie subtitles not supported
        callback.onFailure(new MethodNotSupportedException("Movie subtitles not supported"));
    }

    @Override
    public void getList(final Show show, final Episode episode, final Callback callback) {
        login(new XMLRPCCallback() {
            @Override
            public void onSuccess(long id, Object result) {
                Map<String, Object> response = (Map<String, Object>) result;
                String token = (String) response.get("token");

                final String episodeStr = Integer.toString(episode.episode);
                final String seasonStr = Integer.toString(episode.season);

                if (!token.isEmpty()) {
                    search(show, seasonStr, episodeStr, token, new XMLRPCCallback() {
                        @Override
                        public void onSuccess(long id, Object result) {
                            Map<String, Map<String, String>> returnMap = new HashMap<>();
                            Map<String, Integer[]> scoreMap = new HashMap<>();
                            Map<String, String> episodeMap = new HashMap<>();
                            Map<String, Object> subData = (Map<String, Object>) result;
                            if (subData != null && subData.get("data") != null
                                    && subData.get("data") instanceof Object[]) {
                                Object[] dataList = (Object[]) subData.get("data");
                                for (Object dataItem : dataList) {
                                    Map<String, String> item = (Map<String, String>) dataItem;
                                    if (!item.get("SubFormat").equals("srt")) {
                                        continue;
                                    }

                                    // episode check
                                    if (Integer.parseInt(item.get("SeriesIMDBParent")) != Integer
                                            .parseInt(show.imdbId.replace("tt", ""))) {
                                        continue;
                                    }
                                    if (!item.get("SeriesSeason").equals(seasonStr)) {
                                        continue;
                                    }
                                    if (!item.get("SeriesEpisode").equals(episodeStr)) {
                                        continue;
                                    }

                                    String url = item.get("SubDownloadLink").replace(".gz", ".srt");
                                    String lang = item.get("ISO639").replace("pb", "pt-br");
                                    int downloads = Integer.parseInt(item.get("SubDownloadsCnt"));
                                    int score = 0;

                                    if (item.get("MatchedBy").equals("tag")) {
                                        score += 50;
                                    }
                                    if (item.get("UserRank").equals("trusted")) {
                                        score += 100;
                                    }
                                    if (!episodeMap.containsKey(lang)) {
                                        episodeMap.put(lang, url);
                                        scoreMap.put(lang, new Integer[] { score, downloads });
                                    } else {
                                        // If score is 0 or equal, sort by downloads
                                        if (score > scoreMap.get(lang)[0] || (score == scoreMap.get(lang)[0]
                                                && downloads > scoreMap.get(lang)[1])) {
                                            episodeMap.put(lang, url);
                                            scoreMap.put(lang, new Integer[] { score, downloads });
                                        }
                                    }
                                }
                                returnMap.put(show.videoId, episodeMap);
                                callback.onSuccess(returnMap.get(show.videoId));
                            } else {
                                callback.onFailure(new XMLRPCException("No subs found"));
                            }
                        }

                        @Override
                        public void onFailure(long id, Exception error) {
                            callback.onFailure(error);
                        }
                    });
                } else {
                    callback.onFailure(new XMLRPCException("Token not correct"));
                }
            }

            @Override
            public void onFailure(long id, Exception error) {
                callback.onFailure(error);
            }
        });
    }

    /**
     * Login to server and get token
     *
     * @return Token
     */
    private void login(XMLRPCCallback callback) {
        try {
            XMLRPCClient client = new XMLRPCClient(new URI(mApiUrl), "", "", mUserAgent);
            client.callAsync(callback, "LogIn", new String[] { "", "", "en", mUserAgent });
        } catch (URISyntaxException e) {
            e.printStackTrace();
            // Just catch and fail
        }
    }

    /**
     * Search for subtitles by imdbId, season and episode
     *
     * @param show    Show
     * @param season  Season number
     * @param episode Episode number
     * @param token   Login token
     * @return SRT URL
     */
    private void search(Show show, String season, String episode, String token, XMLRPCCallback callback) {
        try {
            XMLRPCClient client = new XMLRPCClient(new URI(mApiUrl), "", "", mUserAgent);
            Map<String, String> option = new HashMap<String, String>();
            option.put("imdbid", show.imdbId.replace("tt", ""));
            option.put("season", season);
            option.put("episode", episode);
            option.put("sublanguageid", "all");
            client.callAsync(callback, "SearchSubtitles", new Object[] { token, new Object[] { option } });
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

}