From a46601a21cc8918daf54888c951e489456b26e43 Mon Sep 17 00:00:00 2001 From: Marc Piulachs Date: Wed, 25 Jun 2008 13:23:59 +0000 Subject: [PATCH 1/1] - miscellaneous small fixes - add support for preventing all commands to be run on the channel by default. Now TechBot only answers some of the commands in PM - add back the error Command svn path=/trunk/; revision=34079 --- .../Base/BugCommand.cs | 7 +- .../ErrorCommand.cs | 63 +- .../TechBot.Commands.Common.csproj | 1 + .../TechBot.Commands.MSDN/ApiCommand.cs | 5 +- .../TechBot.Library/Commands/Base/Command.cs | 24 + .../Commands/Base/XmlLookupCommand.cs | 2 - .../TechBot.Library/ParametersParser.cs | 537 ------------------ irc/TechBot/TechBot.Library/TechBotService.cs | 2 +- 8 files changed, 63 insertions(+), 578 deletions(-) rename irc/TechBot/{TechBot.Library/Commands => TechBot.Commands.Common}/ErrorCommand.cs (75%) delete mode 100644 irc/TechBot/TechBot.Library/ParametersParser.cs diff --git a/irc/TechBot/TechBot.Commands.Common/Base/BugCommand.cs b/irc/TechBot/TechBot.Commands.Common/Base/BugCommand.cs index a3c6c1f31b0..b3e182dce7a 100644 --- a/irc/TechBot/TechBot.Commands.Common/Base/BugCommand.cs +++ b/irc/TechBot/TechBot.Commands.Common/Base/BugCommand.cs @@ -6,12 +6,17 @@ namespace TechBot.Commands.Common { public abstract class BugCommand : Command { - private string m_BugID = null; +// private string m_BugID = null; public BugCommand() { } + public override bool AnswerInPublic + { + get { return true; } + } + public string BugID { get { return Parameters; } diff --git a/irc/TechBot/TechBot.Library/Commands/ErrorCommand.cs b/irc/TechBot/TechBot.Commands.Common/ErrorCommand.cs similarity index 75% rename from irc/TechBot/TechBot.Library/Commands/ErrorCommand.cs rename to irc/TechBot/TechBot.Commands.Common/ErrorCommand.cs index 5b4551aa9d2..bb1980b032e 100644 --- a/irc/TechBot/TechBot.Library/Commands/ErrorCommand.cs +++ b/irc/TechBot/TechBot.Commands.Common/ErrorCommand.cs @@ -2,7 +2,9 @@ using System; using System.Xml; using System.Collections; -namespace TechBot.Library +using TechBot.Library; + +namespace TechBot.Commands.Common { [Command("error", Help = "!error ")] public class ErrorCommand : Command @@ -68,27 +70,24 @@ namespace TechBot.Library return code.ToString(); } - public override void Handle(MessageContext context) - { - if (Text.Equals(String.Empty)) + public override void ExecuteCommand() + { + if (Parameters.Equals(String.Empty)) { - TechBot.ServiceOutput.WriteLine(context, - "Please provide an Error Code."); + Say("Please provide an Error Code."); return; } - string errorText = originalErrorText; + string errorText = Parameters; retry: NumberParser np = new NumberParser(); long error = np.Parse(errorText); - if (np.Error) - { - TechBot.ServiceOutput.WriteLine(context, - String.Format("{0} is not a valid Error Code.", - originalErrorText)); - return; - } + if (np.Error) + { + Say("{0} is not a valid Error Code.", Parameters); + return; + } ArrayList descriptions = new ArrayList(); @@ -159,27 +158,23 @@ namespace TechBot.Library goto retry; } - TechBot.ServiceOutput.WriteLine(context, - String.Format("I don't know about Error Code {0}.", - originalErrorText)); - } - else if (descriptions.Count == 1) - { - string description = (string)descriptions[0]; - TechBot.ServiceOutput.WriteLine(context, - String.Format("{0} is {1}.", - originalErrorText, - description)); - } - else - { - TechBot.ServiceOutput.WriteLine(context, - String.Format("{0} could be:", - originalErrorText)); - - foreach(string description in descriptions) - TechBot.ServiceOutput.WriteLine(context, String.Format("\t{0}", description)); + Say("I don't know about Error Code {0}.", + Parameters); } + else if (descriptions.Count == 1) + { + string description = (string)descriptions[0]; + Say("{0} is {1}.", + Parameters, + description); + } + else + { + Say("{0} could be:", Parameters); + + foreach (string description in descriptions) + Say("\t{0}", description); + } } } } diff --git a/irc/TechBot/TechBot.Commands.Common/TechBot.Commands.Common.csproj b/irc/TechBot/TechBot.Commands.Common/TechBot.Commands.Common.csproj index 005c98114b7..589f42a206a 100644 --- a/irc/TechBot/TechBot.Commands.Common/TechBot.Commands.Common.csproj +++ b/irc/TechBot/TechBot.Commands.Common/TechBot.Commands.Common.csproj @@ -34,6 +34,7 @@ + diff --git a/irc/TechBot/TechBot.Commands.MSDN/ApiCommand.cs b/irc/TechBot/TechBot.Commands.MSDN/ApiCommand.cs index 3a8e88ad06b..a165f6aa68d 100644 --- a/irc/TechBot/TechBot.Commands.MSDN/ApiCommand.cs +++ b/irc/TechBot/TechBot.Commands.MSDN/ApiCommand.cs @@ -16,11 +16,10 @@ namespace TechBot.Commands.MSDN private bool IsVerbose = false; private HtmlHelpSystem chm; - private string name; public ApiCommand() { - Run(); + LoadCHM(); } [CommandParameter("api", "The API name")] @@ -36,7 +35,7 @@ namespace TechBot.Commands.MSDN Say(message); } - private void Run() + private void LoadCHM() { string CHMFilename = Path.Combine(Settings.Default.ChmPath, Settings.Default.MainChm); chm = new HtmlHelpSystem(); diff --git a/irc/TechBot/TechBot.Library/Commands/Base/Command.cs b/irc/TechBot/TechBot.Library/Commands/Base/Command.cs index 25c5119b2c2..a822e4ca6e9 100644 --- a/irc/TechBot/TechBot.Library/Commands/Base/Command.cs +++ b/irc/TechBot/TechBot.Library/Commands/Base/Command.cs @@ -21,6 +21,11 @@ namespace TechBot.Library set { m_Context = value; } } + public virtual bool AnswerInPublic + { + get { return false; } + } + public string Name { get @@ -53,6 +58,25 @@ namespace TechBot.Library TechBot.ServiceOutput.WriteLine(Context, String.Format(format, args)); } + public void Run() + { + if (Context is ChannelMessageContext) + { + if (AnswerInPublic) + { + ExecuteCommand(); + } + else + { + Say("Sorry, I only respond '{0}' in private , PM me!", Name); + } + } + else + { + ExecuteCommand(); + } + } + public abstract void ExecuteCommand(); public virtual void Initialize() diff --git a/irc/TechBot/TechBot.Library/Commands/Base/XmlLookupCommand.cs b/irc/TechBot/TechBot.Library/Commands/Base/XmlLookupCommand.cs index e3a6aa0843c..20c8bfcfbcc 100644 --- a/irc/TechBot/TechBot.Library/Commands/Base/XmlLookupCommand.cs +++ b/irc/TechBot/TechBot.Library/Commands/Base/XmlLookupCommand.cs @@ -6,8 +6,6 @@ namespace TechBot.Library { public abstract class XmlLookupCommand : XmlCommand { - protected string m_Text = null; - public virtual string Text { get { return Parameters; } diff --git a/irc/TechBot/TechBot.Library/ParametersParser.cs b/irc/TechBot/TechBot.Library/ParametersParser.cs deleted file mode 100644 index 4ce16853518..00000000000 --- a/irc/TechBot/TechBot.Library/ParametersParser.cs +++ /dev/null @@ -1,537 +0,0 @@ -using System; -using System.Text.RegularExpressions; - -//Code taken from : http://www.codeproject.com/KB/recipes/commandlineparser.aspx - -namespace TechBot.Library -{ - /// Implementation of a command-line parsing class. Is capable of - /// having switches registered with it directly or can examine a registered - /// class for any properties with the appropriate attributes appended to - /// them. - public class ParametersParser - { - /// A simple internal class for passing back to the caller - /// some information about the switch. The internals/implementation - /// of this class has privillaged access to the contents of the - /// SwitchRecord class. - public class SwitchInfo - { - #region Private Variables - private object m_Switch = null; - #endregion - - #region Public Properties - public string Name { get { return (m_Switch as SwitchRecord).Name; } } - public string Description { get { return (m_Switch as SwitchRecord).Description; } } - public string[] Aliases { get { return (m_Switch as SwitchRecord).Aliases; } } - public System.Type Type { get { return (m_Switch as SwitchRecord).Type; } } - public object Value { get { return (m_Switch as SwitchRecord).Value; } } - public object InternalValue { get { return (m_Switch as SwitchRecord).InternalValue; } } - public bool IsEnum { get { return (m_Switch as SwitchRecord).Type.IsEnum; } } - public string[] Enumerations { get { return (m_Switch as SwitchRecord).Enumerations; } } - #endregion - - /// - /// Constructor for the SwitchInfo class. Note, in order to hide to the outside world - /// information not necessary to know, the constructor takes a System.Object (aka - /// object) as it's registering type. If the type isn't of the correct type, an exception - /// is thrown. - /// - /// The SwitchRecord for which this class store information. - /// Thrown if the rec parameter is not of - /// the type SwitchRecord. - public SwitchInfo( object rec ) - { - if ( rec is SwitchRecord ) - m_Switch = rec; - else - throw new ArgumentException(); - } - } - - /// - /// The SwitchRecord is stored within the parser's collection of registered - /// switches. This class is private to the outside world. - /// - private class SwitchRecord - { - #region Private Variables - private string m_name = ""; - private string m_description = ""; - private object m_value = null; - private System.Type m_switchType = typeof(bool); - private System.Collections.ArrayList m_Aliases = null; - private string m_Pattern = ""; - - // The following advanced functions allow for callbacks to be - // made to manipulate the associated data type. - private System.Reflection.MethodInfo m_SetMethod = null; - private System.Reflection.MethodInfo m_GetMethod = null; - private object m_PropertyOwner = null; - #endregion - - #region Private Utility Functions - private void Initialize( string name, string description ) - { - m_name = name; - m_description = description; - - BuildPattern(); - } - - private void BuildPattern() - { - string matchString = Name; - - if ( Aliases != null && Aliases.Length > 0 ) - foreach( string s in Aliases ) - matchString += "|" + s; - - string strPatternStart = @"(\s|^)(?(-{1,2}|/)("; - string strPatternEnd; // To be defined below. - - // The common suffix ensures that the switches are followed by - // a white-space OR the end of the string. This will stop - // switches such as /help matching /helpme - // - string strCommonSuffix = @"(?=(\s|$))"; - - if ( Type == typeof(bool) ) - strPatternEnd = @")(?(\+|-){0,1}))"; - else if ( Type == typeof(string) ) - strPatternEnd = @")(?::|\s+))((?:"")(?.+)(?:"")|(?\S+))"; - else if ( Type == typeof(int) ) - strPatternEnd = @")(?::|\s+))((?(-|\+)[0-9]+)|(?[0-9]+))"; - else if ( Type.IsEnum ) - { - string[] enumNames = Enumerations; - string e_str = enumNames[0]; - for ( int e=1; e" + e_str + @")"; - } - else - throw new System.ArgumentException(); - - // Set the internal regular expression pattern. - m_Pattern = strPatternStart + matchString + strPatternEnd + strCommonSuffix; - } - #endregion - - #region Public Properties - public object Value - { - get - { - if ( ReadValue != null ) - return ReadValue; - else - return m_value; - } - } - - public object InternalValue - { - get { return m_value; } - } - - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - public string Description - { - get { return m_description; } - set { m_description = value; } - } - - public System.Type Type - { - get { return m_switchType; } - } - - public string[] Aliases - { - get { return (m_Aliases != null) ? (string[])m_Aliases.ToArray(typeof(string)): null; } - } - - public string Pattern - { - get { return m_Pattern; } - } - - public System.Reflection.MethodInfo SetMethod - { - set { m_SetMethod = value; } - } - - public System.Reflection.MethodInfo GetMethod - { - set { m_GetMethod = value; } - } - - public object PropertyOwner - { - set { m_PropertyOwner = value; } - } - - public object ReadValue - { - get - { - object o = null; - if ( m_PropertyOwner != null && m_GetMethod != null ) - o = m_GetMethod.Invoke( m_PropertyOwner, null ); - return o; - } - } - - public string[] Enumerations - { - get - { - if ( m_switchType.IsEnum ) - return System.Enum.GetNames( m_switchType ); - else - return null; - } - } - #endregion - - #region Constructors - public SwitchRecord( string name, string description ) - { - Initialize( name, description ); - } - - public SwitchRecord( string name, string description, System.Type type ) - { - if ( type == typeof(bool) || - type == typeof(string) || - type == typeof(int) || - type.IsEnum ) - { - m_switchType = type; - Initialize( name, description ); - } - else - throw new ArgumentException("Currently only Ints, Bool and Strings are supported"); - } - #endregion - - #region Public Methods - public void AddAlias( string alias ) - { - if ( m_Aliases == null ) - m_Aliases = new System.Collections.ArrayList(); - m_Aliases.Add( alias ); - - BuildPattern(); - } - - public void Notify( object value ) - { - if ( m_PropertyOwner != null && m_SetMethod != null ) - { - object[] parameters = new object[1]; - parameters[0] = value; - m_SetMethod.Invoke( m_PropertyOwner, parameters ); - } - m_value = value; - } - - #endregion - } - - - #region Private Variables - private string m_commandLine = ""; - private string m_workingString = ""; - private string m_applicationName = ""; - private string[] m_splitParameters = null; - private System.Collections.ArrayList m_switches = null; - #endregion - - #region Private Utility Functions - private void ExtractApplicationName() - { - Regex r = new Regex(@"^(?("".+""|(\S)+))(?.+)", - RegexOptions.ExplicitCapture); - Match m = r.Match(m_commandLine); - if ( m != null && m.Groups["commandLine"] != null ) - { - m_applicationName = m.Groups["commandLine"].Value; - m_workingString = m.Groups["remainder"].Value; - } - } - - private void SplitParameters() - { - // Populate the split parameters array with the remaining parameters. - // Note that if quotes are used, the quotes are removed. - // e.g. one two three "four five six" - // 0 - one - // 1 - two - // 2 - three - // 3 - four five six - // (e.g. 3 is not in quotes). - Regex r = new Regex(@"((\s*(""(?.+?)""|(?\S+))))", - RegexOptions.ExplicitCapture); - MatchCollection m = r.Matches( m_workingString ); - - if ( m != null ) - { - m_splitParameters = new string[ m.Count ]; - for ( int i=0; i < m.Count; i++ ) - m_splitParameters[i] = m[i].Groups["param"].Value; - } - } - - private void HandleSwitches() - { - if ( m_switches != null ) - { - foreach ( SwitchRecord s in m_switches ) - { - Regex r = new Regex( s.Pattern, - RegexOptions.ExplicitCapture - | RegexOptions.IgnoreCase ); - MatchCollection m = r.Matches( m_workingString ); - if ( m != null ) - { - for ( int i=0; i < m.Count; i++ ) - { - string value = null; - if ( m[i].Groups != null && m[i].Groups["value"] != null ) - value = m[i].Groups["value"].Value; - - if ( s.Type == typeof(bool)) - { - bool state = true; - // The value string may indicate what value we want. - if ( m[i].Groups != null && m[i].Groups["value"] != null ) - { - switch ( value ) - { - case "+": state = true; - break; - case "-": state = false; - break; - case "": if ( s.ReadValue != null ) - state = !(bool)s.ReadValue; - break; - default: break; - } - } - s.Notify( state ); - break; - } - else if ( s.Type == typeof(string) ) - s.Notify( value ); - else if ( s.Type == typeof(int) ) - s.Notify( int.Parse( value ) ); - else if ( s.Type.IsEnum ) - s.Notify( System.Enum.Parse(s.Type,value,true) ); - } - } - - m_workingString = r.Replace(m_workingString, " "); - } - } - } - - #endregion - - #region Public Properties - public string ApplicationName - { - get { return m_applicationName; } - } - - public string[] Parameters - { - get { return m_splitParameters; } - } - - public SwitchInfo[] Switches - { - get - { - if ( m_switches == null ) - return null; - else - { - SwitchInfo[] si = new SwitchInfo[ m_switches.Count ]; - for ( int i=0; iThis function returns a list of the unhandled switches - /// that the parser has seen, but not processed. - /// The unhandled switches are not removed from the remainder - /// of the command-line. - public string[] UnhandledSwitches - { - get - { - string switchPattern = @"(\s|^)(?(-{1,2}|/)(.+?))(?=(\s|$))"; - Regex r = new Regex( switchPattern, - RegexOptions.ExplicitCapture - | RegexOptions.IgnoreCase ); - MatchCollection m = r.Matches( m_workingString ); - - if ( m != null ) - { - string[] unhandled = new string[ m.Count ]; - for ( int i=0; i < m.Count; i++ ) - unhandled[i] = m[i].Groups["match"].Value; - return unhandled; - } - else - return null; - } - } - #endregion - - #region Public Methods - public void AddSwitch( string name, string description ) - { - if ( m_switches == null ) - m_switches = new System.Collections.ArrayList(); - - SwitchRecord rec = new SwitchRecord( name, description ); - m_switches.Add( rec ); - } - - public void AddSwitch( string[] names, string description ) - { - if ( m_switches == null ) - m_switches = new System.Collections.ArrayList(); - SwitchRecord rec = new SwitchRecord( names[0], description ); - for ( int s=1; s 0) - { - SwitchRecord rec = null; - - foreach ( Attribute attribute in attributes ) - { - if ( attribute is CommandParameterAttribute ) - { - CommandParameterAttribute switchAttrib = - (CommandParameterAttribute) attribute; - - // Get the property information. We're only handling - // properties at the moment! - if ( members[i] is System.Reflection.PropertyInfo ) - { - System.Reflection.PropertyInfo pi = (System.Reflection.PropertyInfo) members[i]; - - rec = new SwitchRecord( switchAttrib.Name, - switchAttrib.Description, - pi.PropertyType ); - - // Map in the Get/Set methods. - rec.SetMethod = pi.GetSetMethod(); - rec.GetMethod = pi.GetGetMethod(); - rec.PropertyOwner = classForAutoAttributes; - - // Can only handle a single switch for each property - // (otherwise the parsing of aliases gets silly...) - break; - } - } - } - - // See if any aliases are required. We can only do this after - // a switch has been registered and the framework doesn't make - // any guarantees about the order of attributes, so we have to - // walk the collection a second time. - if ( rec != null ) - { - foreach ( Attribute attribute in attributes ) - { - if (attribute is CommandParameterAliasAttribute) - { - CommandParameterAliasAttribute aliasAttrib = - (CommandParameterAliasAttribute)attribute; - rec.AddAlias( aliasAttrib.Alias ); - } - } - } - - // Assuming we have a switch record (that may or may not have - // aliases), add it to the collection of switches. - if ( rec != null ) - { - if ( m_switches == null ) - m_switches = new System.Collections.ArrayList(); - m_switches.Add( rec ); - } - } - } - } - #endregion - } -} diff --git a/irc/TechBot/TechBot.Library/TechBotService.cs b/irc/TechBot/TechBot.Library/TechBotService.cs index ad201736ea4..025ff46d8ed 100644 --- a/irc/TechBot/TechBot.Library/TechBotService.cs +++ b/irc/TechBot/TechBot.Library/TechBotService.cs @@ -81,7 +81,7 @@ namespace TechBot.Library try { cmd.Initialize(); - cmd.ExecuteCommand(); + cmd.Run(); cmd.DeInitialize(); } catch (Exception e) -- 2.17.1