mirror of
https://github.com/openbullet/openbullet.git
synced 2023-10-21 07:33:42 -05:00
Parse refactor.
This commit is contained in:
@@ -2,10 +2,12 @@
|
||||
using Extreme.Net;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RuriLib.LS;
|
||||
using RuriLib.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Media;
|
||||
using System.Linq;
|
||||
|
||||
namespace RuriLib
|
||||
{
|
||||
@@ -275,248 +277,33 @@ namespace RuriLib
|
||||
{
|
||||
base.Process(data);
|
||||
|
||||
InsertVariables(data, isCapture, recursive, Parse(data), variableName, prefix, suffix, encodeOutput, createEmpty);
|
||||
}
|
||||
|
||||
private List<string> Parse(BotData data)
|
||||
{
|
||||
var original = ReplaceValues(parseTarget, data);
|
||||
var partial = original;
|
||||
var list = new List<string>();
|
||||
|
||||
// Parse the value
|
||||
switch (Type)
|
||||
{
|
||||
case ParseType.LR:
|
||||
var ls = ReplaceValues(leftString, data);
|
||||
var rs = ReplaceValues(rightString, data);
|
||||
var pFrom = 0;
|
||||
var pTo = 0;
|
||||
|
||||
// No L and R = return full input
|
||||
if (ls == "" && rs == "")
|
||||
{
|
||||
list.Add(original);
|
||||
break;
|
||||
}
|
||||
|
||||
// L or R not present and not empty
|
||||
else if ( ((!partial.Contains(ls) && ls != "") || (!partial.Contains(rs) && rs != "")))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Instead of the mess below, we could simply use Extreme.NET's Substring extensions
|
||||
// return original.Substrings(ls, rs); // Recursive
|
||||
// return original.Substring(ls, rs); // Not recursive
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
if (useRegexLR)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pattern = BuildLRPattern(ls, rs);
|
||||
MatchCollection mc = Regex.Matches(partial, pattern);
|
||||
foreach (Match m in mc)
|
||||
list.Add(m.Value);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
while ((partial.Contains(ls) || ls == "") && (partial.Contains(rs) || rs == ""))
|
||||
{
|
||||
// Search for left delimiter and Calculate offset
|
||||
pFrom = ls == "" ? 0 : partial.IndexOf(ls) + ls.Length;
|
||||
// Move right of offset
|
||||
partial = partial.Substring(pFrom);
|
||||
// Search for right delimiter and Calculate length to parse
|
||||
pTo = rs == "" ? (partial.Length - 1) : partial.IndexOf(rs);
|
||||
// Parse it
|
||||
var parsed = partial.Substring(0, pTo);
|
||||
list.Add(parsed);
|
||||
// Move right of parsed + right
|
||||
partial = partial.Substring(parsed.Length + rs.Length);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Non-recursive
|
||||
else
|
||||
{
|
||||
if (useRegexLR)
|
||||
{
|
||||
var pattern = BuildLRPattern(ls, rs);
|
||||
MatchCollection mc = Regex.Matches(partial, pattern);
|
||||
if (mc.Count > 0) list.Add(mc[0].Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
pFrom = ls == "" ? 0 : partial.IndexOf(ls) + ls.Length;
|
||||
partial = partial.Substring(pFrom);
|
||||
pTo = rs == "" ? partial.Length : partial.IndexOf(rs);
|
||||
list.Add(partial.Substring(0, pTo));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
list = Parse.LR(original, ReplaceValues(leftString, data), ReplaceValues(rightString, data)).ToList();
|
||||
break;
|
||||
|
||||
case ParseType.CSS:
|
||||
|
||||
HtmlParser parser = new HtmlParser();
|
||||
AngleSharp.Html.Dom.IHtmlDocument document = null;
|
||||
try { document = parser.ParseDocument(original); } catch { }
|
||||
|
||||
try
|
||||
{
|
||||
if (recursive)
|
||||
{
|
||||
foreach(var element in document.QuerySelectorAll(ReplaceValues(cssSelector,data)))
|
||||
{
|
||||
switch (ReplaceValues(attributeName, data))
|
||||
{
|
||||
case "innerHTML":
|
||||
list.Add(element.InnerHtml);
|
||||
break;
|
||||
case "outerHTML":
|
||||
list.Add(element.OuterHtml);
|
||||
break;
|
||||
default:
|
||||
foreach(var attr in element.Attributes)
|
||||
{
|
||||
if(attr.Name == ReplaceValues(attributeName,data))
|
||||
{
|
||||
list.Add(attr.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ReplaceValues(attributeName, data))
|
||||
{
|
||||
case "innerHTML":
|
||||
list.Add(document.QuerySelectorAll(ReplaceValues(cssSelector, data))[cssElementIndex].InnerHtml);
|
||||
break;
|
||||
|
||||
case "outerHTML":
|
||||
list.Add(document.QuerySelectorAll(ReplaceValues(cssSelector, data))[cssElementIndex].OuterHtml);
|
||||
break;
|
||||
|
||||
default:
|
||||
foreach (var attr in document.QuerySelectorAll(ReplaceValues(cssSelector, data))[cssElementIndex].Attributes)
|
||||
{
|
||||
if (attr.Name == ReplaceValues(attributeName, data))
|
||||
{
|
||||
list.Add(attr.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
list = Parse.CSS(original, ReplaceValues(cssSelector, data), ReplaceValues(attributeName, data), cssElementIndex, recursive).ToList();
|
||||
break;
|
||||
|
||||
case ParseType.JSON:
|
||||
if (JTokenParsing)
|
||||
{
|
||||
if (original.Trim().StartsWith("["))
|
||||
{
|
||||
JArray json = JArray.Parse(original);
|
||||
var jsonlist = json.SelectTokens(jsonField, false);
|
||||
foreach (var j in jsonlist)
|
||||
list.Add(j.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
JObject json = JObject.Parse(original);
|
||||
var jsonlist = json.SelectTokens(jsonField, false);
|
||||
foreach (var j in jsonlist)
|
||||
list.Add(j.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var jsonlist = new List<KeyValuePair<string, string>>();
|
||||
parseJSON("", original, jsonlist);
|
||||
foreach (var j in jsonlist)
|
||||
if (j.Key == ReplaceValues(jsonField, data))
|
||||
list.Add(j.Value);
|
||||
}
|
||||
|
||||
list = Parse.JSON(original, ReplaceValues(jsonField, data), recursive, jTokenParsing).ToList();
|
||||
break;
|
||||
|
||||
case ParseType.XPATH:
|
||||
|
||||
// NOT IMPLEMENTED YET
|
||||
break;
|
||||
throw new NotImplementedException("XPATH parsing is not implemented yet");
|
||||
|
||||
case ParseType.REGEX:
|
||||
try
|
||||
{
|
||||
var matches = Regex.Matches(partial, ReplaceValues(regexString, data));
|
||||
foreach(Match match in matches)
|
||||
{
|
||||
var output = ReplaceValues(regexOutput, data);
|
||||
for (var i = 0; i < match.Groups.Count; i++) output = output.Replace("[" + i + "]", match.Groups[i].Value);
|
||||
list.Add(output);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
list = Parse.REGEX(original, ReplaceValues(regexString, data), ReplaceValues(regexOutput, data), recursive).ToList();
|
||||
break;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private string BuildLRPattern(string ls, string rs)
|
||||
{
|
||||
var left = string.IsNullOrEmpty(ls) ? "^" : Regex.Escape(ls); // Empty LEFT = start of the line
|
||||
var right = string.IsNullOrEmpty(rs) ? "$" : Regex.Escape(rs); // Empty RIGHT = end of the line
|
||||
return "(?<=" + left + ").+?(?=" + right + ")";
|
||||
}
|
||||
|
||||
private static void parseJSON(string A, string B, List<KeyValuePair<string, string>> jsonlist)
|
||||
{
|
||||
jsonlist.Add(new KeyValuePair<string, string>(A, B));
|
||||
|
||||
if (B.StartsWith("["))
|
||||
{
|
||||
JArray arr = null;
|
||||
try { arr = JArray.Parse(B); } catch { return; }
|
||||
|
||||
foreach (var i in arr.Children())
|
||||
parseJSON("", i.ToString(), jsonlist);
|
||||
}
|
||||
|
||||
if (B.Contains("{"))
|
||||
{
|
||||
JObject obj = null;
|
||||
try { obj = JObject.Parse(B); } catch { return; }
|
||||
|
||||
foreach (var o in obj)
|
||||
parseJSON(o.Key, o.Value.ToString(), jsonlist);
|
||||
}
|
||||
}
|
||||
|
||||
private string cleanString(string inputString)
|
||||
{
|
||||
return Regex.Replace(inputString, "<br>", "").Trim();
|
||||
InsertVariables(data, isCapture, recursive, list, variableName, prefix, suffix, encodeOutput, createEmpty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,6 +262,7 @@
|
||||
<Compile Include="Runner\RunnerBotViewModel.cs" />
|
||||
<Compile Include="Runner\RunnerViewModel.cs" />
|
||||
<Compile Include="TypeSwitch.cs" />
|
||||
<Compile Include="Utils\Parse.cs" />
|
||||
<Compile Include="ViewModels\ConfigViewModel.cs" />
|
||||
<Compile Include="Models\CProxy.cs" />
|
||||
<Compile Include="Models\LogEntry.cs" />
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using AngleSharp.Html.Parser;
|
||||
using Extreme.Net;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace RuriLib.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides parsing methods.
|
||||
/// </summary>
|
||||
public static class Parse
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses one or more strings from another string based on the left and right delimiters.
|
||||
/// </summary>
|
||||
/// <param name="input">The string to parse from</param>
|
||||
/// <param name="left">The left string delimiter</param>
|
||||
/// <param name="right">The right string delimiter</param>
|
||||
/// <param name="recursive">Whether to find all the occurrences</param>
|
||||
/// <param name="useRegex">Whether to automatically build a Regex pattern and use Regex matching</param>
|
||||
/// <returns>The parsed strings.</returns>
|
||||
public static IEnumerable<string> LR(string input, string left, string right, bool recursive = false, bool useRegex = false)
|
||||
{
|
||||
// No L and R = return full input
|
||||
if (left == "" && right == "")
|
||||
{
|
||||
return new string[] { input };
|
||||
}
|
||||
|
||||
// L or R not present and not empty = return nothing
|
||||
else if (((left != "" && !input.Contains(left)) || (right != "" && !input.Contains(right))))
|
||||
{
|
||||
return new string[] { };
|
||||
}
|
||||
|
||||
var partial = input;
|
||||
var pFrom = 0;
|
||||
var pTo = 0;
|
||||
var list = new List<string>();
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
if (useRegex)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pattern = BuildLRPattern(left, right);
|
||||
MatchCollection mc = Regex.Matches(partial, pattern);
|
||||
foreach (Match m in mc)
|
||||
list.Add(m.Value);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
while (left == "" || (partial.Contains(left)) && (right == "" || partial.Contains(right)))
|
||||
{
|
||||
// Search for left delimiter and Calculate offset
|
||||
pFrom = left == "" ? 0 : partial.IndexOf(left) + left.Length;
|
||||
// Move right of offset
|
||||
partial = partial.Substring(pFrom);
|
||||
// Search for right delimiter and Calculate length to parse
|
||||
pTo = right == "" ? (partial.Length - 1) : partial.IndexOf(right);
|
||||
// Parse it
|
||||
var parsed = partial.Substring(0, pTo);
|
||||
list.Add(parsed);
|
||||
// Move right of parsed + right
|
||||
partial = partial.Substring(parsed.Length + right.Length);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Non-recursive
|
||||
else
|
||||
{
|
||||
if (useRegex)
|
||||
{
|
||||
var pattern = BuildLRPattern(left, right);
|
||||
MatchCollection mc = Regex.Matches(partial, pattern);
|
||||
if (mc.Count > 0) list.Add(mc[0].Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
pFrom = left == "" ? 0 : partial.IndexOf(left) + left.Length;
|
||||
partial = partial.Substring(pFrom);
|
||||
pTo = right == "" ? partial.Length : partial.IndexOf(right);
|
||||
list.Add(partial.Substring(0, pTo));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses an attribute's value from one or more elements of an HTML page.
|
||||
/// </summary>
|
||||
/// <param name="input">The HTML page</param>
|
||||
/// <param name="selector">The CSS Selector that targets the desired elements</param>
|
||||
/// <param name="attribute">The attribute for which you want to parse the value</param>
|
||||
/// <param name="index">The index of the element to parse among all the ones selected (if not recursive)</param>
|
||||
/// <param name="recursive">Whether to parse from all the elements that match the selector</param>
|
||||
/// <returns>The attribute value(s).</returns>
|
||||
public static IEnumerable<string> CSS(string input, string selector, string attribute, int index = 0, bool recursive = false)
|
||||
{
|
||||
HtmlParser parser = new HtmlParser();
|
||||
AngleSharp.Html.Dom.IHtmlDocument document = null;
|
||||
document = parser.ParseDocument(input);
|
||||
var list = new List<string>();
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
foreach (var element in document.QuerySelectorAll(selector))
|
||||
{
|
||||
switch (attribute)
|
||||
{
|
||||
case "innerHTML":
|
||||
list.Add(element.InnerHtml);
|
||||
break;
|
||||
|
||||
case "outerHTML":
|
||||
list.Add(element.OuterHtml);
|
||||
break;
|
||||
|
||||
default:
|
||||
foreach (var attr in element.Attributes)
|
||||
{
|
||||
if (attr.Name == attribute)
|
||||
{
|
||||
list.Add(attr.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (attribute)
|
||||
{
|
||||
case "innerHTML":
|
||||
list.Add(document.QuerySelectorAll(selector)[index].InnerHtml);
|
||||
break;
|
||||
|
||||
case "outerHTML":
|
||||
list.Add(document.QuerySelectorAll(selector)[index].OuterHtml);
|
||||
break;
|
||||
|
||||
default:
|
||||
foreach (var attr in document.QuerySelectorAll(selector)[index].Attributes)
|
||||
{
|
||||
if (attr.Name == attribute)
|
||||
{
|
||||
list.Add(attr.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a JSON object or array.
|
||||
/// </summary>
|
||||
/// <param name="input">The serialized JSON object or array</param>
|
||||
/// <param name="field">The field for which you want to parse the value</param>
|
||||
/// <param name="recursive">Whether to return all the fields matching the name or JToken</param>
|
||||
/// <param name="useJToken">Whether to match via JToken</param>
|
||||
/// <returns>The value(s) of the parsed field(s).</returns>
|
||||
public static IEnumerable<string> JSON(string input, string field, bool recursive = false, bool useJToken = false)
|
||||
{
|
||||
var list = new List<string>();
|
||||
|
||||
if (useJToken)
|
||||
{
|
||||
if (recursive)
|
||||
{
|
||||
if (input.Trim().StartsWith("["))
|
||||
{
|
||||
JArray json = JArray.Parse(input);
|
||||
var jsonlist = json.SelectTokens(field, false);
|
||||
foreach (var j in jsonlist)
|
||||
list.Add(j.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
JObject json = JObject.Parse(input);
|
||||
var jsonlist = json.SelectTokens(field, false);
|
||||
foreach (var j in jsonlist)
|
||||
list.Add(j.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (input.Trim().StartsWith("["))
|
||||
{
|
||||
JArray json = JArray.Parse(input);
|
||||
list.Add(json.SelectToken(field, false).ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
JObject json = JObject.Parse(input);
|
||||
list.Add(json.SelectTokens(field, false).ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var jsonlist = new List<KeyValuePair<string, string>>();
|
||||
parseJSON("", input, jsonlist);
|
||||
foreach (var j in jsonlist)
|
||||
if (j.Key == field)
|
||||
list.Add(j.Value);
|
||||
|
||||
if (!recursive && list.Count > 1) list = new List<string>() { list.First() };
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a string via a Regex pattern containing Groups, then returns them according to an output format.
|
||||
/// </summary>
|
||||
/// <param name="input">The string to parse</param>
|
||||
/// <param name="pattern">The Regex pattern containing groups</param>
|
||||
/// <param name="output">The output format string, for which [0] will be replaced with the full match, [1] with the first group etc.</param>
|
||||
/// <param name="recursive">Whether to make multiple matches</param>
|
||||
/// <returns>The parsed string(s).</returns>
|
||||
public static IEnumerable<string> REGEX(string input, string pattern, string output, bool recursive = false)
|
||||
{
|
||||
var list = new List<string>();
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
var matches = Regex.Matches(input, pattern);
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
var final = output;
|
||||
for (var i = 0; i < match.Groups.Count; i++) final = final.Replace("[" + i + "]", match.Groups[i].Value);
|
||||
list.Add(final);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var match = Regex.Match(input, pattern);
|
||||
if (match.Success)
|
||||
{
|
||||
var final = output;
|
||||
for (var i = 0; i < match.Groups.Count; i++) final = final.Replace("[" + i + "]", match.Groups[i].Value);
|
||||
list.Add(final);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static string BuildLRPattern(string ls, string rs)
|
||||
{
|
||||
var left = string.IsNullOrEmpty(ls) ? "^" : Regex.Escape(ls); // Empty LEFT = start of the line
|
||||
var right = string.IsNullOrEmpty(rs) ? "$" : Regex.Escape(rs); // Empty RIGHT = end of the line
|
||||
return "(?<=" + left + ").+?(?=" + right + ")";
|
||||
}
|
||||
|
||||
private static void parseJSON(string A, string B, List<KeyValuePair<string, string>> jsonlist)
|
||||
{
|
||||
jsonlist.Add(new KeyValuePair<string, string>(A, B));
|
||||
|
||||
if (B.StartsWith("["))
|
||||
{
|
||||
JArray arr = null;
|
||||
try { arr = JArray.Parse(B); } catch { return; }
|
||||
|
||||
foreach (var i in arr.Children())
|
||||
parseJSON("", i.ToString(), jsonlist);
|
||||
}
|
||||
|
||||
if (B.Contains("{"))
|
||||
{
|
||||
JObject obj = null;
|
||||
try { obj = JObject.Parse(B); } catch { return; }
|
||||
|
||||
foreach (var o in obj)
|
||||
parseJSON(o.Key, o.Value.ToString(), jsonlist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user