public async Task <IList <RobloxClass> > DownloadApiDump() { var client = new CookieWebClient(); client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"); var response = await client.DownloadStringTaskAsync(ROBLOX_RAW_API_DUMP_URL); if (response.Contains("setCookie")) { MatchCollection cookieMatches = Regex.Matches(response, @"setCookie\('(.+)', '(.+)', (.+)\)"); if (cookieMatches.Count > 0) { var name = cookieMatches[0].Groups[1].Value; var value = cookieMatches[0].Groups[2].Value; var expireDays = int.Parse(cookieMatches[0].Groups[3].Value); var cookie = new Cookie(name, value); cookie.Domain = "wiki.roblox.com"; cookie.Expires = DateTime.Now.AddDays(expireDays); client.CookieContainer.Add(cookie); } else { throw new Exception("Can't parse cookie"); } } response = await client.DownloadStringTaskAsync(ROBLOX_RAW_API_DUMP_URL); MatchCollection classMatches = Regex.Matches(response, @"Class (\w+)( : (\w+))?"); IList <RobloxClass> robloxClasses = new List <RobloxClass>(); foreach (Match match in classMatches) { string className = match.Groups[1].Value; string superClassName = match.Groups[3].Value; robloxClasses.Add(new RobloxClass() { ClassName = className, SuperClass = superClassName }); } foreach (RobloxClass robloxClass in robloxClasses) { var attributeRegex = OrderedAttributes.Aggregate("", (seed, acc) => seed += $@"(\[{acc}\])?\s?"); MatchCollection propertyMatches = Regex.Matches(response, $@"Property (\w+) { robloxClass.ClassName }\.(\w+)\s?{ attributeRegex }"); foreach (Match match in propertyMatches) { string dataType = match.Groups[1].Value; string propertyName = match.Groups[2].Value; var robloxProperty = new RobloxProperty() { Name = propertyName, DataType = dataType, Deprecated = !String.IsNullOrEmpty(match.Groups[3].Value), Hidden = !String.IsNullOrEmpty(match.Groups[4].Value), ReadOnly = !String.IsNullOrEmpty(match.Groups[5].Value), WriteOnly = !String.IsNullOrEmpty(match.Groups[6].Value), Backend = !String.IsNullOrEmpty(match.Groups[7].Value), RobloxPlaceSecurity = !String.IsNullOrEmpty(match.Groups[8].Value), LocalUserSecurity = !String.IsNullOrEmpty(match.Groups[9].Value), WritePlayerSecurity = !String.IsNullOrEmpty(match.Groups[10].Value), RobloxScriptSecurity = !String.IsNullOrEmpty(match.Groups[11].Value), RobloxSecurity = !String.IsNullOrEmpty(match.Groups[12].Value), PluginSecurity = !String.IsNullOrEmpty(match.Groups[13].Value) }; if (robloxProperty.RobloxPlaceSecurity) { robloxProperty.IdentityLevels = new List <int>() { 3, 4, 5, 6, 7 }; } else if (robloxProperty.PluginSecurity) { robloxProperty.IdentityLevels = new List <int>() { 3, 4, 5, 6, 7 }; } else if (robloxProperty.LocalUserSecurity) { robloxProperty.IdentityLevels = new List <int>() { 4, 5, 7 }; } else if (robloxProperty.RobloxScriptSecurity) { robloxProperty.IdentityLevels = new List <int>() { 4, 7 }; } else { robloxProperty.IdentityLevels = new List <int>() { 1, 2, 3, 4, 5, 6, 7 }; } robloxClass.Properties.Add(robloxProperty); } } return(robloxClasses); }
internal static void Parse(Scope Sc, string varVal, string propName, string[] classes = null) { if (PropertyCallbacks == null) { AddCallbacks(); } //Properties can be defined within a WidgetScope. if (Sc.ID == "Widget") { var WScope = Sc as WidgetScope; if (WScope != null) { RSSInstance Instance = WScope.Instance; RobloxProperty Prop; if (!Instance.HasProperty(propName, out Prop)) { throw new ParserException($"The Instance {Instance.Name} does not have the property {propName}"); } //Check to make sure the value passed isn't a variable. varVal = FetchVarVal(Sc, varVal); //Check for a callback. PropertyProcessCallback Callback; bool isValidFunc = PropertyCallbacks.TryGetValue(Prop.ValueType, out Callback); if (!isValidFunc) { /////ENUM CALLBACK RobloxEnum Enum; if (!RobloxEnum.Enums.TryGetValue(Prop.ValueType, out Enum)) { throw new ParserException($"Failed to find the correct datatype for {Prop.Name} for Instance {Instance.Name}"); } if (!Enum.HasEnumItem(varVal)) { throw new ParserException($"The Enunm {Enum.Name} does not have the item {varVal}"); } Instance.AddProperty(new RSSProperty(Prop.Name, Prop.ValueType, new string[] { RSS.RobloxJSONParser.Writer.JSONWriter.Quotify(varVal) })); } else { Instance.AddProperty(new RSSProperty(Prop.Name, Prop.ValueType, Callback(varVal, WScope))); } } } else if (Sc.ID == "StyleId") { RobloxProperty Prop = null; foreach (var Name in classes) { RobloxInstance Inst = RobloxParser.RobloxHierachy[Name]; if (!Inst.GetProperty(propName, out Prop)) { throw new ParserException($"The ClassName {Name} in the style {((StyleScope)Sc.Parent).StyleName} does not have the property you are trying to set: {propName}"); } } PropertyProcessCallback Callback; bool isValidFunc = PropertyCallbacks.TryGetValue(Prop.ValueType, out Callback); if (isValidFunc) { ((StyleIdScope)Sc).AddProperty(new RSSProperty(Prop.Name, Prop.ValueType, Callback(varVal, Sc))); } } }
internal bool HasProperty(string propName, out RobloxProperty Prop) { return(RobloxParser.RobloxHierachy[ClassName].GetProperty(propName, out Prop)); }