mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Add regex settings for parsing chat messages
Allows user-defined regexes to be used instead of built-in chat detection routines for matching messages on server using a non-standard chat format. Built-in detection routines can be disabled using a single setting, based on a contribution by ZizzyDizzyMC.
This commit is contained in:
parent
29975da627
commit
5038c3d475
3 changed files with 211 additions and 108 deletions
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace MinecraftClient
|
namespace MinecraftClient
|
||||||
{
|
{
|
||||||
|
|
@ -142,11 +143,11 @@ namespace MinecraftClient
|
||||||
|
|
||||||
protected static bool IsValidName(string username)
|
protected static bool IsValidName(string username)
|
||||||
{
|
{
|
||||||
if ( String.IsNullOrEmpty(username) )
|
if (String.IsNullOrEmpty(username))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach ( char c in username )
|
foreach (char c in username)
|
||||||
if ( !((c >= 'a' && c <= 'z')
|
if (!((c >= 'a' && c <= 'z')
|
||||||
|| (c >= 'A' && c <= 'Z')
|
|| (c >= 'A' && c <= 'Z')
|
||||||
|| (c >= '0' && c <= '9')
|
|| (c >= '0' && c <= '9')
|
||||||
|| c == '_') )
|
|| c == '_') )
|
||||||
|
|
@ -165,10 +166,15 @@ namespace MinecraftClient
|
||||||
|
|
||||||
protected static bool IsPrivateMessage(string text, ref string message, ref string sender)
|
protected static bool IsPrivateMessage(string text, ref string message, ref string sender)
|
||||||
{
|
{
|
||||||
text = GetVerbatim(text);
|
if (String.IsNullOrEmpty(text))
|
||||||
if (text == "") { return false; }
|
return false;
|
||||||
string[] tmp = text.Split(' ');
|
|
||||||
|
|
||||||
|
text = GetVerbatim(text);
|
||||||
|
|
||||||
|
//Built-in detection routine for private messages
|
||||||
|
if (Settings.ChatFormat_Builtins)
|
||||||
|
{
|
||||||
|
string[] tmp = text.Split(' ');
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//Detect vanilla /tell messages
|
//Detect vanilla /tell messages
|
||||||
|
|
@ -243,7 +249,22 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
catch (IndexOutOfRangeException) { return false; }
|
catch (IndexOutOfRangeException) { /* Not an expected chat format */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
//User-defined regex for private chat messages
|
||||||
|
if (Settings.ChatFormat_Private != null)
|
||||||
|
{
|
||||||
|
Match regexMatch = Settings.ChatFormat_Private.Match(text);
|
||||||
|
if (regexMatch.Success && regexMatch.Groups.Count >= 3)
|
||||||
|
{
|
||||||
|
sender = regexMatch.Groups[1].Value;
|
||||||
|
message = regexMatch.Groups[2].Value;
|
||||||
|
return IsValidName(sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -256,17 +277,22 @@ namespace MinecraftClient
|
||||||
|
|
||||||
protected static bool IsChatMessage(string text, ref string message, ref string sender)
|
protected static bool IsChatMessage(string text, ref string message, ref string sender)
|
||||||
{
|
{
|
||||||
|
if (String.IsNullOrEmpty(text))
|
||||||
|
return false;
|
||||||
|
|
||||||
text = GetVerbatim(text);
|
text = GetVerbatim(text);
|
||||||
string[] tmp = text.Split(' ');
|
|
||||||
if (text.Length > 0)
|
//Built-in detection routine for public messages
|
||||||
|
if (Settings.ChatFormat_Builtins)
|
||||||
{
|
{
|
||||||
|
string[] tmp = text.Split(' ');
|
||||||
|
|
||||||
//Detect vanilla/factions Messages
|
//Detect vanilla/factions Messages
|
||||||
//<Someone> message
|
//<Someone> message
|
||||||
//<*Faction Someone> message
|
//<*Faction Someone> message
|
||||||
//<*Faction Someone>: message
|
//<*Faction Someone>: message
|
||||||
//<*Faction ~Nicknamed>: message
|
//<*Faction ~Nicknamed>: message
|
||||||
if (text[0] == '<' && Settings.Vanilla_And_Factions_Messages_Enabled.Equals(true))
|
if (text[0] == '<')
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -287,7 +313,7 @@ namespace MinecraftClient
|
||||||
//Detect HeroChat Messages
|
//Detect HeroChat Messages
|
||||||
//Public chat messages
|
//Public chat messages
|
||||||
//[Channel] [Rank] User: Message
|
//[Channel] [Rank] User: Message
|
||||||
else if (text[0] == '[' && text.Contains(':') && tmp.Length > 2 && Settings.Hero_Chat_Messages_Enabled.Equals(true))
|
else if (text[0] == '[' && text.Contains(':') && tmp.Length > 2)
|
||||||
{
|
{
|
||||||
int name_end = text.IndexOf(':');
|
int name_end = text.IndexOf(':');
|
||||||
int name_start = text.Substring(0, name_end).LastIndexOf(']') + 2;
|
int name_start = text.Substring(0, name_end).LastIndexOf(']') + 2;
|
||||||
|
|
@ -306,8 +332,7 @@ namespace MinecraftClient
|
||||||
&& text.IndexOf('*') < text.IndexOf('<')
|
&& text.IndexOf('*') < text.IndexOf('<')
|
||||||
&& text.IndexOf('<') < text.IndexOf('>')
|
&& text.IndexOf('<') < text.IndexOf('>')
|
||||||
&& text.IndexOf('>') < text.IndexOf(' ')
|
&& text.IndexOf('>') < text.IndexOf(' ')
|
||||||
&& text.IndexOf(' ') < text.IndexOf(':')
|
&& text.IndexOf(' ') < text.IndexOf(':'))
|
||||||
&& Settings.Unknown_Chat_Plugin_Messages_One_Enabled.Equals(true))
|
|
||||||
{
|
{
|
||||||
string prefix = tmp[0];
|
string prefix = tmp[0];
|
||||||
string user = tmp[1];
|
string user = tmp[1];
|
||||||
|
|
@ -320,6 +345,19 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//User-defined regex for public chat messages
|
||||||
|
if (Settings.ChatFormat_Public != null)
|
||||||
|
{
|
||||||
|
Match regexMatch = Settings.ChatFormat_Public.Match(text);
|
||||||
|
if (regexMatch.Success && regexMatch.Groups.Count >= 3)
|
||||||
|
{
|
||||||
|
sender = regexMatch.Groups[1].Value;
|
||||||
|
message = regexMatch.Groups[2].Value;
|
||||||
|
return IsValidName(sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -332,8 +370,18 @@ namespace MinecraftClient
|
||||||
|
|
||||||
protected static bool IsTeleportRequest(string text, ref string sender)
|
protected static bool IsTeleportRequest(string text, ref string sender)
|
||||||
{
|
{
|
||||||
|
if (String.IsNullOrEmpty(text))
|
||||||
|
return false;
|
||||||
|
|
||||||
text = GetVerbatim(text);
|
text = GetVerbatim(text);
|
||||||
|
|
||||||
|
//Built-in detection routine for teleport requests
|
||||||
|
if (Settings.ChatFormat_Builtins)
|
||||||
|
{
|
||||||
string[] tmp = text.Split(' ');
|
string[] tmp = text.Split(' ');
|
||||||
|
|
||||||
|
//Detect Essentials teleport requests, prossibly with
|
||||||
|
//nicknamed names or other modifications such as HeroChat
|
||||||
if (text.EndsWith("has requested to teleport to you.")
|
if (text.EndsWith("has requested to teleport to you.")
|
||||||
|| text.EndsWith("has requested that you teleport to them."))
|
|| text.EndsWith("has requested that you teleport to them."))
|
||||||
{
|
{
|
||||||
|
|
@ -347,10 +395,27 @@ namespace MinecraftClient
|
||||||
//Username has requested...
|
//Username has requested...
|
||||||
else sender = tmp[0];
|
else sender = tmp[0];
|
||||||
|
|
||||||
|
//~Username has requested...
|
||||||
|
if (sender.Length > 1 && sender[0] == '~')
|
||||||
|
sender = sender.Substring(1);
|
||||||
|
|
||||||
//Final check on username validity
|
//Final check on username validity
|
||||||
return IsValidName(sender);
|
return IsValidName(sender);
|
||||||
}
|
}
|
||||||
else return false;
|
}
|
||||||
|
|
||||||
|
//User-defined regex for teleport requests
|
||||||
|
if (Settings.ChatFormat_TeleportRequest != null)
|
||||||
|
{
|
||||||
|
Match regexMatch = Settings.ChatFormat_TeleportRequest.Match(text);
|
||||||
|
if (regexMatch.Success && regexMatch.Groups.Count >= 2)
|
||||||
|
{
|
||||||
|
sender = regexMatch.Groups[1].Value;
|
||||||
|
return IsValidName(sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace MinecraftClient
|
namespace MinecraftClient
|
||||||
{
|
{
|
||||||
|
|
@ -97,10 +98,11 @@ namespace MinecraftClient
|
||||||
public static bool RemoteCtrl_AutoTpaccept = true;
|
public static bool RemoteCtrl_AutoTpaccept = true;
|
||||||
public static bool RemoteCtrl_AutoTpaccept_Everyone = false;
|
public static bool RemoteCtrl_AutoTpaccept_Everyone = false;
|
||||||
|
|
||||||
//Chat Message Enabled / Disabled.
|
//Chat Message Parsing
|
||||||
public static bool Hero_Chat_Messages_Enabled = true;
|
public static bool ChatFormat_Builtins = true;
|
||||||
public static bool Unknown_Chat_Plugin_Messages_One_Enabled = true;
|
public static Regex ChatFormat_Public = null;
|
||||||
public static bool Vanilla_And_Factions_Messages_Enabled = true;
|
public static Regex ChatFormat_Private = null;
|
||||||
|
public static Regex ChatFormat_TeleportRequest = null;
|
||||||
|
|
||||||
//Auto Respond
|
//Auto Respond
|
||||||
public static bool AutoRespond_Enabled = false;
|
public static bool AutoRespond_Enabled = false;
|
||||||
|
|
@ -111,7 +113,7 @@ namespace MinecraftClient
|
||||||
private static readonly Dictionary<string, KeyValuePair<string, string>> Accounts = new Dictionary<string, KeyValuePair<string, string>>();
|
private static readonly Dictionary<string, KeyValuePair<string, string>> Accounts = new Dictionary<string, KeyValuePair<string, string>>();
|
||||||
private static readonly Dictionary<string, KeyValuePair<string, ushort>> Servers = new Dictionary<string, KeyValuePair<string, ushort>>();
|
private static readonly Dictionary<string, KeyValuePair<string, ushort>> Servers = new Dictionary<string, KeyValuePair<string, ushort>>();
|
||||||
|
|
||||||
private enum ParseMode { Default, Main, AppVars, Proxy, AntiAFK, Hangman, Alerts, ChatLog, AutoRelog, ScriptScheduler, RemoteControl, ChatBotMessages, AutoRespond };
|
private enum ParseMode { Default, Main, AppVars, Proxy, AntiAFK, Hangman, Alerts, ChatLog, AutoRelog, ScriptScheduler, RemoteControl, ChatFormat, AutoRespond };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load settings from the give INI file
|
/// Load settings from the give INI file
|
||||||
|
|
@ -146,7 +148,7 @@ namespace MinecraftClient
|
||||||
case "proxy": pMode = ParseMode.Proxy; break;
|
case "proxy": pMode = ParseMode.Proxy; break;
|
||||||
case "appvars": pMode = ParseMode.AppVars; break;
|
case "appvars": pMode = ParseMode.AppVars; break;
|
||||||
case "autorespond": pMode = ParseMode.AutoRespond; break;
|
case "autorespond": pMode = ParseMode.AutoRespond; break;
|
||||||
case "chatbotmessages": pMode = ParseMode.ChatBotMessages; break;
|
case "chatformat": pMode = ParseMode.ChatFormat; break;
|
||||||
default: pMode = ParseMode.Default; break;
|
default: pMode = ParseMode.Default; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -309,13 +311,13 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ParseMode.ChatBotMessages:
|
case ParseMode.ChatFormat:
|
||||||
switch (argName.ToLower())
|
switch (argName.ToLower())
|
||||||
{
|
{
|
||||||
case "herochatmessagesenabled": Hero_Chat_Messages_Enabled = str2bool(argValue); break;
|
case "builtins": ChatFormat_Builtins = str2bool(argValue); break;
|
||||||
case "unknownchatpluginmessagesone": Unknown_Chat_Plugin_Messages_One_Enabled = str2bool(argValue); break;
|
case "public": ChatFormat_Public = new Regex(argValue); break;
|
||||||
case "vanillaandfactionsmessages": Vanilla_And_Factions_Messages_Enabled = str2bool(argValue); break;
|
case "private": ChatFormat_Private = new Regex(argValue); break;
|
||||||
|
case "tprequest": ChatFormat_TeleportRequest = new Regex(argValue); break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -424,6 +426,12 @@ namespace MinecraftClient
|
||||||
+ "username=\r\n"
|
+ "username=\r\n"
|
||||||
+ "password=\r\n"
|
+ "password=\r\n"
|
||||||
+ "\r\n"
|
+ "\r\n"
|
||||||
|
+ "[ChatFormat]\r\n"
|
||||||
|
+ "builtins=true #support for handling vanilla and common message formats\r\n"
|
||||||
|
+ "#public=^<([a-zA-Z0-9_]+)> (.+)$ #uncomment and adapt if necessary\r\n"
|
||||||
|
+ "#private=^([a-zA-Z0-9_]+) whispers to you: (.+)$ #vanilla example\r\n"
|
||||||
|
+ "#tprequest=^([a-zA-Z0-9_]+) has requested (?:to|that you) teleport to (?:you|them)\\.$\r\n"
|
||||||
|
+ "\r\n"
|
||||||
+ "#Bot Settings\r\n"
|
+ "#Bot Settings\r\n"
|
||||||
+ "\r\n"
|
+ "\r\n"
|
||||||
+ "[Alerts]\r\n"
|
+ "[Alerts]\r\n"
|
||||||
|
|
@ -464,18 +472,39 @@ namespace MinecraftClient
|
||||||
+ "autotpaccept=true\r\n"
|
+ "autotpaccept=true\r\n"
|
||||||
+ "tpaccepteveryone=false\r\n"
|
+ "tpaccepteveryone=false\r\n"
|
||||||
+ "\r\n"
|
+ "\r\n"
|
||||||
+ "[ChatBotMessages]\r\n"
|
|
||||||
+ "vanillaandfactionsmessages=true # Chat Formats \"<User> Message\" \"<*Faction User>: Message\" \r\n"
|
|
||||||
+ "herochatmessagesenabled=true # Chat Format is \"[Channel][Rank] User: Message\"\r\n"
|
|
||||||
+ "unknownchatpluginmessagesone=true # Chat Format is \"**Faction<Rank> User : Message\"\r\n"
|
|
||||||
+ "\r\n"
|
|
||||||
+ "[AutoRespond]\r\n"
|
+ "[AutoRespond]\r\n"
|
||||||
+ "enabled=false\r\n"
|
+ "enabled=false\r\n"
|
||||||
+ "matchesfile=matches.ini\r\n", Encoding.UTF8);
|
+ "matchesfile=matches.ini\r\n", Encoding.UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int str2int(string str) { try { return Convert.ToInt32(str); } catch { return 0; } }
|
/// <summary>
|
||||||
public static bool str2bool(string str) { return str == "true" || str == "1"; }
|
/// Convert the specified string to an integer, defaulting to zero if invalid argument
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">String to parse as an integer</param>
|
||||||
|
/// <returns>Integer value</returns>
|
||||||
|
|
||||||
|
public static int str2int(string str)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(str);
|
||||||
|
}
|
||||||
|
catch { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert the specified string to a boolean value, defaulting to false if invalid argument
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">String to parse as a boolean</param>
|
||||||
|
/// <returns>Boolean value</returns>
|
||||||
|
|
||||||
|
public static bool str2bool(string str)
|
||||||
|
{
|
||||||
|
if (String.IsNullOrEmpty(str))
|
||||||
|
return false;
|
||||||
|
str = str.Trim().ToLowerInvariant();
|
||||||
|
return str == "true" || str == "1";
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load login/password using an account alias
|
/// Load login/password using an account alias
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,15 @@ These files describe how some messages should be printed depending on your prefe
|
||||||
The client will automatically load en_GB.lang from your Minecraft folder if Minecraft is installed on your
|
The client will automatically load en_GB.lang from your Minecraft folder if Minecraft is installed on your
|
||||||
computer, or download it from Mojang's servers. You may choose another language in the config file.
|
computer, or download it from Mojang's servers. You may choose another language in the config file.
|
||||||
|
|
||||||
|
=========================
|
||||||
|
Detecting chat messages
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Minecraft Console Client can parse messages from the server in order to detect private and public messages.
|
||||||
|
This is useful for reacting to messages eg when using the AutoRespond, Hangman game, or RemoteControl bots.
|
||||||
|
However, for unusual chat formats, so you may need to tinker with the ChatFormat section of the config file.
|
||||||
|
Building regular expressions can be a bit tricky, so you might want to try them out eg on regex101.com
|
||||||
|
|
||||||
======================
|
======================
|
||||||
Using the Alerts bot
|
Using the Alerts bot
|
||||||
======================
|
======================
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue