/*
* 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 java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import de.timroes.axmlrpc.XMLRPCCallback;
import de.timroes.axmlrpc.XMLRPCClient;
import de.timroes.axmlrpc.XMLRPCException;
import de.timroes.axmlrpc.XMLRPCServerException;
import pct.droid.base.providers.media.models.Episode;
import pct.droid.base.providers.media.models.Movie;
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 NoSuchMethodException("Movie subtitles not supported"));
}
@Override
public void getList(final Episode episode, final Callback callback) {
login(new XMLRPCCallback() {
@Override
public void onResponse(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(episode, token, new XMLRPCCallback() {
@Override
public void onResponse(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(episode.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 > 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(episode.videoId, episodeMap);
callback.onSuccess(returnMap.get(episode.videoId));
} else {
callback.onFailure(new XMLRPCException("No subs found"));
}
}
@Override
public void onError(long id, XMLRPCException error) {
callback.onFailure(error);
}
@Override
public void onServerError(long id, XMLRPCServerException error) {
callback.onFailure(error);
}
});
} else {
callback.onFailure(new XMLRPCException("Token not correct"));
}
}
@Override
public void onError(long id, XMLRPCException error) {
callback.onFailure(error);
}
@Override
public void onServerError(long id, XMLRPCServerException error) {
callback.onFailure(error);
}
});
}
/**
* Login to server and get token
*
* @return Token
*/
private void login(XMLRPCCallback callback) {
try {
XMLRPCClient client = new XMLRPCClient(new URL(mApiUrl.replace("http://", "https://")), mUserAgent);
client.callAsync(callback, "LogIn", "", "", "en", mUserAgent);
} catch (MalformedURLException e) {
e.printStackTrace();
// Just catch and fail
}
}
/**
* Search for subtitles by imdbId, season and episode
*
* @param episode Episode
* @param token Login token
* @return SRT URL
*/
private void search(Episode episode, String token, XMLRPCCallback callback) {
try {
XMLRPCClient client = new XMLRPCClient(new URL(mApiUrl), mUserAgent);
Map<String, String> option = new HashMap<>();
option.put("imdbid", episode.imdbId.replace("tt", ""));
option.put("season", String.format(Locale.US, "%d", episode.season));
option.put("episode", String.format(Locale.US, "%d", episode.episode));
option.put("sublanguageid", "all");
client.callAsync(callback, "SearchSubtitles", token, new Object[]{option});
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}