diff --git a/irc/TechBot/Default.build b/irc/TechBot/Default.build
deleted file mode 100644
index 62738cfa1f0..00000000000
--- a/irc/TechBot/Default.build
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/irc/TechBot/TechBot.Console/ConsoleTechBotService.cs b/irc/TechBot/TechBot.Console/ConsoleTechBotService.cs
new file mode 100644
index 00000000000..14c3c84533d
--- /dev/null
+++ b/irc/TechBot/TechBot.Console/ConsoleTechBotService.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using TechBot.Library;
+
+namespace TechBot.Console
+{
+ public class ConsoleServiceOutput : IServiceOutput
+ {
+ public void WriteLine(MessageContext context,
+ string message)
+ {
+ System.Console.WriteLine(message);
+ }
+ }
+
+ public class ConsoleTechBotService : TechBotService
+ {
+ public ConsoleTechBotService(
+ string chmPath,
+ string mainChm)
+ : base(new ConsoleServiceOutput(), chmPath, mainChm)
+ {
+ }
+
+ public override void Run()
+ {
+ //Call the base class
+ base.Run();
+
+ while (true)
+ {
+ string s = System.Console.ReadLine();
+ InjectMessage(null, s);
+ }
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Console/Main.cs b/irc/TechBot/TechBot.Console/Main.cs
index 6826558a7c6..88760ac51aa 100644
--- a/irc/TechBot/TechBot.Console/Main.cs
+++ b/irc/TechBot/TechBot.Console/Main.cs
@@ -4,16 +4,6 @@ using TechBot.Library;
namespace TechBot.Console
{
- public class ConsoleServiceOutput : IServiceOutput
- {
- public void WriteLine(MessageContext context,
- string message)
- {
- System.Console.WriteLine(message);
- }
- }
-
-
class MainClass
{
private static void VerifyRequiredOption(string optionName,
@@ -208,53 +198,43 @@ namespace TechBot.Console
}
- private static void RunIrcService()
- {
- IrcService ircService = new IrcService(IRCServerHostName,
- IRCServerHostPort,
- IRCChannelNames,
- IRCBotName,
- IRCBotPassword,
- ChmPath,
- MainChm,
- //NtstatusXml,
- //WinerrorXml,
- //HresultXml,
- //WmXml,
- //SvnCommand,
- BugUrl,
- WineBugUrl,
- SambaBugUrl);
- ircService.Run();
- }
-
- public static void Main(string[] args)
- {
- if (args.Length > 0 && args[0].ToLower().Equals("irc"))
- {
- RunIrcService();
- return;
- }
-
- System.Console.WriteLine("TechBot running console service...");
- TechBotService service = new TechBotService(new ConsoleServiceOutput(),
- ChmPath,
- MainChm);
- //NtstatusXml,
- //WinerrorXml,
- //HresultXml,
- //WmXml,
- //SvnCommand,
- //BugUrl,
- //WineBugUrl,
- //SambaBugUrl);
- service.Run();
- while (true)
- {
- string s = System.Console.ReadLine();
- service.InjectMessage(null,
- s);
- }
- }
+ //private static void RunIrcService()
+ //{
+ // IrcTechBotService ircService = new IrcTechBotService(IRCServerHostName,
+ // IRCServerHostPort,
+ // IRCChannelNames,
+ // IRCBotName,
+ // IRCBotPassword,
+ // ChmPath,
+ // MainChm);
+ // ircService.Run();
+ //}
+
+ public static void Main(string[] args)
+ {
+ TechBotService m_TechBot = null;
+
+ if (args.Length > 0 && args[0].ToLower().Equals("irc"))
+ {
+ m_TechBot = new IrcTechBotService(IRCServerHostName,
+ IRCServerHostPort,
+ IRCChannelNames,
+ IRCBotName,
+ IRCBotPassword,
+ ChmPath,
+ MainChm);
+ }
+ else
+ {
+ System.Console.WriteLine("TechBot running console service...");
+ m_TechBot = new ConsoleTechBotService(
+ ChmPath,
+ MainChm);
+
+
+ }
+
+ m_TechBot.Run();
+ }
}
-}
+}
\ No newline at end of file
diff --git a/irc/TechBot/TechBot.Console/TechBot.Console.csproj b/irc/TechBot/TechBot.Console/TechBot.Console.csproj
index 1044ed8c029..4c0b6f77141 100644
--- a/irc/TechBot/TechBot.Console/TechBot.Console.csproj
+++ b/irc/TechBot/TechBot.Console/TechBot.Console.csproj
@@ -38,6 +38,7 @@
-->
+
diff --git a/irc/TechBot/TechBot.Library/Attributes/CommandAttribute.cs b/irc/TechBot/TechBot.Library/Attributes/CommandAttribute.cs
new file mode 100644
index 00000000000..a16ee780d7c
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Attributes/CommandAttribute.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TechBot.Library
+{
+ public class CommandAttribute : Attribute
+ {
+ private string m_Name = null;
+ private string m_Help = "No help for this command is available";
+ private string m_Desc = "No description for this command is available";
+
+ public CommandAttribute(string name)
+ {
+ m_Name = name;
+ }
+
+ public string Name
+ {
+ get { return m_Name; }
+ }
+
+ public string Help
+ {
+ get { return m_Help; }
+ set { m_Help = value; }
+ }
+
+ public string Description
+ {
+ get { return m_Desc; }
+ set { m_Desc = value; }
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/Attributes/CommandParameterAliasAttribute.cs b/irc/TechBot/TechBot.Library/Attributes/CommandParameterAliasAttribute.cs
new file mode 100644
index 00000000000..05dc10da4bd
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Attributes/CommandParameterAliasAttribute.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace TechBot.Library
+{
+ ///
+ /// This class implements an alias attribute to work in conjunction
+ /// with the CommandLineSwitchAttribute
+ /// attribute. If the CommandLineSwitchAttribute exists, then this attribute
+ /// defines an alias for it.
+ ///
+ [AttributeUsage( AttributeTargets.Property )]
+ public class CommandParameterAliasAttribute : Attribute
+ {
+ #region Private Variables
+ protected string m_Alias = "";
+ #endregion
+
+ #region Public Properties
+ public string Alias
+ {
+ get { return m_Alias; }
+ }
+
+ #endregion
+
+ #region Constructors
+ public CommandParameterAliasAttribute(string alias)
+ {
+ m_Alias = alias;
+ }
+ #endregion
+ }
+
+}
diff --git a/irc/TechBot/TechBot.Library/Attributes/CommandParameterAttribute.cs b/irc/TechBot/TechBot.Library/Attributes/CommandParameterAttribute.cs
new file mode 100644
index 00000000000..bdb3a8091b0
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Attributes/CommandParameterAttribute.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace TechBot.Library
+{
+ /// Implements a basic command-line switch by taking the
+ /// switching name and the associated description.
+ /// Only currently is implemented for properties, so all
+ /// auto-switching variables should have a get/set method supplied.
+ [AttributeUsage( AttributeTargets.Property )]
+ public class CommandParameterAttribute : Attribute
+ {
+ #region Private Variables
+ private string m_name = "";
+ private string m_description = "";
+ private bool m_Required = true;
+ #endregion
+
+ #region Public Properties
+ /// Accessor for retrieving the switch-name for an associated
+ /// property.
+ public string Name { get { return m_name; } }
+
+ /// Accessor for retrieving the description for a switch of
+ /// an associated property.
+ public string Description { get { return m_description; } }
+
+ public bool Required { get { return m_Required; } }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Attribute constructor.
+ ///
+ public CommandParameterAttribute(string name, string description)
+ {
+ m_name = name;
+ m_description = description;
+ }
+ #endregion
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/BugCommand.cs b/irc/TechBot/TechBot.Library/BugCommand.cs
deleted file mode 100644
index 99427388eb9..00000000000
--- a/irc/TechBot/TechBot.Library/BugCommand.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System;
-
-namespace TechBot.Library
-{
- public abstract class BugCommand : Command//, ICommand
- {
- public BugCommand(TechBotService techBot) : base (techBot)
- {
- }
-
- public override void Handle(MessageContext context,
- string commandName,
- string parameters)
- {
- string bugText = parameters;
- if (bugText.Equals(String.Empty))
- {
- TechBot.ServiceOutput.WriteLine(context,
- "Please provide a valid bug number.");
- return;
- }
-
- NumberParser np = new NumberParser();
- long bug = np.Parse(bugText);
- if (np.Error)
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("{0} is not a valid bug number.",
- bugText));
- return;
- }
-
- /*
- string bugUrl = this.RosBugUrl;
-
- if (context is ChannelMessageContext)
- {
- ChannelMessageContext channelContext = context as ChannelMessageContext;
- if (channelContext.Channel.Name == "winehackers")
- bugUrl = this.WineBugUrl;
- else if (channelContext.Channel.Name == "samba-technical")
- bugUrl = this.SambaBugUrl;
- }*/
-
- TechBot.ServiceOutput.WriteLine(context, String.Format(BugUrl, bug));
- }
-
- protected abstract string BugUrl { get; }
- }
-}
diff --git a/irc/TechBot/TechBot.Library/Collections/CommandBuilderCollection.cs b/irc/TechBot/TechBot.Library/Collections/CommandBuilderCollection.cs
new file mode 100644
index 00000000000..6cb4a814ca1
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Collections/CommandBuilderCollection.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TechBot.Library
+{
+ public class CommandBuilderCollection : List
+ {
+ public CommandBuilder Find(string name)
+ {
+ foreach (CommandBuilder command in this)
+ {
+ if (command.Name == name)
+ return command;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/Command.cs b/irc/TechBot/TechBot.Library/Command.cs
deleted file mode 100644
index b6ae0a14e58..00000000000
--- a/irc/TechBot/TechBot.Library/Command.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-
-namespace TechBot.Library
-{
- /*
- public interface ICommand
- {
- bool CanHandle(string commandName);
- void Handle(MessageContext context,
- string commandName,
- string parameters);
- //string Help();
- }*/
-
- public abstract class Command
- {
- protected TechBotService m_TechBotService = null;
-
- public Command(TechBotService techbot)
- {
- m_TechBotService = techbot;
- }
-
- public TechBotService TechBot
- {
- get { return m_TechBotService; }
- }
-
- public abstract string[] AvailableCommands { get; }
-
- public abstract void Handle(MessageContext context,
- string commandName,
- string parameters);
-
- /*
- protected bool CanHandle(string commandName,
- string[] availableCommands)
- {
- foreach (string availableCommand in availableCommands)
- {
- if (String.Compare(availableCommand, commandName, true) == 0)
- return true;
- }
- return false;
- }
- */
-
- public virtual string Help()
- {
- return "No help is available for this command";
- }
- }
-}
diff --git a/irc/TechBot/TechBot.Library/ApiCommand.cs b/irc/TechBot/TechBot.Library/Commands/ApiCommand.cs
similarity index 91%
rename from irc/TechBot/TechBot.Library/ApiCommand.cs
rename to irc/TechBot/TechBot.Library/Commands/ApiCommand.cs
index c0f3cc1d5c7..102ee140d29 100644
--- a/irc/TechBot/TechBot.Library/ApiCommand.cs
+++ b/irc/TechBot/TechBot.Library/Commands/ApiCommand.cs
@@ -1,353 +1,333 @@
-using System;
-using System.IO;
-using System.Data;
-using System.Text.RegularExpressions;
-using HtmlHelp;
-using HtmlHelp.ChmDecoding;
-
-namespace TechBot.Library
-{
- public class ApiCommand : Command
- {
- private const bool IsVerbose = false;
-
- private HtmlHelpSystem chm;
- private string chmPath;
- private string mainChm;
-
- public ApiCommand(TechBotService techBot)
- : base(techBot)
- {
- Run();
- }
-
- private void WriteIfVerbose(MessageContext context,
- string message)
- {
- if (IsVerbose)
- TechBot.ServiceOutput.WriteLine(context,
- message);
- }
-
- private void Run()
- {
- string CHMFilename = Path.Combine(chmPath, mainChm);
- chm = new HtmlHelpSystem();
- chm.OpenFile(CHMFilename, null);
-
- Console.WriteLine(String.Format("Loaded main CHM: {0}",
- Path.GetFileName(CHMFilename)));
- foreach (string filename in Directory.GetFiles(chmPath))
- {
- if (!Path.GetExtension(filename).ToLower().Equals(".chm"))
- continue;
- if (Path.GetFileName(filename).ToLower().Equals(mainChm))
- continue;
-
- Console.WriteLine(String.Format("Loading CHM: {0}",
- Path.GetFileName(filename)));
- try
- {
- chm.MergeFile(filename);
- }
- catch (Exception ex)
- {
- Console.WriteLine(String.Format("Could not load CHM: {0}. Exception {1}",
- Path.GetFileName(filename),
- ex));
- }
- }
- Console.WriteLine(String.Format("Loaded {0} CHMs",
- chm.FileList.Length));
- }
-
- public override string[] AvailableCommands
- {
- get { return new string[] { "api" }; }
- }
-
- /*
- public bool CanHandle(string commandName)
- {
- return CanHandle(commandName,
- new string[] { "api" });
- }
-*/
-
- public override void Handle(MessageContext context,
- string commandName,
- string parameters)
- {
- if (parameters.Trim().Equals(String.Empty))
- DisplayNoKeyword(context);
- else
- Search(context,
- parameters);
- }
-
- public override string Help()
- {
- return "!api ";
- }
-
- private bool SearchIndex(MessageContext context,
- string keyword)
- {
- if (chm.HasIndex)
- {
- IndexItem item = chm.Index.SearchIndex(keyword,
- IndexType.KeywordLinks);
- if (item != null && item.Topics.Count > 0)
- {
- WriteIfVerbose(context,
- String.Format("Keyword {0} found in index",
- item.KeyWord));
- IndexTopic indexTopic = item.Topics[0] as IndexTopic;
- return DisplayResult(context,
- keyword,
- indexTopic);
- }
- else
- {
- WriteIfVerbose(context,
- String.Format("Keyword {0} not found in index",
- keyword));
- return false;
- }
- }
- else
- return false;
- }
-
- private void SearchFullText(MessageContext context,
- string keyword)
- {
- string sort = "Rating ASC";
- WriteIfVerbose(context,
- String.Format("Searching fulltext database for {0}",
- keyword));
-
- bool partialMatches = false;
- bool titlesOnly = true;
- int maxResults = 100;
- DataTable results = chm.PerformSearch(keyword,
- maxResults,
- partialMatches,
- titlesOnly);
- WriteIfVerbose(context,
- String.Format("results.Rows.Count = {0}",
- results != null ?
- results.Rows.Count.ToString() : "(none)"));
- if (results != null && results.Rows.Count > 0)
- {
- results.DefaultView.Sort = sort;
- if (!DisplayResult(context,
- keyword,
- results))
- {
- DisplayNoResult(context,
- keyword);
- }
- }
- else
- {
- DisplayNoResult(context,
- keyword);
- }
- }
-
- private void Search(MessageContext context,
- string keyword)
- {
- if (!SearchIndex(context,
- keyword))
- SearchFullText(context,
- keyword);
- }
-
- private bool DisplayResult(MessageContext context,
- string keyword,
- IndexTopic indexTopic)
- {
- keyword = keyword.Trim().ToLower();
- string url = indexTopic.URL;
- WriteIfVerbose(context,
- String.Format("URL from index search {0}",
- url));
- string prototype = ExtractPrototype(context,
- url);
- if (prototype == null || prototype.Trim().Equals(String.Empty))
- return false;
- string formattedPrototype = FormatPrototype(prototype);
- TechBot.ServiceOutput.WriteLine(context,
- formattedPrototype);
- return true;
- }
-
- private bool DisplayResult(MessageContext context,
- string keyword,
- DataTable results)
- {
- keyword = keyword.Trim().ToLower();
- for (int i = 0; i < results.DefaultView.Count; i++)
- {
- DataRowView row = results.DefaultView[i];
- string title = row["Title"].ToString();
- WriteIfVerbose(context,
- String.Format("Examining {0}", title));
- if (title.Trim().ToLower().Equals(keyword))
- {
- string location = row["Location"].ToString();
- string rating = row["Rating"].ToString();
- string url = row["Url"].ToString();
- string prototype = ExtractPrototype(context,
- url);
- if (prototype == null || prototype.Trim().Equals(String.Empty))
- continue;
- string formattedPrototype = FormatPrototype(prototype);
- TechBot.ServiceOutput.WriteLine(context,
- formattedPrototype);
- return true;
- }
- }
- return false;
- }
-
- private void DisplayNoResult(MessageContext context,
- string keyword)
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("I don't know about keyword {0}",
- keyword));
- }
-
- private void DisplayNoKeyword(MessageContext context)
- {
- TechBot.ServiceOutput.WriteLine(context,
- "Please give me a keyword.");
- }
-
- private string ReplaceComments(string s)
- {
- return Regex.Replace(s, "//(.+)\r\n", "");
- }
-
- private string ReplaceLineEndings(string s)
- {
- return Regex.Replace(s, "(\r\n)+", " ");
- }
-
- private string ReplaceSpaces(string s)
- {
- return Regex.Replace(s, @" +", " ");
- }
-
- private string ReplaceSpacesBeforeLeftParenthesis(string s)
- {
- return Regex.Replace(s, @"\( ", @"(");
- }
-
- private string ReplaceSpacesBeforeRightParenthesis(string s)
- {
- return Regex.Replace(s, @" \)", @")");
- }
-
- private string ReplaceSemicolon(string s)
- {
- return Regex.Replace(s, @";", @"");
- }
-
- private string FormatPrototype(string prototype)
- {
- string s = ReplaceComments(prototype);
- s = ReplaceLineEndings(s);
- s = ReplaceSpaces(s);
- s = ReplaceSpacesBeforeLeftParenthesis(s);
- s = ReplaceSpacesBeforeRightParenthesis(s);
- s = ReplaceSemicolon(s);
- return s;
- }
-
- private string ExtractPrototype(MessageContext context,
- string url)
- {
- string page = GetPage(context,
- url);
- Match match = Regex.Match(page,
- "(.+)
",
- RegexOptions.Multiline |
- RegexOptions.Singleline);
- if (match.Groups.Count > 1)
- {
- string prototype = match.Groups[1].ToString();
- return StripHtml(StripAfterSlashPre(prototype));
- }
-
- return "";
- }
-
- private string StripAfterSlashPre(string html)
- {
- int index = html.IndexOf("");
- if (index != -1)
- {
- return html.Substring(0, index);
- }
- else
- return html;
- }
-
- private string StripHtml(string html)
- {
- return Regex.Replace(html, @"<(.|\n)*?>", String.Empty);
- }
-
- private string GetPage(MessageContext context,
- string url)
- {
- string CHMFileName = "";
- string topicName = "";
- string anchor = "";
- CHMStream.CHMStream baseStream;
- if (!chm.BaseStream.GetCHMParts(url, ref CHMFileName, ref topicName, ref anchor))
- {
- baseStream = chm.BaseStream;
- CHMFileName = baseStream.CHMFileName;
- topicName = url;
- anchor = "";
- }
- else
- {
- baseStream = GetBaseStreamFromCHMFileName(context,
- CHMFileName);
- }
-
- if ((topicName == "") || (CHMFileName == "") || (baseStream == null))
- {
- return "";
- }
-
- return baseStream.ExtractTextFile(topicName);
- }
-
- private CHMStream.CHMStream GetBaseStreamFromCHMFileName(MessageContext context,
- string CHMFileName)
- {
- foreach (CHMFile file in chm.FileList)
- {
- WriteIfVerbose(context,
- String.Format("Compare: {0} <> {1}",
- file.ChmFilePath,
- CHMFileName));
- if (file.ChmFilePath.ToLower().Equals(CHMFileName.ToLower()))
- {
- return file.BaseStream;
- }
- }
- WriteIfVerbose(context,
- String.Format("Could not find loaded CHM file in list: {0}",
- CHMFileName));
- return null;
- }
- }
-}
+using System;
+using System.IO;
+using System.Data;
+using System.Text.RegularExpressions;
+using HtmlHelp;
+using HtmlHelp.ChmDecoding;
+
+namespace TechBot.Library
+{
+ [Command("api", Help = "!api ")]
+ public class ApiCommand : Command
+ {
+ private const bool IsVerbose = false;
+
+ private HtmlHelpSystem chm;
+ private string chmPath;
+ private string mainChm;
+
+ public ApiCommand()
+ {
+ Run();
+ }
+
+ private void WriteIfVerbose(MessageContext context,
+ string message)
+ {
+ if (IsVerbose)
+ TechBot.ServiceOutput.WriteLine(context,
+ message);
+ }
+
+ private void Run()
+ {
+ string CHMFilename = Path.Combine(chmPath, mainChm);
+ chm = new HtmlHelpSystem();
+ chm.OpenFile(CHMFilename, null);
+
+ Console.WriteLine(String.Format("Loaded main CHM: {0}",
+ Path.GetFileName(CHMFilename)));
+ foreach (string filename in Directory.GetFiles(chmPath))
+ {
+ if (!Path.GetExtension(filename).ToLower().Equals(".chm"))
+ continue;
+ if (Path.GetFileName(filename).ToLower().Equals(mainChm))
+ continue;
+
+ Console.WriteLine(String.Format("Loading CHM: {0}",
+ Path.GetFileName(filename)));
+ try
+ {
+ chm.MergeFile(filename);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(String.Format("Could not load CHM: {0}. Exception {1}",
+ Path.GetFileName(filename),
+ ex));
+ }
+ }
+ Console.WriteLine(String.Format("Loaded {0} CHMs",
+ chm.FileList.Length));
+ }
+
+ public override void Handle(MessageContext context)
+ {
+ if (parameters.Trim().Equals(String.Empty))
+ DisplayNoKeyword(context);
+ else
+ Search(context,
+ parameters);
+ }
+
+ private bool SearchIndex(MessageContext context,
+ string keyword)
+ {
+ if (chm.HasIndex)
+ {
+ IndexItem item = chm.Index.SearchIndex(keyword,
+ IndexType.KeywordLinks);
+ if (item != null && item.Topics.Count > 0)
+ {
+ WriteIfVerbose(context,
+ String.Format("Keyword {0} found in index",
+ item.KeyWord));
+ IndexTopic indexTopic = item.Topics[0] as IndexTopic;
+ return DisplayResult(context,
+ keyword,
+ indexTopic);
+ }
+ else
+ {
+ WriteIfVerbose(context,
+ String.Format("Keyword {0} not found in index",
+ keyword));
+ return false;
+ }
+ }
+ else
+ return false;
+ }
+
+ private void SearchFullText(MessageContext context,
+ string keyword)
+ {
+ string sort = "Rating ASC";
+ WriteIfVerbose(context,
+ String.Format("Searching fulltext database for {0}",
+ keyword));
+
+ bool partialMatches = false;
+ bool titlesOnly = true;
+ int maxResults = 100;
+ DataTable results = chm.PerformSearch(keyword,
+ maxResults,
+ partialMatches,
+ titlesOnly);
+ WriteIfVerbose(context,
+ String.Format("results.Rows.Count = {0}",
+ results != null ?
+ results.Rows.Count.ToString() : "(none)"));
+ if (results != null && results.Rows.Count > 0)
+ {
+ results.DefaultView.Sort = sort;
+ if (!DisplayResult(context,
+ keyword,
+ results))
+ {
+ DisplayNoResult(context,
+ keyword);
+ }
+ }
+ else
+ {
+ DisplayNoResult(context,
+ keyword);
+ }
+ }
+
+ private void Search(MessageContext context,
+ string keyword)
+ {
+ if (!SearchIndex(context,
+ keyword))
+ SearchFullText(context,
+ keyword);
+ }
+
+ private bool DisplayResult(MessageContext context,
+ string keyword,
+ IndexTopic indexTopic)
+ {
+ keyword = keyword.Trim().ToLower();
+ string url = indexTopic.URL;
+ WriteIfVerbose(context,
+ String.Format("URL from index search {0}",
+ url));
+ string prototype = ExtractPrototype(context,
+ url);
+ if (prototype == null || prototype.Trim().Equals(String.Empty))
+ return false;
+ string formattedPrototype = FormatPrototype(prototype);
+ TechBot.ServiceOutput.WriteLine(context,
+ formattedPrototype);
+ return true;
+ }
+
+ private bool DisplayResult(MessageContext context,
+ string keyword,
+ DataTable results)
+ {
+ keyword = keyword.Trim().ToLower();
+ for (int i = 0; i < results.DefaultView.Count; i++)
+ {
+ DataRowView row = results.DefaultView[i];
+ string title = row["Title"].ToString();
+ WriteIfVerbose(context,
+ String.Format("Examining {0}", title));
+ if (title.Trim().ToLower().Equals(keyword))
+ {
+ string location = row["Location"].ToString();
+ string rating = row["Rating"].ToString();
+ string url = row["Url"].ToString();
+ string prototype = ExtractPrototype(context,
+ url);
+ if (prototype == null || prototype.Trim().Equals(String.Empty))
+ continue;
+ string formattedPrototype = FormatPrototype(prototype);
+ TechBot.ServiceOutput.WriteLine(context,
+ formattedPrototype);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void DisplayNoResult(MessageContext context,
+ string keyword)
+ {
+ TechBot.ServiceOutput.WriteLine(context,
+ String.Format("I don't know about keyword {0}",
+ keyword));
+ }
+
+ private void DisplayNoKeyword(MessageContext context)
+ {
+ TechBot.ServiceOutput.WriteLine(context,
+ "Please give me a keyword.");
+ }
+
+ private string ReplaceComments(string s)
+ {
+ return Regex.Replace(s, "//(.+)\r\n", "");
+ }
+
+ private string ReplaceLineEndings(string s)
+ {
+ return Regex.Replace(s, "(\r\n)+", " ");
+ }
+
+ private string ReplaceSpaces(string s)
+ {
+ return Regex.Replace(s, @" +", " ");
+ }
+
+ private string ReplaceSpacesBeforeLeftParenthesis(string s)
+ {
+ return Regex.Replace(s, @"\( ", @"(");
+ }
+
+ private string ReplaceSpacesBeforeRightParenthesis(string s)
+ {
+ return Regex.Replace(s, @" \)", @")");
+ }
+
+ private string ReplaceSemicolon(string s)
+ {
+ return Regex.Replace(s, @";", @"");
+ }
+
+ private string FormatPrototype(string prototype)
+ {
+ string s = ReplaceComments(prototype);
+ s = ReplaceLineEndings(s);
+ s = ReplaceSpaces(s);
+ s = ReplaceSpacesBeforeLeftParenthesis(s);
+ s = ReplaceSpacesBeforeRightParenthesis(s);
+ s = ReplaceSemicolon(s);
+ return s;
+ }
+
+ private string ExtractPrototype(MessageContext context,
+ string url)
+ {
+ string page = GetPage(context,
+ url);
+ Match match = Regex.Match(page,
+ "(.+)
",
+ RegexOptions.Multiline |
+ RegexOptions.Singleline);
+ if (match.Groups.Count > 1)
+ {
+ string prototype = match.Groups[1].ToString();
+ return StripHtml(StripAfterSlashPre(prototype));
+ }
+
+ return "";
+ }
+
+ private string StripAfterSlashPre(string html)
+ {
+ int index = html.IndexOf("");
+ if (index != -1)
+ {
+ return html.Substring(0, index);
+ }
+ else
+ return html;
+ }
+
+ private string StripHtml(string html)
+ {
+ return Regex.Replace(html, @"<(.|\n)*?>", String.Empty);
+ }
+
+ private string GetPage(MessageContext context,
+ string url)
+ {
+ string CHMFileName = "";
+ string topicName = "";
+ string anchor = "";
+ CHMStream.CHMStream baseStream;
+ if (!chm.BaseStream.GetCHMParts(url, ref CHMFileName, ref topicName, ref anchor))
+ {
+ baseStream = chm.BaseStream;
+ CHMFileName = baseStream.CHMFileName;
+ topicName = url;
+ anchor = "";
+ }
+ else
+ {
+ baseStream = GetBaseStreamFromCHMFileName(context,
+ CHMFileName);
+ }
+
+ if ((topicName == "") || (CHMFileName == "") || (baseStream == null))
+ {
+ return "";
+ }
+
+ return baseStream.ExtractTextFile(topicName);
+ }
+
+ private CHMStream.CHMStream GetBaseStreamFromCHMFileName(MessageContext context,
+ string CHMFileName)
+ {
+ foreach (CHMFile file in chm.FileList)
+ {
+ WriteIfVerbose(context,
+ String.Format("Compare: {0} <> {1}",
+ file.ChmFilePath,
+ CHMFileName));
+ if (file.ChmFilePath.ToLower().Equals(CHMFileName.ToLower()))
+ {
+ return file.BaseStream;
+ }
+ }
+ WriteIfVerbose(context,
+ String.Format("Could not find loaded CHM file in list: {0}",
+ CHMFileName));
+ return null;
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/Commands/Base/Command.cs b/irc/TechBot/TechBot.Library/Commands/Base/Command.cs
new file mode 100644
index 00000000000..839475b73f7
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Commands/Base/Command.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace TechBot.Library
+{
+ public abstract class Command
+ {
+ protected TechBotService m_TechBotService = null;
+ protected MessageContext m_Context = null;
+
+ public TechBotService TechBot
+ {
+ get { return m_TechBotService; }
+ set { m_TechBotService = value; }
+ }
+
+ public MessageContext Context
+ {
+ get { return m_Context; }
+ set { m_Context = value; }
+ }
+
+ public string Name
+ {
+ get
+ {
+ CommandAttribute commandAttribute = (CommandAttribute)
+ Attribute.GetCustomAttribute(GetType(), typeof(CommandAttribute));
+
+ return commandAttribute.Name;
+ }
+ }
+
+ public void ParseParameters(string paramaters)
+ {
+ ParametersParser parser = new ParametersParser(paramaters, this);
+ parser.Parse();
+ }
+
+ protected virtual void Say(string message)
+ {
+ TechBot.ServiceOutput.WriteLine(Context, message);
+ }
+
+ protected virtual void Say(string format , params object[] args)
+ {
+ TechBot.ServiceOutput.WriteLine(Context, String.Format(format, args));
+ }
+
+ public abstract void ExecuteCommand();
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/Commands/Base/XmlCommand.cs b/irc/TechBot/TechBot.Library/Commands/Base/XmlCommand.cs
index f5d39df1ab3..673e796eb50 100644
--- a/irc/TechBot/TechBot.Library/Commands/Base/XmlCommand.cs
+++ b/irc/TechBot/TechBot.Library/Commands/Base/XmlCommand.cs
@@ -9,8 +9,7 @@ namespace TechBot.Library
{
protected XmlDocument m_XmlDocument;
- public XmlCommand(TechBotService techBot)
- : base(techBot)
+ public XmlCommand()
{
m_XmlDocument = new XmlDocument();
m_XmlDocument.Load(XmlFile);
diff --git a/irc/TechBot/TechBot.Library/Commands/Base/XmlLookupCommand.cs b/irc/TechBot/TechBot.Library/Commands/Base/XmlLookupCommand.cs
new file mode 100644
index 00000000000..547badb5adb
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Commands/Base/XmlLookupCommand.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TechBot.Library
+{
+ public abstract class XmlLookupCommand : XmlCommand
+ {
+ private string m_Text = null;
+
+ [CommandParameter("text", "The value to check")]
+ public string Text
+ {
+ get { return m_Text; }
+ set { m_Text = value; }
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/Commands/BugCommand.cs b/irc/TechBot/TechBot.Library/Commands/BugCommand.cs
new file mode 100644
index 00000000000..1beb5fce661
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Commands/BugCommand.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace TechBot.Library
+{
+ public abstract class BugCommand : Command
+ {
+ private string m_BugID = null;
+
+ public BugCommand()
+ {
+ }
+
+ [CommandParameter("id", "The bug ID")]
+ public string BugID
+ {
+ get { return m_BugID; }
+ set { m_BugID = value; }
+ }
+
+ public override void ExecuteCommand()
+ {
+ if (BugID == null)
+ {
+ Say("Please provide a valid bug number.");
+ }
+ else
+ {
+ try
+ {
+ Say(BugUrl, Int32.Parse(BugID));
+ }
+ catch (Exception)
+ {
+ Say("{0} is not a valid bug number.", BugID);
+ }
+ }
+ }
+
+ protected abstract string BugUrl { get; }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/ErrorCommand.cs b/irc/TechBot/TechBot.Library/Commands/ErrorCommand.cs
similarity index 81%
rename from irc/TechBot/TechBot.Library/ErrorCommand.cs
rename to irc/TechBot/TechBot.Library/Commands/ErrorCommand.cs
index 3d7a7cf8c1a..5b4551aa9d2 100644
--- a/irc/TechBot/TechBot.Library/ErrorCommand.cs
+++ b/irc/TechBot/TechBot.Library/Commands/ErrorCommand.cs
@@ -1,206 +1,185 @@
-using System;
-using System.Xml;
-using System.Collections;
-
-namespace TechBot.Library
-{
- public class ErrorCommand : Command
- {
- private NtStatusCommand ntStatus;
- private WinerrorCommand winerror;
- private HResultCommand hresult;
-
- public ErrorCommand(TechBotService techBot)
- : base(techBot)
- {
- this.ntStatus = new NtStatusCommand(techBot);
- this.winerror = new WinerrorCommand(techBot);
- this.hresult = new HResultCommand(techBot);
- }
-
- /*
- public bool CanHandle(string commandName)
- {
- return CanHandle(commandName,
- new string[] { "error" });
- }
- */
-
- public override string[] AvailableCommands
- {
- get { return new string[] { "error" }; }
- }
-
- private static int GetSeverity(long error)
- {
- return (int)((error >> 30) & 0x3);
- }
-
- private static bool IsCustomer(long error)
- {
- return (error & 0x20000000) != 0;
- }
-
- private static bool IsReserved(long error)
- {
- return (error & 0x10000000) != 0;
- }
-
- private static int GetFacility(long error)
- {
- return (int)((error >> 16) & 0xFFF);
- }
-
- private static short GetCode(long error)
- {
- return (short)((error >> 0) & 0xFFFF);
- }
-
- private static string FormatSeverity(long error)
- {
- int severity = GetSeverity(error);
- switch (severity)
- {
- case 0: return "SUCCESS";
- case 1: return "INFORMATIONAL";
- case 2: return "WARNING";
- case 3: return "ERROR";
- }
- return null;
- }
-
- private static string FormatFacility(long error)
- {
- int facility = GetFacility(error);
- return facility.ToString();
- }
-
- private static string FormatCode(long error)
- {
- int code = GetCode(error);
- return code.ToString();
- }
-
- public override void Handle(MessageContext context,
- string commandName,
- string parameters)
- {
- string originalErrorText = parameters.Trim();
- if (originalErrorText.Equals(String.Empty))
- {
- TechBot.ServiceOutput.WriteLine(context,
- "Please provide an Error Code.");
- return;
- }
-
- string errorText = originalErrorText;
-
- 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;
- }
-
- ArrayList descriptions = new ArrayList();
-
- // Error is out of bounds
- if ((ulong)error > uint.MaxValue)
- {
- // Do nothing
- }
- // Error is outside of the range [0, 65535]: it cannot be a plain Win32 error code
- else if ((ulong)error > ushort.MaxValue)
- {
- // Customer bit is set: custom error code
- if (IsCustomer(error))
- {
- string description = String.Format("[custom, severity {0}, facility {1}, code {2}]",
- FormatSeverity(error),
- FormatFacility(error),
- FormatCode(error));
- descriptions.Add(description);
- }
- // Reserved bit is set: HRESULT_FROM_NT(ntstatus)
- else if (IsReserved(error))
- {
- int status = (int)(error & 0xCFFFFFFF);
- string description = ntStatus.GetNtstatusDescription(status);
-
- if (description == null)
- description = status.ToString("X");
-
- description = String.Format("HRESULT_FROM_NT({0})", description);
- descriptions.Add(description);
- }
- // Win32 facility: HRESULT_FROM_WIN32(winerror)
- else if (GetFacility(error) == 7)
- {
- // Must be an error code
- if (GetSeverity(error) == 2)
- {
- short err = GetCode(error);
- string description = winerror.GetWinerrorDescription(err);
-
- if (description == null)
- description = err.ToString("D");
-
- description = String.Format("HRESULT_FROM_WIN32({0})", description);
- descriptions.Add(description);
- }
- }
- }
-
- string winerrorDescription = winerror.GetWinerrorDescription(error);
- string ntstatusDescription = ntStatus.GetNtstatusDescription(error);
- string hresultDescription = hresult.GetHresultDescription(error);
-
- if (winerrorDescription != null)
- descriptions.Add(winerrorDescription);
- if (ntstatusDescription != null)
- descriptions.Add(ntstatusDescription);
- if (hresultDescription != null)
- descriptions.Add(hresultDescription);
-
- if (descriptions.Count == 0)
- {
- // Last chance heuristics: attempt to parse a 8-digit decimal as hexadecimal
- if (errorText.Length == 8)
- {
- errorText = "0x" + errorText;
- 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));
- }
- }
-
- public override string Help()
- {
- return "!error ";
- }
- }
-}
+using System;
+using System.Xml;
+using System.Collections;
+
+namespace TechBot.Library
+{
+ [Command("error", Help = "!error ")]
+ public class ErrorCommand : Command
+ {
+ private NtStatusCommand ntStatus;
+ private WinErrorCommand winerror;
+ private HResultCommand hresult;
+
+ public ErrorCommand()
+ {
+ this.ntStatus = new NtStatusCommand();
+ this.winerror = new WinErrorCommand();
+ this.hresult = new HResultCommand();
+ }
+
+ private static int GetSeverity(long error)
+ {
+ return (int)((error >> 30) & 0x3);
+ }
+
+ private static bool IsCustomer(long error)
+ {
+ return (error & 0x20000000) != 0;
+ }
+
+ private static bool IsReserved(long error)
+ {
+ return (error & 0x10000000) != 0;
+ }
+
+ private static int GetFacility(long error)
+ {
+ return (int)((error >> 16) & 0xFFF);
+ }
+
+ private static short GetCode(long error)
+ {
+ return (short)((error >> 0) & 0xFFFF);
+ }
+
+ private static string FormatSeverity(long error)
+ {
+ int severity = GetSeverity(error);
+ switch (severity)
+ {
+ case 0: return "SUCCESS";
+ case 1: return "INFORMATIONAL";
+ case 2: return "WARNING";
+ case 3: return "ERROR";
+ }
+ return null;
+ }
+
+ private static string FormatFacility(long error)
+ {
+ int facility = GetFacility(error);
+ return facility.ToString();
+ }
+
+ private static string FormatCode(long error)
+ {
+ int code = GetCode(error);
+ return code.ToString();
+ }
+
+ public override void Handle(MessageContext context)
+ {
+ if (Text.Equals(String.Empty))
+ {
+ TechBot.ServiceOutput.WriteLine(context,
+ "Please provide an Error Code.");
+ return;
+ }
+
+ string errorText = originalErrorText;
+
+ 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;
+ }
+
+ ArrayList descriptions = new ArrayList();
+
+ // Error is out of bounds
+ if ((ulong)error > uint.MaxValue)
+ {
+ // Do nothing
+ }
+ // Error is outside of the range [0, 65535]: it cannot be a plain Win32 error code
+ else if ((ulong)error > ushort.MaxValue)
+ {
+ // Customer bit is set: custom error code
+ if (IsCustomer(error))
+ {
+ string description = String.Format("[custom, severity {0}, facility {1}, code {2}]",
+ FormatSeverity(error),
+ FormatFacility(error),
+ FormatCode(error));
+ descriptions.Add(description);
+ }
+ // Reserved bit is set: HRESULT_FROM_NT(ntstatus)
+ else if (IsReserved(error))
+ {
+ int status = (int)(error & 0xCFFFFFFF);
+ string description = ntStatus.GetNtstatusDescription(status);
+
+ if (description == null)
+ description = status.ToString("X");
+
+ description = String.Format("HRESULT_FROM_NT({0})", description);
+ descriptions.Add(description);
+ }
+ // Win32 facility: HRESULT_FROM_WIN32(winerror)
+ else if (GetFacility(error) == 7)
+ {
+ // Must be an error code
+ if (GetSeverity(error) == 2)
+ {
+ short err = GetCode(error);
+ string description = winerror.GetWinerrorDescription(err);
+
+ if (description == null)
+ description = err.ToString("D");
+
+ description = String.Format("HRESULT_FROM_WIN32({0})", description);
+ descriptions.Add(description);
+ }
+ }
+ }
+
+ string winerrorDescription = winerror.GetWinerrorDescription(error);
+ string ntstatusDescription = ntStatus.GetNtstatusDescription(error);
+ string hresultDescription = hresult.GetHresultDescription(error);
+
+ if (winerrorDescription != null)
+ descriptions.Add(winerrorDescription);
+ if (ntstatusDescription != null)
+ descriptions.Add(ntstatusDescription);
+ if (hresultDescription != null)
+ descriptions.Add(hresultDescription);
+
+ if (descriptions.Count == 0)
+ {
+ // Last chance heuristics: attempt to parse a 8-digit decimal as hexadecimal
+ if (errorText.Length == 8)
+ {
+ errorText = "0x" + errorText;
+ 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));
+ }
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/Commands/HelpCommand.cs b/irc/TechBot/TechBot.Library/Commands/HelpCommand.cs
new file mode 100644
index 00000000000..f47ae18e912
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Commands/HelpCommand.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections;
+
+namespace TechBot.Library
+{
+ [Command("help", Help = "!help")]
+ public class HelpCommand : Command
+ {
+ private string m_CommandName = null;
+
+ public HelpCommand()
+ {
+ }
+
+ [CommandParameter("Name", "The command name to show help")]
+ public string CommandName
+ {
+ get { return m_CommandName; }
+ set { m_CommandName = value; }
+ }
+
+ public override void ExecuteCommand()
+ {
+ if (CommandName == null)
+ {
+ Say("I support the following commands:");
+
+ foreach (CommandBuilder command in TechBot.Commands)
+ {
+ Say("!{0} - {1}",
+ command.Name,
+ command.Description);
+ }
+ }
+ else
+ {
+ CommandBuilder cmdBuilder = TechBot.Commands.Find(CommandName);
+
+ if (cmdBuilder == null)
+ {
+ Say("Command '{0}' is not recognized. Type '!help' to show all available commands", CommandName);
+ }
+ else
+ {
+ Say("Command '{0}' help:", CommandName);
+ Say("");
+ }
+ }
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/HresultCommand.cs b/irc/TechBot/TechBot.Library/Commands/HresultCommand.cs
similarity index 50%
rename from irc/TechBot/TechBot.Library/HresultCommand.cs
rename to irc/TechBot/TechBot.Library/Commands/HresultCommand.cs
index c8842cdbb98..cb631cd6c3b 100644
--- a/irc/TechBot/TechBot.Library/HresultCommand.cs
+++ b/irc/TechBot/TechBot.Library/Commands/HresultCommand.cs
@@ -1,90 +1,69 @@
-using System;
-using System.Xml;
-
-namespace TechBot.Library
-{
- public class HResultCommand : XmlCommand
- {
- public HResultCommand(TechBotService techBot)
- : base(techBot)
- {
- }
-
- public override string XmlFile
- {
- get { return Settings.Default.HResultXml; }
- }
-
- public override string[] AvailableCommands
- {
- get { return new string[] { "hresult" }; }
- }
-
- /*
- public bool CanHandle(string commandName)
- {
- return CanHandle(commandName,
- new string[] { "hresult" });
- }
- */
-
- public override void Handle(MessageContext context,
- string commandName,
- string parameters)
- {
- string hresultText = parameters;
- if (hresultText.Equals(String.Empty))
- {
- TechBot.ServiceOutput.WriteLine(context,
- "Please provide a valid HRESULT value.");
- return;
- }
-
- NumberParser np = new NumberParser();
- long hresult = np.Parse(hresultText);
- if (np.Error)
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("{0} is not a valid HRESULT value.",
- hresultText));
- return;
- }
-
- string description = GetHresultDescription(hresult);
- if (description != null)
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("{0} is {1}.",
- hresultText,
- description));
- }
- else
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("I don't know about HRESULT {0}.",
- hresultText));
- }
- }
-
- public override string Help()
- {
- return "!hresult ";
- }
-
- public string GetHresultDescription(long hresult)
- {
- XmlElement root = base.m_XmlDocument.DocumentElement;
- XmlNode node = root.SelectSingleNode(String.Format("Hresult[@value='{0}']",
- hresult.ToString("X8")));
- if (node != null)
- {
- XmlAttribute text = node.Attributes["text"];
- if (text == null)
- throw new Exception("Node has no text attribute.");
- return text.Value;
- }
- else
- return null;
- }
- }
-}
+using System;
+using System.Xml;
+
+namespace TechBot.Library
+{
+ [Command("hresult", Help = "!hresult ")]
+ public class HResultCommand : XmlLookupCommand
+ {
+ public HResultCommand()
+ {
+ }
+
+ public override string XmlFile
+ {
+ get { return Settings.Default.HResultXml; }
+ }
+
+ public override void ExecuteCommand()
+ {
+ if (Text.Equals(String.Empty))
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ "Please provide a valid HRESULT value.");
+ return;
+ }
+
+ NumberParser np = new NumberParser();
+ long hresult = np.Parse(Text);
+ if (np.Error)
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("{0} is not a valid HRESULT value.",
+ Text));
+ return;
+ }
+
+ string description = GetHresultDescription(hresult);
+ if (description != null)
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("{0} is {1}.",
+ Text,
+ description));
+ }
+ else
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("I don't know about HRESULT {0}.",
+ Text));
+ }
+ }
+
+ public string GetHresultDescription(long hresult)
+ {
+ XmlElement root = base.m_XmlDocument.DocumentElement;
+ XmlNode node = root.SelectSingleNode(String.Format("Hresult[@value='{0}']",
+ hresult.ToString("X8")));
+ if (node != null)
+ {
+ XmlAttribute text = node.Attributes["text"];
+ if (text == null)
+ throw new Exception("Node has no text attribute.");
+ return text.Value;
+ }
+ else
+ return null;
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/NtStatusCommand.cs b/irc/TechBot/TechBot.Library/Commands/NtStatusCommand.cs
similarity index 51%
rename from irc/TechBot/TechBot.Library/NtStatusCommand.cs
rename to irc/TechBot/TechBot.Library/Commands/NtStatusCommand.cs
index 4833c57487d..c38751bf35b 100644
--- a/irc/TechBot/TechBot.Library/NtStatusCommand.cs
+++ b/irc/TechBot/TechBot.Library/Commands/NtStatusCommand.cs
@@ -1,88 +1,69 @@
-using System;
-using System.Xml;
-
-namespace TechBot.Library
-{
- public class NtStatusCommand : XmlCommand
- {
- public NtStatusCommand(TechBotService techBot)
- : base(techBot)
- {
- }
-
- public override string XmlFile
- {
- get { return Settings.Default.NtStatusXml; }
- }
-
- public override string[] AvailableCommands
- {
- get { return new string[] { "ntstatus" }; }
- }
-/*
- public bool CanHandle(string commandName)
- {
- return CanHandle(commandName,
- new string[] { "ntstatus" });
- }
-*/
- public override void Handle(MessageContext context,
- string commandName,
- string parameters)
- {
- string ntstatusText = parameters;
- if (ntstatusText.Equals(String.Empty))
- {
- TechBot.ServiceOutput.WriteLine(context,
- "Please provide a valid NTSTATUS value.");
- return;
- }
-
- NumberParser np = new NumberParser();
- long ntstatus = np.Parse(ntstatusText);
- if (np.Error)
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("{0} is not a valid NTSTATUS value.",
- ntstatusText));
- return;
- }
-
- string description = GetNtstatusDescription(ntstatus);
- if (description != null)
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("{0} is {1}.",
- ntstatusText,
- description));
- }
- else
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("I don't know about NTSTATUS {0}.",
- ntstatusText));
- }
- }
-
- public override string Help()
- {
- return "!ntstatus ";
- }
-
- public string GetNtstatusDescription(long ntstatus)
- {
- XmlElement root = base.m_XmlDocument.DocumentElement;
- XmlNode node = root.SelectSingleNode(String.Format("Ntstatus[@value='{0}']",
- ntstatus.ToString("X8")));
- if (node != null)
- {
- XmlAttribute text = node.Attributes["text"];
- if (text == null)
- throw new Exception("Node has no text attribute.");
- return text.Value;
- }
- else
- return null;
- }
- }
-}
+using System;
+using System.Xml;
+
+namespace TechBot.Library
+{
+ [Command("ntstatus", Help = "!ntstatus ")]
+ public class NtStatusCommand : XmlLookupCommand
+ {
+ public NtStatusCommand()
+ {
+ }
+
+ public override string XmlFile
+ {
+ get { return Settings.Default.NtStatusXml; }
+ }
+
+ public override void ExecuteCommand()
+ {
+ if (Text.Equals(String.Empty))
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ "Please provide a valid NTSTATUS value.");
+ return;
+ }
+
+ NumberParser np = new NumberParser();
+ long ntstatus = np.Parse(Text);
+ if (np.Error)
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("{0} is not a valid NTSTATUS value.",
+ Text));
+ return;
+ }
+
+ string description = GetNtstatusDescription(ntstatus);
+ if (description != null)
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("{0} is {1}.",
+ Text,
+ description));
+ }
+ else
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("I don't know about NTSTATUS {0}.",
+ Text));
+ }
+ }
+
+ public string GetNtstatusDescription(long ntstatus)
+ {
+ XmlElement root = base.m_XmlDocument.DocumentElement;
+ XmlNode node = root.SelectSingleNode(String.Format("Ntstatus[@value='{0}']",
+ ntstatus.ToString("X8")));
+ if (node != null)
+ {
+ XmlAttribute text = node.Attributes["text"];
+ if (text == null)
+ throw new Exception("Node has no text attribute.");
+ return text.Value;
+ }
+ else
+ return null;
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/ReactOSBugUrl.cs b/irc/TechBot/TechBot.Library/Commands/ReactOSBugUrl.cs
similarity index 50%
rename from irc/TechBot/TechBot.Library/ReactOSBugUrl.cs
rename to irc/TechBot/TechBot.Library/Commands/ReactOSBugUrl.cs
index daa0e5c5c73..0fd194d8443 100644
--- a/irc/TechBot/TechBot.Library/ReactOSBugUrl.cs
+++ b/irc/TechBot/TechBot.Library/Commands/ReactOSBugUrl.cs
@@ -4,26 +4,16 @@ using System.Text;
namespace TechBot.Library
{
+ [Command("rosbug", Help = "!rosbug ")]
class ReactOSBugUrl : BugCommand
{
- public ReactOSBugUrl(TechBotService techBot)
- : base(techBot)
+ public ReactOSBugUrl()
{
}
- public override string[] AvailableCommands
- {
- get { return new string[] { "rosbug" }; }
- }
-
protected override string BugUrl
{
get { return "http://www.reactos.org/bugzilla/show_bug.cgi?id={0}"; }
}
-
- public override string Help()
- {
- return "!rosbug ";
- }
}
}
diff --git a/irc/TechBot/TechBot.Library/Commands/SambaBugUrl.cs b/irc/TechBot/TechBot.Library/Commands/SambaBugUrl.cs
new file mode 100644
index 00000000000..74b51827d5a
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Commands/SambaBugUrl.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TechBot.Library
+{
+ [Command("sambabug", Help = "!sambabug ")]
+ class SambaBugUrl : BugCommand
+ {
+ public SambaBugUrl()
+ {
+ }
+
+ protected override string BugUrl
+ {
+ get { return "https://bugzilla.samba.org/show_bug.cgi?id={0}"; }
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/Commands/SvnCommand.cs b/irc/TechBot/TechBot.Library/Commands/SvnCommand.cs
new file mode 100644
index 00000000000..5146c281b5f
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Commands/SvnCommand.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace TechBot.Library
+{
+ [Command("svn", Help = "!svn")]
+ public class SvnCommand : Command
+ {
+ private string m_SvnRoot;
+
+ public SvnCommand()
+ {
+ m_SvnRoot = Settings.Default.SVNRoot;
+ }
+
+ public override void ExecuteCommand()
+ {
+ Say("svn co {0}", m_SvnRoot);
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/Commands/WineBugUrl.cs b/irc/TechBot/TechBot.Library/Commands/WineBugUrl.cs
new file mode 100644
index 00000000000..ace4f003e0a
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Commands/WineBugUrl.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TechBot.Library
+{
+ [Command("winebug", Help = "!winebug ")]
+ class WineBugUrl : BugCommand
+ {
+ public WineBugUrl()
+ {
+ }
+
+ protected override string BugUrl
+ {
+ get { return "http://bugs.winehq.org/show_bug.cgi?id={0}"; }
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/WinerrorCommand.cs b/irc/TechBot/TechBot.Library/Commands/WinerrorCommand.cs
similarity index 51%
rename from irc/TechBot/TechBot.Library/WinerrorCommand.cs
rename to irc/TechBot/TechBot.Library/Commands/WinerrorCommand.cs
index 512157575a8..66e439a68e0 100644
--- a/irc/TechBot/TechBot.Library/WinerrorCommand.cs
+++ b/irc/TechBot/TechBot.Library/Commands/WinerrorCommand.cs
@@ -1,82 +1,69 @@
-using System;
-using System.Xml;
-
-namespace TechBot.Library
-{
- public class WinerrorCommand : XmlCommand
- {
- public WinerrorCommand(TechBotService techBot)
- : base(techBot)
- {
- }
-
- public override string XmlFile
- {
- get { return Settings.Default.WinErrorXml; }
- }
-
- public override string[] AvailableCommands
- {
- get { return new string[] { "winerror" }; }
- }
-
- public override void Handle(MessageContext context,
- string commandName,
- string parameters)
- {
- string winerrorText = parameters;
- if (winerrorText.Equals(String.Empty))
- {
- TechBot.ServiceOutput.WriteLine(context,
- "Please provide a valid System Error Code value.");
- return;
- }
-
- NumberParser np = new NumberParser();
- long winerror = np.Parse(winerrorText);
- if (np.Error)
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("{0} is not a valid System Error Code value.",
- winerrorText));
- return;
- }
-
- string description = GetWinerrorDescription(winerror);
- if (description != null)
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("{0} is {1}.",
- winerrorText,
- description));
- }
- else
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("I don't know about System Error Code {0}.",
- winerrorText));
- }
- }
-
- public override string Help()
- {
- return "!winerror ";
- }
-
- public string GetWinerrorDescription(long winerror)
- {
- XmlElement root = base.m_XmlDocument.DocumentElement;
- XmlNode node = root.SelectSingleNode(String.Format("Winerror[@value='{0}']",
- winerror));
- if (node != null)
- {
- XmlAttribute text = node.Attributes["text"];
- if (text == null)
- throw new Exception("Node has no text attribute.");
- return text.Value;
- }
- else
- return null;
- }
- }
-}
+using System;
+using System.Xml;
+
+namespace TechBot.Library
+{
+ [Command("winerror", Help = "!winerror ")]
+ public class WinErrorCommand : XmlLookupCommand
+ {
+ public WinErrorCommand()
+ {
+ }
+
+ public override string XmlFile
+ {
+ get { return Settings.Default.WinErrorXml; }
+ }
+
+ public override void ExecuteCommand()
+ {
+ if (Text.Equals(String.Empty))
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ "Please provide a valid System Error Code value.");
+ return;
+ }
+
+ NumberParser np = new NumberParser();
+ long winerror = np.Parse(Text);
+ if (np.Error)
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("{0} is not a valid System Error Code value.",
+ Text));
+ return;
+ }
+
+ string description = GetWinerrorDescription(winerror);
+ if (description != null)
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("{0} is {1}.",
+ Text,
+ description));
+ }
+ else
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("I don't know about System Error Code {0}.",
+ Text));
+ }
+ }
+
+ public string GetWinerrorDescription(long winerror)
+ {
+ XmlElement root = base.m_XmlDocument.DocumentElement;
+ XmlNode node = root.SelectSingleNode(String.Format("Winerror[@value='{0}']",
+ Text));
+ if (node != null)
+ {
+ XmlAttribute text = node.Attributes["text"];
+ if (text == null)
+ throw new Exception("Node has no text attribute.");
+ return text.Value;
+ }
+ else
+ return null;
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/WmCommand.cs b/irc/TechBot/TechBot.Library/Commands/WmCommand.cs
similarity index 65%
rename from irc/TechBot/TechBot.Library/WmCommand.cs
rename to irc/TechBot/TechBot.Library/Commands/WmCommand.cs
index 31d670109ae..4ffd4939e85 100644
--- a/irc/TechBot/TechBot.Library/WmCommand.cs
+++ b/irc/TechBot/TechBot.Library/Commands/WmCommand.cs
@@ -1,100 +1,96 @@
-using System;
-using System.Xml;
-
-namespace TechBot.Library
-{
- public class WMCommand : XmlCommand
- {
- public WMCommand(TechBotService techBot)
- : base(techBot)
- {
- }
-
- public override string XmlFile
- {
- get { return Settings.Default.WMXml; }
- }
-
- public override string[] AvailableCommands
- {
- get { return new string[] { "wm" }; }
- }
-
- public override void Handle(MessageContext context,
- string commandName,
- string parameters)
- {
- string wmText = parameters;
- if (wmText.Equals(String.Empty))
- {
- TechBot.ServiceOutput.WriteLine(context,
- "Please provide a valid window message value or name.");
- return;
- }
-
- NumberParser np = new NumberParser();
- long wm = np.Parse(wmText);
- string output;
- if (np.Error)
- {
- // Assume "!wm " form.
- output = GetWmNumber(wmText);
- }
- else
- {
- output = GetWmDescription(wm);
- }
-
- if (output != null)
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("{0} is {1}.",
- wmText,
- output));
- }
- else
- {
- TechBot.ServiceOutput.WriteLine(context,
- String.Format("I don't know about window message {0}.",
- wmText));
- }
- }
-
- public override string Help()
- {
- return "!wm or !wm ";
- }
-
- private string GetWmDescription(long wm)
- {
- XmlElement root = base.m_XmlDocument.DocumentElement;
- XmlNode node = root.SelectSingleNode(String.Format("WindowMessage[@value='{0}']",
- wm));
- if (node != null)
- {
- XmlAttribute text = node.Attributes["text"];
- if (text == null)
- throw new Exception("Node has no text attribute.");
- return text.Value;
- }
- else
- return null;
- }
-
- private string GetWmNumber(string wmName)
- {
- XmlElement root = base.m_XmlDocument.DocumentElement;
- XmlNode node = root.SelectSingleNode(String.Format("WindowMessage[@text='{0}']",
- wmName));
- if (node != null)
- {
- XmlAttribute value = node.Attributes["value"];
- if (value == null)
- throw new Exception("Node has no value attribute.");
- return value.Value;
- }
- else
- return null;
- }
- }
-}
+using System;
+using System.Xml;
+
+namespace TechBot.Library
+{
+ [Command("wm" , Help = "!wm or !wm ")]
+ public class WMCommand : XmlCommand
+ {
+ private string m_WMText = null;
+
+ public WMCommand()
+ {
+ }
+
+ public override string XmlFile
+ {
+ get { return Settings.Default.WMXml; }
+ }
+
+ [CommandParameter("wm", "The windows message to check")]
+ public string WMText
+ {
+ get { return m_WMText; }
+ set { m_WMText = value; }
+ }
+
+ public override void ExecuteCommand()
+ {
+ if (WMText.Equals(String.Empty))
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ "Please provide a valid window message value or name.");
+ return;
+ }
+
+ NumberParser np = new NumberParser();
+ long wm = np.Parse(WMText);
+ string output;
+ if (np.Error)
+ {
+ // Assume "!wm " form.
+ output = GetWmNumber(WMText);
+ }
+ else
+ {
+ output = GetWmDescription(wm);
+ }
+
+ if (output != null)
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("{0} is {1}.",
+ WMText,
+ output));
+ }
+ else
+ {
+ TechBot.ServiceOutput.WriteLine(Context,
+ String.Format("I don't know about window message {0}.",
+ WMText));
+ }
+ }
+
+ private string GetWmDescription(long wm)
+ {
+ XmlElement root = base.m_XmlDocument.DocumentElement;
+ XmlNode node = root.SelectSingleNode(String.Format("WindowMessage[@value='{0}']",
+ wm));
+ if (node != null)
+ {
+ XmlAttribute text = node.Attributes["text"];
+ if (text == null)
+ throw new Exception("Node has no text attribute.");
+ return text.Value;
+ }
+ else
+ return null;
+ }
+
+ private string GetWmNumber(string wmName)
+ {
+ XmlElement root = base.m_XmlDocument.DocumentElement;
+ XmlNode node = root.SelectSingleNode(String.Format("WindowMessage[@text='{0}']",
+ wmName));
+ if (node != null)
+ {
+ XmlAttribute value = node.Attributes["value"];
+ if (value == null)
+ throw new Exception("Node has no value attribute.");
+ return value.Value;
+ }
+ else
+ return null;
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/Factory/CommandBuilder.cs b/irc/TechBot/TechBot.Library/Factory/CommandBuilder.cs
new file mode 100644
index 00000000000..6a459670a4c
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Factory/CommandBuilder.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TechBot.Library
+{
+ public class CommandBuilder
+ {
+ private Type m_CommandType;
+ private string m_CommandName;
+ private string m_CommandHelp;
+ private string m_CommandDesc;
+
+ public CommandBuilder(Type commandType)
+ {
+ m_CommandType = commandType;
+
+ CommandAttribute commandAttribute = (CommandAttribute)
+ Attribute.GetCustomAttribute(commandType, typeof(CommandAttribute));
+
+ m_CommandName = commandAttribute.Name;
+ m_CommandHelp = commandAttribute.Help;
+ m_CommandDesc = commandAttribute.Description;
+ }
+
+ public string Name
+ {
+ get { return m_CommandName; }
+ }
+
+ public string Help
+ {
+ get { return m_CommandHelp; }
+ }
+
+ public string Description
+ {
+ get { return m_CommandDesc; }
+ }
+
+ public Type Type
+ {
+ get { return m_CommandType; }
+ }
+
+ public Command CreateCommand()
+ {
+ return (Command)Type.Assembly.CreateInstance(Type.FullName, true);
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/Factory/CommandFactory.cs b/irc/TechBot/TechBot.Library/Factory/CommandFactory.cs
new file mode 100644
index 00000000000..34e3471f6f8
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/Factory/CommandFactory.cs
@@ -0,0 +1,54 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Reflection;
+
+namespace TechBot.Library
+{
+ public class CommandFactory
+ {
+ private static CommandBuilderCollection m_Commands = new CommandBuilderCollection();
+
+ private CommandFactory()
+ {
+ }
+
+ public static void LoadPlugins()
+ {
+ //get the file names of the dll files in the current directory.
+ FileInfo objExeInfo = new FileInfo(@"C:\Ros\current\irc\TechBot\TechBot.Console\bin\Debug\");
+
+ foreach (FileInfo objInfo in objExeInfo.Directory.GetFiles("*.dll"))
+ {
+ LoadPluginsFromDLLFile(objInfo.FullName);
+ }
+ }
+
+ private static void LoadPluginsFromDLLFile(string sFile)
+ {
+ Assembly assPlugin = Assembly.LoadFile(sFile);
+
+ if (assPlugin != null)
+ {
+ foreach (Type pluginType in assPlugin.GetTypes())
+ {
+ if (pluginType.IsSubclassOf(typeof(Command)))
+ {
+ if (pluginType.IsAbstract == false)
+ {
+ //Add it to the list.
+ Commands.Add(new CommandBuilder(pluginType));
+ }
+ }
+ }
+ }
+ }
+
+ public static CommandBuilderCollection Commands
+ {
+ get { return m_Commands; }
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/HelpCommand.cs b/irc/TechBot/TechBot.Library/HelpCommand.cs
deleted file mode 100644
index b007a7e5cc3..00000000000
--- a/irc/TechBot/TechBot.Library/HelpCommand.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System;
-using System.Collections;
-
-namespace TechBot.Library
-{
- public class HelpCommand : Command
- {
- public HelpCommand(TechBotService techBot)
- : base(techBot)
- {
- }
-
- public override string[] AvailableCommands
- {
- get { return new string[] { "help" }; }
- }
-
- public override void Handle(
- MessageContext context,
- string commandName,
- string parameters)
- {
- TechBot.ServiceOutput.WriteLine(context, "I support the following commands:");
-
- foreach (Command command in TechBot.Commands)
- {
- TechBot.ServiceOutput.WriteLine(context,
- command.Help());
- }
- }
-
- public override string Help()
- {
- return "!help";
- }
- }
-}
diff --git a/irc/TechBot/TechBot.Library/MessageContext.cs b/irc/TechBot/TechBot.Library/MessageContext.cs
index 8d1728a25c1..1d9677c8462 100644
--- a/irc/TechBot/TechBot.Library/MessageContext.cs
+++ b/irc/TechBot/TechBot.Library/MessageContext.cs
@@ -7,43 +7,33 @@ namespace TechBot.Library
{
}
-
-
public class ChannelMessageContext : MessageContext
{
- private IrcChannel channel;
+ private IrcChannel m_IrcChannel;
- public IrcChannel Channel
- {
- get
- {
- return channel;
- }
- }
+ public IrcChannel Channel
+ {
+ get { return m_IrcChannel; }
+ }
public ChannelMessageContext(IrcChannel channel)
{
- this.channel = channel;
+ m_IrcChannel = channel;
}
}
-
-
public class UserMessageContext : MessageContext
{
- private IrcUser user;
+ private IrcUser m_IrcUser;
- public IrcUser User
- {
- get
- {
- return user;
- }
- }
+ public IrcUser User
+ {
+ get { return m_IrcUser; }
+ }
public UserMessageContext(IrcUser user)
{
- this.user = user;
+ m_IrcUser = user;
}
}
}
diff --git a/irc/TechBot/TechBot.Library/ParametersParser.cs b/irc/TechBot/TechBot.Library/ParametersParser.cs
new file mode 100644
index 00000000000..4ce16853518
--- /dev/null
+++ b/irc/TechBot/TechBot.Library/ParametersParser.cs
@@ -0,0 +1,537 @@
+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/SambaBugUrl.cs b/irc/TechBot/TechBot.Library/SambaBugUrl.cs
deleted file mode 100644
index 6b70fac0aeb..00000000000
--- a/irc/TechBot/TechBot.Library/SambaBugUrl.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TechBot.Library
-{
- class SambaBugUrl : BugCommand
- {
- public SambaBugUrl(TechBotService techBot)
- : base(techBot)
- {
- }
-
- public override string[] AvailableCommands
- {
- get { return new string[] { "sambabug" }; }
- }
-
- protected override string BugUrl
- {
- get { return "https://bugzilla.samba.org/show_bug.cgi?id={0}"; }
- }
-
- public override string Help()
- {
- return "!sambabug ";
- }
- }
-}
diff --git a/irc/TechBot/TechBot.Library/ServiceOutput.cs b/irc/TechBot/TechBot.Library/ServiceOutput.cs
index 809cc930819..d73a93e62ea 100644
--- a/irc/TechBot/TechBot.Library/ServiceOutput.cs
+++ b/irc/TechBot/TechBot.Library/ServiceOutput.cs
@@ -2,9 +2,8 @@ using System;
namespace TechBot.Library
{
- public interface IServiceOutput
- {
- void WriteLine(MessageContext context,
- string message);
- }
+ public interface IServiceOutput
+ {
+ void WriteLine(MessageContext context, string message);
+ }
}
diff --git a/irc/TechBot/TechBot.Library/SvnCommand.cs b/irc/TechBot/TechBot.Library/SvnCommand.cs
deleted file mode 100644
index aef633b2b7b..00000000000
--- a/irc/TechBot/TechBot.Library/SvnCommand.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-
-namespace TechBot.Library
-{
- public class SvnCommand : Command
- {
- private string m_SvnRoot;
-
- public SvnCommand(TechBotService techBot)
- : base(techBot)
- {
- m_SvnRoot = Settings.Default.SVNRoot;
- }
-
- public override string[] AvailableCommands
- {
- get { return new string[] { "svn" }; }
- }
-
- public override void Handle(MessageContext context,
- string commandName,
- string parameters)
- {
- TechBot.ServiceOutput.WriteLine(context, string.Format("svn co {0}" , m_SvnRoot));
- }
-
- public override string Help()
- {
- return "!svn";
- }
- }
-}
diff --git a/irc/TechBot/TechBot.Library/TechBot.Library.csproj b/irc/TechBot/TechBot.Library/TechBot.Library.csproj
index 3db836921f6..9cd39a4a7ff 100644
--- a/irc/TechBot/TechBot.Library/TechBot.Library.csproj
+++ b/irc/TechBot/TechBot.Library/TechBot.Library.csproj
@@ -39,21 +39,29 @@
-->
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
@@ -61,10 +69,8 @@
True
Settings.settings
-
+
-
-
diff --git a/irc/TechBot/TechBot.Library/IrcService.cs b/irc/TechBot/TechBot.Library/TechBotIrcService.cs
similarity index 70%
rename from irc/TechBot/TechBot.Library/IrcService.cs
rename to irc/TechBot/TechBot.Library/TechBotIrcService.cs
index bfd2867df36..ec5f70af967 100644
--- a/irc/TechBot/TechBot.Library/IrcService.cs
+++ b/irc/TechBot/TechBot.Library/TechBotIrcService.cs
@@ -1,296 +1,267 @@
-using System;
-using System.Text;
-using System.Collections;
-using System.Threading;
-
-using TechBot.IRCLibrary;
-
-namespace TechBot.Library
-{
- public class IrcService : IServiceOutput
- {
- private string hostname;
- private int port;
- private string channelnames;
- private string botname;
- private string password;
- private string chmPath;
- private string mainChm;
- private string ntstatusXml;
- private string winerrorXml;
- private string hresultXml;
- private string wmXml;
- private string svnCommand;
- private string bugUrl, WineBugUrl, SambaBugUrl;
- private IrcClient m_IrcClient;
- private ArrayList channels = new ArrayList(); /* IrcChannel */
- private TechBotService service;
- private bool isStopped = false;
-
- public IrcService(string hostname,
- int port,
- string channelnames,
- string botname,
- string password,
- string chmPath,
- string mainChm,
- //string ntstatusXml,
- //string winerrorXml,
- //string hresultXml,
- //string wmXml,
- //string svnCommand,
- string BugUrl,
- string WineBugUrl,
- string SambaBugUrl)
- {
- this.hostname = hostname;
- this.port = port;
- this.channelnames = channelnames;
- this.botname = botname;
- if (password == null || password.Trim() == "")
- this.password = null;
- else
- this.password = password;
- this.chmPath = chmPath;
- this.mainChm = mainChm;
- this.ntstatusXml = ntstatusXml;
- this.winerrorXml = winerrorXml;
- this.hresultXml = hresultXml;
- this.wmXml = wmXml;
- this.svnCommand = svnCommand;
- this.bugUrl = BugUrl;
- this.WineBugUrl = WineBugUrl;
- this.SambaBugUrl = SambaBugUrl;
- }
-
- public void Run()
- {
- service = new TechBotService(this,
- chmPath,
- mainChm);
- //ntstatusXml,
- //winerrorXml,
- //hresultXml,
- //wmXml,
- //svnCommand,
- //bugUrl,
- //WineBugUrl,
- //SambaBugUrl);
- service.Run();
-
- m_IrcClient = new IrcClient();
- m_IrcClient.Encoding = Encoding.GetEncoding("iso-8859-1");
- m_IrcClient.MessageReceived += new MessageReceivedHandler(client_MessageReceived);
- m_IrcClient.ChannelUserDatabaseChanged += new ChannelUserDatabaseChangedHandler(client_ChannelUserDatabaseChanged);
- Console.WriteLine("Connecting to {0} port {1}",
- hostname,
- port);
- m_IrcClient.Connect(hostname, port);
- Console.WriteLine("Connected...");
- m_IrcClient.Register(botname, password, null);
- Console.WriteLine("Registered as {0}...", botname);
- JoinChannels();
-
- while (!isStopped)
- {
- Thread.Sleep(1000);
- }
-
- PartChannels();
- m_IrcClient.Diconnect();
- Console.WriteLine("Disconnected...");
- }
-
- public void Stop()
- {
- isStopped = true;
- }
-
- private void JoinChannels()
- {
- foreach (string channelname in channelnames.Split(new char[] { ';' }))
- {
- IrcChannel channel = m_IrcClient.JoinChannel(channelname);
- channels.Add(channel);
- System.Console.WriteLine(String.Format("Joined channel #{0}...",
- channel.Name));
- }
- }
-
- private void PartChannels()
- {
- foreach (IrcChannel channel in channels)
- {
- m_IrcClient.PartChannel(channel, "Caught in the bitstream...");
- System.Console.WriteLine(String.Format("Parted channel #{0}...",
- channel.Name));
- }
- }
-
- private string GetMessageSource(MessageContext context)
- {
- if (context is ChannelMessageContext)
- {
- ChannelMessageContext channelContext = context as ChannelMessageContext;
- return String.Format("#{0}",
- channelContext.Channel.Name);
- }
- else if (context is UserMessageContext)
- {
- UserMessageContext userContext = context as UserMessageContext;
- return userContext.User.Nickname;
- }
- else
- {
- throw new InvalidOperationException(String.Format("Unhandled message context '{0}'",
- context.GetType()));
- }
- }
-
- public void WriteLine(MessageContext context,
- string message)
- {
- if (context is ChannelMessageContext)
- {
- ChannelMessageContext channelContext = context as ChannelMessageContext;
- channelContext.Channel.Talk(message);
- }
- else if (context is UserMessageContext)
- {
- UserMessageContext userContext = context as UserMessageContext;
- userContext.User.Talk(message);
- }
- else
- {
- throw new InvalidOperationException(String.Format("Unhandled message context '{0}'",
- context.GetType()));
- }
- }
-
- private void ExtractMessage(string parameters,
- out string message)
- {
- int startIndex = parameters.IndexOf(':');
- if (startIndex != -1)
- {
- message = parameters.Substring(startIndex + 1);
- }
- else
- {
- message = parameters;
- }
- }
-
- private bool GetChannelName(IrcMessage message,
- out string channelName)
- {
- if (message.Parameters == null || !message.Parameters.StartsWith("#"))
- {
- channelName = null;
- return false;
- }
-
- int index = message.Parameters.IndexOf(' ');
- if (index == -1)
- index = message.Parameters.Length;
- else
- index = index - 1;
- channelName = message.Parameters.Substring(1, index);
- return true;
- }
-
- private bool GetTargetNickname(IrcMessage message,
- out string nickname)
- {
- if (message.Parameters == null)
- {
- nickname = null;
- return false;
- }
-
- int index = message.Parameters.IndexOf(' ');
- if (index == -1)
- index = message.Parameters.Length;
- nickname = message.Parameters.Substring(0, index);
- Console.WriteLine("nickname: " + nickname);
- return true;
- }
-
- private bool ShouldAcceptMessage(IrcMessage message,
- out MessageContext context)
- {
- if (message.Command.ToUpper().Equals("PRIVMSG"))
- {
- string channelName;
- string nickname;
- if (GetChannelName(message,
- out channelName))
- {
- foreach (IrcChannel channel in channels)
- {
- if (String.Compare(channel.Name, channelName, true) == 0)
- {
- context = new ChannelMessageContext(channel);
- return true;
- }
- }
- }
- else if (GetTargetNickname(message,
- out nickname))
- {
- IrcUser targetUser = new IrcUser(m_IrcClient,
- nickname);
- if (String.Compare(targetUser.Nickname, botname, true) == 0)
- {
- IrcUser sourceUser = new IrcUser(m_IrcClient,
- message.PrefixNickname);
- context = new UserMessageContext(sourceUser);
- return true;
- }
- }
- }
- context = null;
- return false;
- }
-
- private void client_MessageReceived(IrcMessage message)
- {
- try
- {
- if (message.Command != null &&
- message.Parameters != null)
- {
- string injectMessage;
- ExtractMessage(message.Parameters,
- out injectMessage);
- MessageContext context;
- if (ShouldAcceptMessage(message,
- out context))
- {
- Console.WriteLine(String.Format("Injecting: {0} from {1}",
- injectMessage,
- GetMessageSource(context)));
- service.InjectMessage(context,
- injectMessage);
- }
- else
- {
- Console.WriteLine("Received: " + message.Line);
- }
- }
- else
- {
- Console.WriteLine("Received: " + message.Line);
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(String.Format("Exception: {0}", ex));
- }
- }
-
- private void client_ChannelUserDatabaseChanged(IrcChannel channel)
- {
- }
- }
-}
+using System;
+using System.Text;
+using System.Collections;
+using System.Threading;
+
+using TechBot.IRCLibrary;
+
+namespace TechBot.Library
+{
+ public class IrcServiceOutput : IServiceOutput
+ {
+ public void WriteLine(MessageContext context,
+ string message)
+ {
+ if (context is ChannelMessageContext)
+ {
+ ChannelMessageContext channelContext = context as ChannelMessageContext;
+ channelContext.Channel.Talk(message);
+ }
+ else if (context is UserMessageContext)
+ {
+ UserMessageContext userContext = context as UserMessageContext;
+ userContext.User.Talk(message);
+ }
+ else
+ {
+ throw new InvalidOperationException(String.Format("Unhandled message context '{0}'",
+ context.GetType()));
+ }
+ }
+ }
+
+ public class IrcTechBotService : TechBotService
+ {
+ private int port;
+ private string hostname;
+ private string channelnames;
+ private string botname;
+ private string password;
+ private string chmPath;
+ private string mainChm;
+ private IrcClient m_IrcClient;
+ private ArrayList channels = new ArrayList();
+ private bool isStopped = false;
+
+ public IrcTechBotService(string hostname,
+ int port,
+ string channelnames,
+ string botname,
+ string password,
+ string chmPath,
+ string mainChm)
+ : base (new IrcServiceOutput() , chmPath , mainChm)
+ {
+ this.hostname = hostname;
+ this.port = port;
+ this.channelnames = channelnames;
+ this.botname = botname;
+ if (password == null || password.Trim() == "")
+ this.password = null;
+ else
+ this.password = password;
+ this.chmPath = chmPath;
+ this.mainChm = mainChm;
+ }
+
+ public override void Run()
+ {
+ //Call the base class
+ base.Run();
+
+ m_IrcClient = new IrcClient();
+ m_IrcClient.Encoding = Encoding.GetEncoding("iso-8859-1");
+ m_IrcClient.MessageReceived += new MessageReceivedHandler(client_MessageReceived);
+ m_IrcClient.ChannelUserDatabaseChanged += new ChannelUserDatabaseChangedHandler(client_ChannelUserDatabaseChanged);
+ Console.WriteLine("Connecting to {0} port {1}",
+ hostname,
+ port);
+ m_IrcClient.Connect(hostname, port);
+ Console.WriteLine("Connected...");
+ m_IrcClient.Register(botname, password, null);
+ Console.WriteLine("Registered as {0}...", botname);
+ JoinChannels();
+
+ while (!isStopped)
+ {
+ Thread.Sleep(1000);
+ }
+
+ PartChannels();
+ m_IrcClient.Diconnect();
+ Console.WriteLine("Disconnected...");
+ }
+
+ public void Stop()
+ {
+ isStopped = true;
+ }
+
+ private void JoinChannels()
+ {
+ foreach (string channelname in channelnames.Split(new char[] { ';' }))
+ {
+ IrcChannel channel = m_IrcClient.JoinChannel(channelname);
+ channels.Add(channel);
+ System.Console.WriteLine(String.Format("Joined channel #{0}...",
+ channel.Name));
+ }
+ }
+
+ private void PartChannels()
+ {
+ foreach (IrcChannel channel in channels)
+ {
+ m_IrcClient.PartChannel(channel, "Caught in the bitstream...");
+ System.Console.WriteLine(String.Format("Parted channel #{0}...",
+ channel.Name));
+ }
+ }
+
+ private string GetMessageSource(MessageContext context)
+ {
+ if (context is ChannelMessageContext)
+ {
+ ChannelMessageContext channelContext = context as ChannelMessageContext;
+ return String.Format("#{0}",
+ channelContext.Channel.Name);
+ }
+ else if (context is UserMessageContext)
+ {
+ UserMessageContext userContext = context as UserMessageContext;
+ return userContext.User.Nickname;
+ }
+ else
+ {
+ throw new InvalidOperationException(String.Format("Unhandled message context '{0}'",
+ context.GetType()));
+ }
+ }
+
+ private void ExtractMessage(string parameters,
+ out string message)
+ {
+ int startIndex = parameters.IndexOf(':');
+ if (startIndex != -1)
+ {
+ message = parameters.Substring(startIndex + 1);
+ }
+ else
+ {
+ message = parameters;
+ }
+ }
+
+ private bool GetChannelName(IrcMessage message,
+ out string channelName)
+ {
+ if (message.Parameters == null || !message.Parameters.StartsWith("#"))
+ {
+ channelName = null;
+ return false;
+ }
+
+ int index = message.Parameters.IndexOf(' ');
+ if (index == -1)
+ index = message.Parameters.Length;
+ else
+ index = index - 1;
+ channelName = message.Parameters.Substring(1, index);
+ return true;
+ }
+
+ private bool GetTargetNickname(IrcMessage message,
+ out string nickname)
+ {
+ if (message.Parameters == null)
+ {
+ nickname = null;
+ return false;
+ }
+
+ int index = message.Parameters.IndexOf(' ');
+ if (index == -1)
+ index = message.Parameters.Length;
+ nickname = message.Parameters.Substring(0, index);
+ Console.WriteLine("nickname: " + nickname);
+ return true;
+ }
+
+ private bool ShouldAcceptMessage(IrcMessage message,
+ out MessageContext context)
+ {
+ if (message.Command.ToUpper().Equals("PRIVMSG"))
+ {
+ string channelName;
+ string nickname;
+ if (GetChannelName(message,
+ out channelName))
+ {
+ foreach (IrcChannel channel in channels)
+ {
+ if (String.Compare(channel.Name, channelName, true) == 0)
+ {
+ context = new ChannelMessageContext(channel);
+ return true;
+ }
+ }
+ }
+ else if (GetTargetNickname(message,
+ out nickname))
+ {
+ IrcUser targetUser = new IrcUser(m_IrcClient,
+ nickname);
+ if (String.Compare(targetUser.Nickname, botname, true) == 0)
+ {
+ IrcUser sourceUser = new IrcUser(m_IrcClient,
+ message.PrefixNickname);
+ context = new UserMessageContext(sourceUser);
+ return true;
+ }
+ }
+ }
+ context = null;
+ return false;
+ }
+
+ private void client_MessageReceived(IrcMessage message)
+ {
+ try
+ {
+ if (message.Command != null &&
+ message.Parameters != null)
+ {
+ string injectMessage;
+ ExtractMessage(message.Parameters,
+ out injectMessage);
+ MessageContext context;
+ if (ShouldAcceptMessage(message,
+ out context))
+ {
+ Console.WriteLine(String.Format("Injecting: {0} from {1}",
+ injectMessage,
+ GetMessageSource(context)));
+ InjectMessage(context,
+ injectMessage);
+ }
+ else
+ {
+ Console.WriteLine("Received: " + message.Line);
+ }
+ }
+ else
+ {
+ Console.WriteLine("Received: " + message.Line);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(String.Format("Exception: {0}", ex));
+ }
+ }
+
+ private void client_ChannelUserDatabaseChanged(IrcChannel channel)
+ {
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot.Library/TechBotService.cs b/irc/TechBot/TechBot.Library/TechBotService.cs
index d40ab91e2c7..bb0bb5563d8 100644
--- a/irc/TechBot/TechBot.Library/TechBotService.cs
+++ b/irc/TechBot/TechBot.Library/TechBotService.cs
@@ -4,63 +4,29 @@ using System.Collections.Generic;
using System.IO;
using System.Data;
using System.Threading;
+
using TechBot.IRCLibrary;
namespace TechBot.Library
{
- public class TechBotService
+ public abstract class TechBotService
{
- private IServiceOutput serviceOutput;
+ protected IServiceOutput serviceOutput;
private string chmPath;
private string mainChm;
- private string ntstatusXml;
- private string winerrorXml;
- private string hresultXml;
- private string wmXml;
- private string svnCommand;
- private string bugUrl, WineBugUrl, SambaBugUrl;
- private List commands = new List();
public TechBotService(IServiceOutput serviceOutput,
string chmPath,
string mainChm)
- //string ntstatusXml,
- //string winerrorXml,
- //string hresultXml,
- //string wmXml,
- //string svnCommand,
- //string bugUrl,
- //string WineBugUrl,
- //string SambaBugUrl)
{
this.serviceOutput = serviceOutput;
this.chmPath = chmPath;
this.mainChm = mainChm;
- this.ntstatusXml = ntstatusXml;
- this.winerrorXml = winerrorXml;
- this.hresultXml = hresultXml;
- this.wmXml = wmXml;
- this.svnCommand = svnCommand;
- this.bugUrl = bugUrl;
- this.WineBugUrl = WineBugUrl;
- this.SambaBugUrl = SambaBugUrl;
}
- public void Run()
+ public virtual void Run()
{
- commands.Add(new HelpCommand(this));
- /*commands.Add(new ApiCommand(serviceOutput,
- chmPath,
- mainChm));*/
- commands.Add(new NtStatusCommand(this));
- commands.Add(new WinerrorCommand(this));
- commands.Add(new HResultCommand(this));
- commands.Add(new ErrorCommand(this));
- commands.Add(new WMCommand(this));
- commands.Add(new SvnCommand(this));
- commands.Add(new ReactOSBugUrl(this));
- commands.Add(new SambaBugUrl(this));
- commands.Add(new WineBugUrl(this));
+ CommandFactory.LoadPlugins();
}
public IServiceOutput ServiceOutput
@@ -68,18 +34,16 @@ namespace TechBot.Library
get { return serviceOutput; }
}
- public IList Commands
+ public CommandBuilderCollection Commands
{
- get { return commands; }
+ get { return CommandFactory.Commands; }
+ }
+
+ public void InjectMessage(MessageContext context, string message)
+ {
+ ParseCommandMessage(context,
+ message);
}
-
- public void InjectMessage(MessageContext context,
- string message)
- {
- if (message.StartsWith("!"))
- ParseCommandMessage(context,
- message);
- }
private bool IsCommandMessage(string message)
{
@@ -104,19 +68,21 @@ namespace TechBot.Library
else
commandName = message.Trim();
- foreach (Command command in commands)
- {
- foreach (string cmd in command.AvailableCommands)
+ foreach (CommandBuilder command in Commands)
+ {
+ if (command.Name == commandName)
{
- if (cmd == commandName)
- {
- command.Handle(context,
- commandName,
- commandParams);
- return;
- }
+ //Create a new instance of the required command type
+ Command cmd = command.CreateCommand();
+
+ cmd.TechBot = this;
+ cmd.Context = context;
+ cmd.ParseParameters(message);
+ cmd.ExecuteCommand();
+
+ return;
}
- }
+ }
}
}
}
diff --git a/irc/TechBot/TechBot.Library/WineBugUrl.cs b/irc/TechBot/TechBot.Library/WineBugUrl.cs
deleted file mode 100644
index 94464a1fdc8..00000000000
--- a/irc/TechBot/TechBot.Library/WineBugUrl.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TechBot.Library
-{
- class WineBugUrl : BugCommand
- {
- public WineBugUrl(TechBotService techBot)
- : base(techBot)
- {
- }
-
- public override string[] AvailableCommands
- {
- get { return new string[] { "winebug" }; }
- }
-
- protected override string BugUrl
- {
- get { return "http://bugs.winehq.org/show_bug.cgi?id={0}"; }
- }
-
- public override string Help()
- {
- return "!winebug ";
- }
- }
-}
diff --git a/irc/TechBot/TechBot.cmbx b/irc/TechBot/TechBot.cmbx
deleted file mode 100644
index 3e8915e180a..00000000000
--- a/irc/TechBot/TechBot.cmbx
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/irc/TechBot/TechBot/ProjectInstaller.cs b/irc/TechBot/TechBot/ProjectInstaller.cs
new file mode 100644
index 00000000000..0dc2b152a6e
--- /dev/null
+++ b/irc/TechBot/TechBot/ProjectInstaller.cs
@@ -0,0 +1,28 @@
+using System;
+using System.ComponentModel;
+using System.ServiceProcess;
+using System.Configuration.Install;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TechBot
+{
+ [RunInstaller(true)]
+ public class ProjectInstaller : Installer
+ {
+ public ProjectInstaller()
+ {
+ ServiceProcessInstaller spi = null;
+ ServiceInstaller si = null;
+
+ spi = new ServiceProcessInstaller();
+ spi.Account = ServiceAccount.LocalSystem;
+
+ si = new ServiceInstaller();
+ si.ServiceName = "TechBot";
+ si.StartType = ServiceStartMode.Automatic;
+
+ Installers.AddRange(new Installer[] { spi, si });
+ }
+ }
+}
diff --git a/irc/TechBot/TechBot/ServiceThread.cs b/irc/TechBot/TechBot/ServiceThread.cs
index 9e22beb25fb..0675bca22b6 100644
--- a/irc/TechBot/TechBot/ServiceThread.cs
+++ b/irc/TechBot/TechBot/ServiceThread.cs
@@ -51,21 +51,21 @@ namespace TechBot
SetupConfiguration();
System.Console.WriteLine("TechBot irc service...");
- IrcService ircService = new IrcService(IRCServerHostName,
+ IrcTechBotService ircService = new IrcTechBotService(IRCServerHostName,
IRCServerHostPort,
IRCChannelNames,
IRCBotName,
IRCBotPassword,
ChmPath,
- MainChm,
+ MainChm);
//NtstatusXml,
//WinerrorXml,
//HresultXml,
//WmXml,
//SvnCommand,
- BugUrl,
- WineBugUrl,
- SambaBugUrl);
+ //BugUrl,
+ //WineBugUrl,
+ //SambaBugUrl);
ircService.Run();
}
diff --git a/irc/TechBot/TechBot/TechBot.csproj b/irc/TechBot/TechBot/TechBot.csproj
index 692e4739541..85fc4791e03 100644
--- a/irc/TechBot/TechBot/TechBot.csproj
+++ b/irc/TechBot/TechBot/TechBot.csproj
@@ -42,6 +42,9 @@
+
+ Component
+
Component
@@ -52,6 +55,7 @@
+
diff --git a/irc/TechBot/TechBot/TechBotService.cs b/irc/TechBot/TechBot/TechBotService.cs
index 79fca2d38d3..362ce849d0f 100644
--- a/irc/TechBot/TechBot/TechBotService.cs
+++ b/irc/TechBot/TechBot/TechBotService.cs
@@ -80,18 +80,3 @@ namespace TechBot
}
}
}
-
-[RunInstaller(true)]
-public class ProjectInstaller : Installer
-{
- public ProjectInstaller()
- {
- ServiceProcessInstaller spi = new ServiceProcessInstaller();
- spi.Account = ServiceAccount.LocalSystem;
-
- ServiceInstaller si = new ServiceInstaller();
- si.ServiceName = "TechBot";
- si.StartType = ServiceStartMode.Automatic;
- Installers.AddRange(new Installer[] {spi, si});
- }
-}