You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
12 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ProxyCore.Input
{
internal static class InputHandler
{
static InputHandler()
{
}
internal static SortedDictionary<string, InputEntry> Commands = new SortedDictionary<string, InputEntry>();
/// <summary>
/// Register a new command or overwrite a previous one.
/// </summary>
/// <param name="Cmd">Command to register.</param>
/// <param name="Args">Arguments to match (regex pattern). This can be set to null or empty string
/// if you don't want to capture anything or plan to do so in the function yourself.</param>
/// <param name="f">Function of command.</param>
internal static void RegisterCommand(string Cmd, string Args, CmdFunction f)
{
RegisterCommand(Cmd, Args, f, CMDFlags.None);
}
/// <summary>
/// Register a new command or overwrite a previous one.
/// </summary>
/// <param name="Cmd">Command to register.</param>
/// <param name="Args">Arguments to match (regex pattern). This can be set to null or empty string
/// if you don't want to capture anything or plan to do so in the function yourself.</param>
/// <param name="f">Function of command.</param>
/// <param name="flags">Options for command.</param>
internal static void RegisterCommand(string Cmd, string Args, CmdFunction f, CMDFlags flags)
{
RegisterCommand(Cmd, Args, f, flags, null);
}
/// <summary>
/// Register a new command or overwrite a previous one.
/// </summary>
/// <param name="Cmd">Command to register.</param>
/// <param name="Args">Arguments to match (regex pattern). This can be set to null or empty string
/// if you don't want to capture anything or plan to do so in the function yourself.</param>
/// <param name="f">Function of command.</param>
/// <param name="flags">Options for command.</param>
/// <param name="parent">Parent command (if you want to create a subcommand). You can enter commands separated with space if it's nested.</param>
internal static void RegisterCommand(string Cmd, string Args, CmdFunction f, CMDFlags flags, string parent)
{
RegisterCommand(Cmd, Args, f, flags, parent, 0);
}
/// <summary>
/// Register a new command or overwrite a previous one.
/// </summary>
/// <param name="Cmd">Command to register.</param>
/// <param name="Args">Arguments to match (regex pattern). This can be set to null or empty string
/// if you don't want to capture anything or plan to do so in the function yourself.</param>
/// <param name="f">Function of command.</param>
/// <param name="flags">Options for command.</param>
/// <param name="parent">Parent command (if you want to create a subcommand). You can enter commands separated with space if it's nested.</param>
/// <param name="Arg">Custom argument to pass to function handler. This way you can register multiple commands to a same
/// function handler only differentiating them with this custom argument.</param>
internal static void RegisterCommand(string Cmd, string Args, CmdFunction f, CMDFlags flags, string parent, int Arg)
{
RegisterCommand(Cmd, Args, f, flags, parent, Arg, ulong.MaxValue, "core", 0);
}
/// <summary>
/// Register a new command or overwrite a previous one.
/// </summary>
/// <param name="Cmd">Command to register.</param>
/// <param name="Args">Arguments to match (regex pattern). This can be set to null or empty string
/// if you don't want to capture anything or plan to do so in the function yourself.</param>
/// <param name="f">Function of command.</param>
/// <param name="flags">Options for command.</param>
/// <param name="parent">Parent command (if you want to create a subcommand). You can enter commands separated with space if it's nested.</param>
/// <param name="Arg">Custom argument to pass to function handler. This way you can register multiple commands to a same
/// function handler only differentiating them with this custom argument.</param>
/// <param name="AuthMask">Mask of allowed auth levels to access this command. Default ulong.MaxValue (meaning all auth levels are allowed).
/// Enter 3 for example to allow only auth level 1 and 2 to access this command.</param>
/// <param name="Plugin">From which plugin did this come.</param>
/// <param name="ReqMinLength">Minimum length of command typed required to activate. For example if command is "plugins" and this is 6 then "plugin" and "plugins" both activate this command but "plugi" won't.</param>
internal static void RegisterCommand(string Cmd, string Args, CmdFunction f, CMDFlags flags, string parent, int Arg, ulong AuthMask, string Plugin, int ReqMinLength)
{
if(string.IsNullOrEmpty(Cmd))
return;
Cmd = Cmd.ToLower().Trim();
if(string.IsNullOrEmpty(Cmd))
return;
if(Cmd.Contains(' '))
Cmd = Cmd.Substring(0, Cmd.IndexOf(' '));
InputEntry p = null;
if(!string.IsNullOrEmpty(parent))
{
string[] pc = parent.ToLower().Trim().Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
if(pc.Length == 0)
return;
if(Commands.ContainsKey(pc[0]))
{
p = Commands[pc[0]];
for(int i = 1; i < pc.Length; i++)
{
if(p.Subcommands != null && p.Subcommands.ContainsKey(pc[i]))
p = p.Subcommands[pc[i]];
else
return;
}
}
else
return;
}
InputEntry c = new InputEntry()
{
Command = Cmd,
CustomArg = Arg,
Flags = flags,
Func = f,
Parent = p,
Plugin = Plugin,
MinLength = ReqMinLength,
AuthMask = AuthMask
};
try
{
c.ArgumentsPattern = new Regex(Args, RegexOptions.IgnoreCase);
}
catch
{
c.ArgumentsPattern = null;
}
if(p != null)
{
if(p.Subcommands == null)
p.Subcommands = new SortedDictionary<string, InputEntry>();
p.Subcommands[Cmd] = c;
p.Flags |= CMDFlags.IsParent;
}
else
Commands[Cmd] = c;
}
/// <summary>
/// Unregister a command.
/// </summary>
/// <param name="Cmd">Command to unregister. If you want to unregister a nested command
/// separate commands with a space.</param>
internal static void UnregisterCommand(string Cmd)
{
if(Cmd == null)
return;
string[] pc = Cmd.ToLower().Trim().Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
if(pc.Length == 0)
return;
if(!Commands.ContainsKey(pc[0]))
return;
if(pc.Length > 1)
{
InputEntry p = Commands[pc[0]];
for(int i = 1; i < pc.Length; i++)
{
if(p.Subcommands == null || !p.Subcommands.ContainsKey(pc[i]))
return;
p = p.Subcommands[pc[i]];
}
p.Parent.Subcommands.Remove(p.Command);
if(p.Parent.Subcommands.Count == 0)
p.Parent.Flags &= ~CMDFlags.IsParent;
}
else
Commands.Remove(pc[0]);
}
internal static InputData HandleInput(string origCommand, string Msg, uint ClientId, int AuthLevel, InputEntry parent, World world)
{
Msg = Msg.Trim();
string cmd = "";
string text = "";
if(Msg.Contains(' '))
{
cmd = Msg.Substring(0, Msg.IndexOf(' '));
text = Msg.Substring(Msg.IndexOf(' ') + 1).Trim();
}
else
{
cmd = Msg;
}
cmd = cmd.ToLower();
InputEntry f = null;
if(!string.IsNullOrEmpty(cmd))
{
if(parent == null)
{
foreach(KeyValuePair<string, InputEntry> x in Commands)
{
if(x.Key == cmd && (x.Value.Flags & (CMDFlags.Dummy | CMDFlags.Disabled)) == CMDFlags.None && (x.Value.AuthMask & ((ulong)1 << (AuthLevel - 1))) != 0)
{
f = x.Value;
break;
}
}
if(f == null)
{
foreach(KeyValuePair<string, InputEntry> x in Commands)
{
if(x.Value.MinLength <= 0)
continue;
if(cmd.Length < x.Value.Command.Length && cmd.Length >= x.Value.MinLength && x.Value.Command.StartsWith(cmd) && (x.Value.Flags & (CMDFlags.Dummy | CMDFlags.Disabled)) == CMDFlags.None && (x.Value.AuthMask & ((ulong)1 << (AuthLevel - 1))) != 0)
{
f = x.Value;
break;
}
}
}
}
else if(parent.Subcommands != null)
{
foreach(KeyValuePair<string, InputEntry> x in parent.Subcommands)
{
if(x.Key == cmd && (x.Value.Flags & (CMDFlags.Dummy | CMDFlags.Disabled)) == CMDFlags.None && (x.Value.AuthMask & ((ulong)1 << (AuthLevel - 1))) != 0)
{
f = x.Value;
break;
}
}
if(f == null)
{
foreach(KeyValuePair<string, InputEntry> x in parent.Subcommands)
{
if(x.Value.MinLength <= 0)
continue;
if(cmd.Length < x.Value.Command.Length && cmd.Length >= x.Value.MinLength && x.Value.Command.StartsWith(cmd) && (x.Value.Flags & (CMDFlags.Dummy | CMDFlags.Disabled)) == CMDFlags.None && (x.Value.AuthMask & ((ulong)1 << (AuthLevel - 1))) != 0)
{
f = x.Value;
break;
}
}
}
}
}
else
{
if(parent != null && parent.Func != null)
f = parent;
else
return null;
}
if(f != null && (f.Flags & CMDFlags.IsParent) != CMDFlags.None && !string.IsNullOrEmpty(text))
return HandleInput(origCommand, text, ClientId, AuthLevel, f, world);
if(f == null || f.Func == null)
return null;
InputData data = new InputData();
data.Command = origCommand;
data.ClientId = ClientId;
data.ClientAuthLevel = AuthLevel;
data.Function = f;
if(f.ArgumentsPattern != null)
data.Arguments = f.ArgumentsPattern.Match(text);
return data;
}
}
}