using RuriLib.LS; using RuriLib.Models; using System; using System.Collections.Generic; namespace RuriLib { /// /// A block that changes the bot status according to some conditions. /// public class BlockKeycheck : BlockBase { private bool banOn4XX = false; /// Whether to set the bot status to BAN if the last HTTP code was of type 4. public bool BanOn4XX { get { return banOn4XX; } set { banOn4XX = value; OnPropertyChanged(); } } private bool banOnToCheck = true; /// Whether to set the bot status as BAN if no keychain was valid. public bool BanOnToCheck { get { return banOnToCheck; } set { banOnToCheck = value; OnPropertyChanged(); } } /// The list of all keychains. public List KeyChains = new List(); /// /// Creates a KeyCheck block. /// public BlockKeycheck() { Label = "KEY CHECK"; } /// public override BlockBase FromLS(string line) { // Trim the line var input = line.Trim(); // Parse the label if (input.StartsWith("#")) Label = LineParser.ParseLabel(ref input); /* * Syntax: * KEYCHECK [BAN4XX? BANTOCHECK?] [KEYCHAIN TYPE [CUSTOMNAME] MODE [KEY "STRING" [CONDITION "STRING"]]*]* * */ while (LineParser.Lookahead(ref input) == TokenType.Boolean) LineParser.SetBool(ref input, this); while (input != "") // Scan for keychains until the end { LineParser.EnsureIdentifier(ref input, "KEYCHAIN"); KeyChain kc = new KeyChain(); kc.Type = (KeyChain.KeychainType)LineParser.ParseEnum(ref input, "Keychain Type", typeof(KeyChain.KeychainType)); if (kc.Type == KeyChain.KeychainType.Custom && LineParser.Lookahead(ref input) == TokenType.Literal) kc.CustomType = LineParser.ParseLiteral(ref input, "Custom Type"); kc.Mode = (KeyChain.KeychainMode)LineParser.ParseEnum(ref input, "Keychain Mode", typeof(KeyChain.KeychainMode)); while (!input.StartsWith("KEYCHAIN") && input != "") // Scan for keys { Key k = new Key(); LineParser.EnsureIdentifier(ref input, "KEY"); var first = LineParser.ParseLiteral(ref input, "Left Term"); // If there is another key/keychain/nothing, the user used the short syntax if (LineParser.CheckIdentifier(ref input, "KEY") || LineParser.CheckIdentifier(ref input, "KEYCHAIN") || input == "") { k.LeftTerm = ""; k.Condition = Condition.Contains; k.RightTerm = first; } // Otherwise use the long syntax else { k.LeftTerm = first; k.Condition = (Condition)LineParser.ParseEnum(ref input, "Condition", typeof(Condition)); if (k.Condition != Condition.Exists && k.Condition != Condition.DoesNotExist) k.RightTerm = LineParser.ParseLiteral(ref input, "Right Term"); } kc.Keys.Add(k); } KeyChains.Add(kc); } return this; } /// public override string ToLS(bool indent = true) { var writer = new BlockWriter(GetType(), indent, Disabled); writer .Label(Label) .Token("KEYCHECK") .Boolean(BanOn4XX, "BanOn4XX") .Boolean(BanOnToCheck, "BanOnToCheck"); foreach(var kc in KeyChains) { writer .Indent(1) .Token("KEYCHAIN") .Token(kc.Type); if (kc.Type == KeyChain.KeychainType.Custom) writer.Literal(kc.CustomType); writer.Token(kc.Mode); foreach(var k in kc.Keys) { if (k.LeftTerm == "" && k.Condition == Condition.Contains) { writer .Indent(2) .Token("KEY") .Literal(k.RightTerm); } else { writer .Indent(2) .Token("KEY") .Literal(k.LeftTerm) .Token(k.Condition); if (k.Condition != Condition.Exists && k.Condition != Condition.DoesNotExist) writer.Literal(k.RightTerm); } } } return writer.ToString(); } /// public override void Process(BotData data) { base.Process(data); if (data.ResponseCode.StartsWith("4") && banOn4XX) { data.Status = BotStatus.BAN; return; } // Check Global Keys foreach (var key in data.GlobalSettings.Proxies.GlobalBanKeys) { if (key != "" && data.ResponseSource.Contains(key)) { data.Status = BotStatus.BAN; return; } } // KEYS WILL BE CHECKED IN THE ORDER IN WHICH THEY APPEAR IN THE LIST, THE LAST KEY HAS ABSOLUTE PRIORITY bool found = false; foreach (var keychain in KeyChains) { if (keychain.CheckKeys(data)) { found = true; switch (keychain.Type) { case KeyChain.KeychainType.Success: data.Status = BotStatus.SUCCESS; break; case KeyChain.KeychainType.Failure: data.Status = BotStatus.FAIL; break; case KeyChain.KeychainType.Ban: data.Status = BotStatus.BAN; break; case KeyChain.KeychainType.Retry: data.Status = BotStatus.RETRY; break; case KeyChain.KeychainType.Custom: data.Status = BotStatus.CUSTOM; data.CustomStatus = keychain.CustomType; break; } } } // If at the end no key was found, set it to ban if (!found && banOnToCheck) data.Status = BotStatus.BAN; } } }