using System; using System.IO; using System.Collections.Generic; using System.Text.RegularExpressions; namespace MinecraftClient.ChatBots { /// /// This bot automatically runs actions when a user sends a message matching a specified rule /// class AutoRespond : ChatBot { private string matchesFile; private List respondRules; /// /// Create a new AutoRespond bot /// /// INI File to load matches from public AutoRespond(string matchesFile) { this.matchesFile = matchesFile; } /// /// Describe a respond rule based on a simple match or a regex /// private class RespondRule { private Regex regex; private string match; private string actionPublic; private string actionPrivate; /// /// Create a respond rule from a regex and a reponse message or command /// /// Regex /// Internal command to run for public messages /// Internal command to run for private messages public RespondRule(Regex regex, string actionPublic, string actionPrivate) { this.regex = regex; this.match = null; this.actionPublic = actionPublic; this.actionPrivate = actionPrivate; } /// /// Create a respond rule from a match string and a reponse message or command /// /// Match string /// Internal command to run for public messages /// Internal command to run for private messages public RespondRule(string match, string actionPublic, string actionPrivate) { this.regex = null; this.match = match; this.actionPublic = actionPublic; this.actionPrivate = actionPrivate; } /// /// Match the respond rule to the specified string and return a message or command to send if a match is detected /// /// Player who have sent the message /// Message to match against the regex or match string /// True if the provided message was sent privately eg with /tell /// Internal command to run as a response to this user, or null if no match has been detected public string Match(string username, string message, bool privateMsg) { if (regex != null) { if (regex.IsMatch(message)) { Match regexMatch = regex.Match(message); string toSend = privateMsg ? actionPrivate : actionPublic; for (int i = regexMatch.Groups.Count - 1; i >= 1; i--) toSend = toSend.Replace("$" + i, regexMatch.Groups[i].Value); toSend = toSend.Replace("$u", username); return toSend; } } else if (!String.IsNullOrEmpty(match)) { if (message.ToLower().Contains(match.ToLower())) { return (privateMsg ? actionPrivate : actionPublic).Replace("$u", username); } } return null; } } /// /// Initialize the AutoRespond bot from the matches file /// public override void Initialize() { if (File.Exists(matchesFile)) { Regex matchRegex = null; string matchString = null; string matchAction = null; string matchActionPrivate = null; respondRules = new List(); foreach (string lineRAW in File.ReadAllLines(matchesFile)) { string line = lineRAW.Split('#')[0].Trim(); if (line.Length > 0) { if (line[0] == '[' && line[line.Length - 1] == ']') { switch (line.Substring(1, line.Length - 2).ToLower()) { case "match": CheckAddMatch(matchRegex, matchString, matchAction, matchActionPrivate); matchRegex = null; matchString = null; matchAction = null; matchActionPrivate = null; break; } } else { string argName = line.Split('=')[0]; if (line.Length > (argName.Length + 1)) { string argValue = line.Substring(argName.Length + 1); switch (argName.ToLower()) { case "regex": matchRegex = new Regex(argValue); break; case "match": matchString = argValue; break; case "action": matchAction = argValue; break; case "actionprivate": matchActionPrivate = argValue; break; } } } } } CheckAddMatch(matchRegex, matchString, matchAction, matchActionPrivate); } else { LogToConsole("File not found: '" + matchesFile + "'"); UnloadBot(); //No need to keep the bot active } } /// /// Create a new respond rule from the provided arguments, only if they are valid: at least one match and one action /// /// Matching regex /// Matching string /// Action if the matching message is public /// Action if the matching message is private private void CheckAddMatch(Regex matchRegex, string matchString, string matchAction, string matchActionPrivate) { if (matchAction != null || matchActionPrivate != null) { if (matchActionPrivate == null) { matchActionPrivate = matchAction; } if (matchRegex != null) { respondRules.Add(new RespondRule(matchRegex, matchAction, matchActionPrivate)); } else if (matchString != null) { respondRules.Add(new RespondRule(matchString, matchAction, matchActionPrivate)); } } } public override void GetText(string text) { //Remove colour codes text = GetVerbatim(text); //Check if this is a valid message string sender = "", message = ""; bool chatMessage = IsChatMessage(text, ref message, ref sender); bool privateMessage = false; if (!chatMessage) privateMessage = IsPrivateMessage(text, ref message, ref sender); //Process only chat messages sent by another user if ((chatMessage || privateMessage) && sender != Settings.Username) { foreach (RespondRule rule in respondRules) { string toPerform = rule.Match(sender, message, privateMessage); if (toPerform != null) { string response = null; LogToConsole(toPerform); PerformInternalCommand(toPerform, ref response); if (!String.IsNullOrEmpty(response)) LogToConsole(response); } } } } } }