package org.softeg.slartus.forpdaplus.video.api;
import android.text.Html;
import android.text.TextUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.softeg.slartus.forpdaplus.Client;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class YouTubeAPI {
public static final String URL_GET_VIDEO_INFO = "http://www.youtube.com/get_video_info?&video_id=";
public static CharSequence getYoutubeId(CharSequence youtubeUrl) {
String[] patterns = {
"v=([a-zA-Z0-9_\\-]*)",
"v/([a-zA-Z0-9_\\-]*)",
"youtu.be/([a-zA-Z0-9_\\-]*)",
"vnd.youtube:([a-zA-Z0-9_\\-]*)",
"embed/([a-zA-Z0-9_\\-]*)",
};
for (String pattern : patterns) {
Matcher m = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(youtubeUrl);
if (m.find())
return m.group(1);
}
return null;
}
public static void parse(VideoItem videoItem, String id) throws Exception {
String url = URL_GET_VIDEO_INFO + id;
String infoStr = Client.getInstance().performGet(url);
Matcher m = Pattern.compile("([^&=]*)=([^$&]*)", Pattern.CASE_INSENSITIVE).matcher(infoStr);
String fmtList = null;
String url_encoded_fmt_stream_map = null;
CharSequence title = videoItem.getTitle();
String error = null;
while (m.find()) {
String name = m.group(1);
if (fmtList == null && "fmt_list".equalsIgnoreCase(name))
fmtList = URLDecoder.decode(m.group(2), "UTF-8");
else if (url_encoded_fmt_stream_map == null && "url_encoded_fmt_stream_map".equalsIgnoreCase(name))
url_encoded_fmt_stream_map = URLDecoder.decode(m.group(2), "UTF-8");
else if (title == null && "title".equalsIgnoreCase(name))
title = URLDecoder.decode(m.group(2), "UTF-8");
else if (error == null && "reason".equalsIgnoreCase(name))
error = Html.fromHtml(URLDecoder.decode(m.group(2), "UTF-8")).toString();
if (fmtList != null && url_encoded_fmt_stream_map != null
&& title != null && error != null)
break;
}
if (!TextUtils.isEmpty(error)) {
videoItem.setDefaultBitrate("http://www.youtube.com/watch?v=" + id);
return;
}
videoItem.setTitle(title);
if (fmtList != null && url_encoded_fmt_stream_map != null) {
Matcher fmtMatcher = Pattern.compile("(\\d+)/(\\d+x\\d+)/\\d+/\\d+/\\d+").matcher(fmtList);
String streamStrs[] = url_encoded_fmt_stream_map.split(",");
int fmtInd = 0;
while (fmtMatcher.find()) {
fmtInd++;
if (streamStrs.length == fmtInd)
break;
int ind = indexOf(Integer.parseInt(fmtMatcher.group(1)), YouTubeFMTQuality.supported);
if (ind == -1) continue;
Quality videoFormat = new Quality();
videoFormat.setHeight(YouTubeFMTQuality.supported_titles[ind]);
videoFormat.setFileName(URLDecoder.decode(getUrlFromParams(streamStrs[fmtInd - 1]), "UTF-8"));
videoItem.getQualities().add(videoFormat);
}
}
}
public static int indexOf(int needle, int[] haystack) {
for (int i = 0; i < haystack.length; i++) {
if (haystack[i] == needle) return i;
}
return -1;
}
private static boolean parse2(VideoItem info) throws Exception {
String page = Client.getInstance().performGet(String.format("https://gdata.youtube.com/feeds/api/videos/%s?v=2&alt=json", info.getvId()));
try {
JSONObject jsonObject = new JSONObject(page);
info.setTitle(jsonObject.getJSONObject("entry").getJSONObject("title").getString("$t"));
String url = jsonObject.getJSONObject("entry").getJSONObject("content").getString("src");
if (!url.endsWith("3gp")) {
url = null;
JSONArray jarray = jsonObject.getJSONObject("entry").getJSONObject("media$group").getJSONArray("media$content");
for (int i = 0; i < jarray.length(); i++) {
JSONObject jitem = jarray.getJSONObject(i);
String qualityUrl = jitem.getString("url");
if (!qualityUrl.endsWith("3gp")) continue;
url = qualityUrl;
break;
}
}
if (url == null)
return false;
return true;
} catch (Throwable ex) {
return false;
}
}
private static String getUrlFromParams(CharSequence params) throws UnsupportedEncodingException {
Matcher m = Pattern.compile("(\\w+)=([^&]*)").matcher(params);
String sig = null;
String quality = null;
String url = null;
while (m.find()) {
String name = m.group(1);
if (url == null && "url".equalsIgnoreCase(name))
url = m.group(2);
else if (sig == null && "sig".equalsIgnoreCase(name))
sig = m.group(2);
else if (quality == null && "quality".equalsIgnoreCase(name))
quality = m.group(2);
if (url != null && sig != null && quality != null)
break;
}
return url + "&signature=" + sig;
}
public static class YouTubeFMTQuality {
public static final int GPP3_LOW = 13; //3GPP (MPEG-4 encoded) Low quality
public static final int GPP3_MEDIUM = 17; //3GPP (MPEG-4 encoded) Medium quality
public static final int MP4_NORMAL = 18; //MP4 (H.264 encoded) Normal quality
public static final int MP4_HIGH = 22; //MP4 (H.264 encoded) High quality
public static final int MP4_HIGH1 = 37; //MP4 (H.264 encoded) High quality
public static final CharSequence GPP3_LOW_TITLE = "240p"; //3GPP (MPEG-4 encoded) Low quality
public static final CharSequence GPP3_MEDIUM_TITLE = "360p"; //3GPP (MPEG-4 encoded) Medium quality
public static final CharSequence MP4_NORMAL_TITLE = "480p"; //MP4 (H.264 encoded) Normal quality
public static final CharSequence MP4_HIGH_TITLE = "720p HD"; //MP4 (H.264 encoded) High quality
public static final CharSequence MP4_HIGH1_TITLE = "1080p HD"; //MP4 (H.264 encoded) High quality
public static final int[] supported = {
GPP3_LOW,
GPP3_MEDIUM,
MP4_NORMAL,
MP4_HIGH,
MP4_HIGH1
};
public static final CharSequence[] supported_titles = {
GPP3_LOW_TITLE,
GPP3_MEDIUM_TITLE,
MP4_NORMAL_TITLE,
MP4_HIGH_TITLE,
MP4_HIGH1_TITLE
};
}
}