/// <summary> /// Create a JSONObject by parsing string data /// </summary> /// <param name="val">The string to be parsed</param> /// <param name="maxDepth">The maximum depth for the parser to search. Set this to to 1 for the first level, /// 2 for the first 2 levels, etc. It defaults to -2 because -1 is the depth value that is parsed (see below)</param> /// <param name="storeExcessLevels">Whether to store levels beyond maxDepth in baked JSONObjects</param> /// <param name="strict">Whether to be strict in the parsing. For example, non-strict parsing will successfully /// parse "a string" into a string-type </param> /// <returns></returns> public static VideoHostingJson Create(string val, int maxDepth = -2, bool storeExcessLevels = false, bool strict = false) { VideoHostingJson obj = Create(); obj.Parse(val, maxDepth, storeExcessLevels, strict); return(obj); }
public void AddField(string name, VideoHostingJson obj) { if (obj) //Don't do anything if the object is null { if (type != Type.OBJECT) { if (keys == null) { keys = new List <string>(); } if (type == Type.ARRAY) { for (int i = 0; i < list.Count; i++) { keys.Add(i + ""); } } else if (list == null) { list = new List <VideoHostingJson>(); } type = Type.OBJECT; //Congratulations, son, you're an OBJECT now } keys.Add(name); list.Add(obj); } }
public static VideoHostingJson Create(AddJSONContents content) { VideoHostingJson obj = Create(); content.Invoke(obj); return(obj); }
public static VideoHostingJson CreateBakedObject(string val) { VideoHostingJson bakedObject = Create(); bakedObject.type = Type.BAKED; bakedObject.str = val; return(bakedObject); }
public static VideoHostingJson CreateStringObject(string val) { VideoHostingJson obj = Create(); obj.type = Type.STRING; obj.str = val; return(obj); }
public static VideoHostingJson Create(float val) { VideoHostingJson obj = Create(); obj.type = Type.NUMBER; obj.n = val; return(obj); }
public static VideoHostingJson Create(bool val) { VideoHostingJson obj = Create(); obj.type = Type.BOOL; obj.b = val; return(obj); }
private static string GetHtml5PlayerVersion(VideoHostingJson json) { var regex = new Regex(@"player(.+?).js"); string js = Regex.Unescape(json["assets"]["js"].str); return(regex.Match(js).Result("$1")); }
public VideoHostingInfo[] Parse(VideoHostingJson data) { string videoTitle = GetVideoTitle(data); IEnumerable <ExtractionInfo> downloadUrls = ExtractDownloadUrls(data); IEnumerable <VideoHostingInfo> infos = GetVideoInfos(downloadUrls, videoTitle).ToList(); return((VideoHostingInfo[])infos); }
public void SetField(string name, VideoHostingJson obj) { if (HasField(name)) { list.Remove(this[name]); keys.Remove(name); } AddField(name, obj); }
public static VideoHostingJson Create(long val) { VideoHostingJson obj = Create(); obj.type = Type.NUMBER; obj.n = val; obj.useInt = true; obj.i = val; return(obj); }
public void Absorb(VideoHostingJson obj) { list.AddRange(obj.list); keys.AddRange(obj.keys); str = obj.str; n = obj.n; useInt = obj.useInt; i = obj.i; b = obj.b; type = obj.type; }
public IEnumerator Parse(string url, Action <string, VideoHostingInfo[]> completedCallback, Action <string> errorCallback) { var headers = new Dictionary <string, string>(); headers.Add("User-Agent", USER_AGENT); var www = new WWW(url, null, headers); yield return(www); if (!string.IsNullOrEmpty(www.error)) { if (errorCallback != null) { errorCallback("YoutubeVideoParser error: " + www.error); } yield break; } try { string pageSource = www.text; if (IsVideoUnavailable(pageSource)) { Debug.Log("YoutubeVideoParser error: video is unavailable"); } var dataRegex = new Regex(@"ytplayer\.config\s*=\s*(\{.+?\});", RegexOptions.Multiline); string extractedJson = dataRegex.Match(pageSource).Result("$1"); var data = new VideoHostingJson(extractedJson); string videoTitle = GetVideoTitle(data); IEnumerable <ExtractionInfo> downloadUrls = ExtractDownloadUrls(data); IEnumerable <VideoHostingInfo> videoInfos = GetVideoInfos(downloadUrls, videoTitle).ToList(); string htmlPlayerVersion = GetHtml5PlayerVersion(data); foreach (VideoHostingInfo info in videoInfos) { info.HtmlPlayerVersion = htmlPlayerVersion; } if (completedCallback != null) { completedCallback(url, videoInfos.ToArray()); } } catch (Exception e) { if (errorCallback != null) { errorCallback("YoutubeVideoParser error: maybe your youtube link is incorrect or not supported - " + e.ToString()); } } }
public void Add(VideoHostingJson obj) { if (obj) //Don't do anything if the object is null { if (type != Type.ARRAY) { type = Type.ARRAY; //Congratulations, son, you're an ARRAY now if (list == null) { list = new List <VideoHostingJson>(); } } list.Add(obj); } }
public static VideoHostingJson Create(Dictionary <string, string> dic) { VideoHostingJson obj = Create(); obj.type = Type.OBJECT; obj.keys = new List <string>(); obj.list = new List <VideoHostingJson>(); //Not sure if it's worth removing the foreach here foreach (KeyValuePair <string, string> kvp in dic) { obj.keys.Add(kvp.Key); obj.list.Add(CreateStringObject(kvp.Value)); } return(obj); }
private static string GetAdaptiveStreamMap(VideoHostingJson json) { string streamMap = null; if (json["args"].keys.Contains("adaptive_fmts")) { streamMap = Regex.Unescape(json["args"]["adaptive_fmts"].str); } if (streamMap == null) { streamMap = Regex.Unescape(json["args"]["url_encoded_fmt_stream_map"].str); } return(streamMap.ToString()); }
private static string GetStreamMap(VideoHostingJson json) { string streamMap = null; if (json["args"].keys.Contains("url_encoded_fmt_stream_map")) { streamMap = Regex.Unescape(json["args"]["url_encoded_fmt_stream_map"].str); } string streamMapString = streamMap == null ? null : streamMap.ToString(); if (streamMapString == null || streamMapString.Contains("been+removed")) { throw new Exception("Video is removed or has an age restriction."); } return(streamMapString); }
public static VideoHostingJson Create(Type t) { VideoHostingJson obj = Create(); obj.type = t; switch (t) { case Type.ARRAY: obj.list = new List <VideoHostingJson>(); break; case Type.OBJECT: obj.list = new List <VideoHostingJson>(); obj.keys = new List <string>(); break; } return(obj); }
private static IEnumerable <ExtractionInfo> ExtractDownloadUrls(VideoHostingJson json) { string[] splitByUrls = (GetStreamMap(json) + ',' + GetAdaptiveStreamMap(json)).Split(','); foreach (string s in splitByUrls) { IDictionary <string, string> queries = VideoHostingHelper.ParseQueryString(s); string url; bool requiresDecryption = false; if (queries.ContainsKey("s") || queries.ContainsKey("sig")) { requiresDecryption = queries.ContainsKey("s"); string signature = queries.ContainsKey("s") ? queries["s"] : queries["sig"]; url = string.Format("{0}&{1}={2}", queries["url"], SIGNATURE_QUERY, signature); string fallbackHost = queries.ContainsKey("fallback_host") ? "&fallback_host=" + queries["fallback_host"] : String.Empty; url += fallbackHost; } else { url = queries["url"]; } url = VideoHostingHelper.UrlDecode(url); IDictionary <string, string> parameters = VideoHostingHelper.ParseQueryString(url); if (!parameters.ContainsKey(RATE_BYPASS_FLAG)) { url += string.Format("&{0}={1}", RATE_BYPASS_FLAG, "yes"); } yield return(new ExtractionInfo { RequiresDecryption = requiresDecryption, Uri = new Uri(url) }); } }
public Dictionary <string, string> ToDictionary() { if (type == Type.OBJECT) { Dictionary <string, string> result = new Dictionary <string, string>(); for (int i = 0; i < list.Count; i++) { VideoHostingJson val = list[i]; switch (val.type) { case Type.STRING: result.Add(keys[i], val.str); break; case Type.NUMBER: result.Add(keys[i], val.n + ""); break; case Type.BOOL: result.Add(keys[i], val.b + ""); break; default: #if UNITY_2 || UNITY_3 || UNITY_4 || UNITY_5 Debug.LogWarning #else Debug.WriteLine #endif ("Omitting object: " + keys[i] + " in dictionary conversion"); break; } } return(result); } #if UNITY_2 || UNITY_3 || UNITY_4 || UNITY_5 Debug.Log #else Debug.WriteLine #endif ("Tried to turn non-Object JSONObject into a dictionary"); return(null); }
/// <summary> /// Merge object right into left recursively /// </summary> /// <param name="left">The left (base) object</param> /// <param name="right">The right (new) object</param> static void MergeRecur(VideoHostingJson left, VideoHostingJson right) { if (left.type == Type.NULL) { left.Absorb(right); } else if (left.type == Type.OBJECT && right.type == Type.OBJECT) { for (int i = 0; i < right.list.Count; i++) { string key = right.keys[i]; if (right[i].isContainer) { if (left.HasField(key)) { MergeRecur(left[key], right[i]); } else { left.AddField(key, right[i]); } } else { if (left.HasField(key)) { left.SetField(key, right[i]); } else { left.AddField(key, right[i]); } } } } else if (left.type == Type.ARRAY && right.type == Type.ARRAY) { if (right.Count > left.Count) { #if UNITY_2 || UNITY_3 || UNITY_4 || UNITY_5 Debug.LogError #else Debug.WriteLine #endif ("Cannot merge arrays when right object has more elements"); return; } for (int i = 0; i < right.list.Count; i++) { if (left[i].type == right[i].type) //Only overwrite with the same type { if (left[i].isContainer) { MergeRecur(left[i], right[i]); } else { left[i] = right[i]; } } } } }
public VideoHostingJsonEnumer(VideoHostingJson jsonObject) { Debug.Assert(jsonObject.isContainer); //must be an array or object to itterate _jobj = jsonObject; }
private string GetVideoTitle(VideoHostingJson json) { string title = Regex.Unescape(json["args"]["title"].str); return(title == null ? string.Empty : title); }
/* * The Merge function is experimental. Use at your own risk. */ public void Merge(VideoHostingJson obj) { MergeRecur(this, obj); }
//TODO: Refactor Stringify functions to share core logic /* * I know, I know, this is really bad form. It turns out that there is a * significant amount of garbage created when calling as a coroutine, so this * method is duplicated. Hopefully there won't be too many future changes, but * I would still like a more elegant way to optionaly yield */ void Stringify(int depth, StringBuilder builder, bool pretty = false) //Convert the JSONObject into a string //Profiler.BeginSample("JSONprint"); { if (depth++ > MAX_DEPTH) { #if UNITY_2 || UNITY_3 || UNITY_4 || UNITY_5 Debug.Log #else Debug.WriteLine #endif ("reached max depth!"); return; } switch (type) { case Type.BAKED: builder.Append(str); break; case Type.STRING: builder.AppendFormat("\"{0}\"", str); break; case Type.NUMBER: if (useInt) { builder.Append(i.ToString()); } else { #if USEFLOAT if (float.IsInfinity(n)) { builder.Append(INFINITY); } else if (float.IsNegativeInfinity(n)) { builder.Append(NEGINFINITY); } else if (float.IsNaN(n)) { builder.Append(NaN); } #else if (double.IsInfinity(n)) { builder.Append(INFINITY); } else if (double.IsNegativeInfinity(n)) { builder.Append(NEGINFINITY); } else if (double.IsNaN(n)) { builder.Append(NaN); } #endif else { builder.Append(n.ToString()); } } break; case Type.OBJECT: builder.Append("{"); if (list.Count > 0) { #if (PRETTY) //for a bit more readability, comment the define above to disable system-wide if (pretty) { builder.Append("\n"); } #endif for (int i = 0; i < list.Count; i++) { string key = keys[i]; VideoHostingJson obj = list[i]; if (obj) { #if (PRETTY) if (pretty) { for (int j = 0; j < depth; j++) { builder.Append("\t"); //for a bit more readability } } #endif builder.AppendFormat("\"{0}\":", key); obj.Stringify(depth, builder, pretty); builder.Append(","); #if (PRETTY) if (pretty) { builder.Append("\n"); } #endif } } #if (PRETTY) if (pretty) { builder.Length -= 2; } else #endif builder.Length--; } #if (PRETTY) if (pretty && list.Count > 0) { builder.Append("\n"); for (int j = 0; j < depth - 1; j++) { builder.Append("\t"); //for a bit more readability } } #endif builder.Append("}"); break; case Type.ARRAY: builder.Append("["); if (list.Count > 0) { #if (PRETTY) if (pretty) { builder.Append("\n"); //for a bit more readability } #endif for (int i = 0; i < list.Count; i++) { if (list[i]) { #if (PRETTY) if (pretty) { for (int j = 0; j < depth; j++) { builder.Append("\t"); //for a bit more readability } } #endif list[i].Stringify(depth, builder, pretty); builder.Append(","); #if (PRETTY) if (pretty) { builder.Append("\n"); //for a bit more readability } #endif } } #if (PRETTY) if (pretty) { builder.Length -= 2; } else #endif builder.Length--; } #if (PRETTY) if (pretty && list.Count > 0) { builder.Append("\n"); for (int j = 0; j < depth - 1; j++) { builder.Append("\t"); //for a bit more readability } } #endif builder.Append("]"); break; case Type.BOOL: if (b) { builder.Append("true"); } else { builder.Append("false"); } break; case Type.NULL: builder.Append("null"); break; } //Profiler.EndSample(); }