diff --git a/irc/TechBot/TechBot.Console/App.config b/irc/TechBot/TechBot.Console/App.config index bdb4e734fac..f7fa9ac9905 100644 --- a/irc/TechBot/TechBot.Console/App.config +++ b/irc/TechBot/TechBot.Console/App.config @@ -3,7 +3,7 @@ - + diff --git a/irc/TechBot/TechBot.Console/Main.cs b/irc/TechBot/TechBot.Console/Main.cs index 9705e678925..f658ec38cde 100644 --- a/irc/TechBot/TechBot.Console/Main.cs +++ b/irc/TechBot/TechBot.Console/Main.cs @@ -6,7 +6,8 @@ namespace TechBot.Console { public class ConsoleServiceOutput : IServiceOutput { - public void WriteLine(string message) + public void WriteLine(MessageContext context, + string message) { System.Console.WriteLine(message); } @@ -49,11 +50,11 @@ namespace TechBot.Console } } - private static string IRCChannelName + private static string IRCChannelNames { get { - string optionName = "IRCChannelName"; + string optionName = "IRCChannelNames"; string s = ConfigurationSettings.AppSettings[optionName]; VerifyRequiredOption(optionName, s); @@ -149,7 +150,7 @@ namespace TechBot.Console { IrcService ircService = new IrcService(IRCServerHostName, IRCServerHostPort, - IRCChannelName, + IRCChannelNames, IRCBotName, ChmPath, MainChm, @@ -180,7 +181,8 @@ namespace TechBot.Console while (true) { string s = System.Console.ReadLine(); - service.InjectMessage(s); + service.InjectMessage(null, + s); } } } diff --git a/irc/TechBot/TechBot.Library/ApiCommand.cs b/irc/TechBot/TechBot.Library/ApiCommand.cs index 767a3b2f1eb..b6aab953f09 100644 --- a/irc/TechBot/TechBot.Library/ApiCommand.cs +++ b/irc/TechBot/TechBot.Library/ApiCommand.cs @@ -26,10 +26,12 @@ namespace TechBot.Library Run(); } - private void WriteIfVerbose(string message) + private void WriteIfVerbose(MessageContext context, + string message) { if (IsVerbose) - serviceOutput.WriteLine(message); + serviceOutput.WriteLine(context, + message); } private void Run() @@ -70,13 +72,15 @@ namespace TechBot.Library new string[] { "api" }); } - public void Handle(string commandName, + public void Handle(MessageContext context, + string commandName, string parameters) { if (parameters.Trim().Equals(String.Empty)) - DisplayNoKeyword(); + DisplayNoKeyword(context); else - Search(parameters); + Search(context, + parameters); } public string Help() @@ -84,7 +88,8 @@ namespace TechBot.Library return "!api "; } - private bool SearchIndex(string keyword) + private bool SearchIndex(MessageContext context, + string keyword) { if (chm.HasIndex) { @@ -92,14 +97,18 @@ namespace TechBot.Library IndexType.KeywordLinks); if (item != null && item.Topics.Count > 0) { - WriteIfVerbose(String.Format("Keyword {0} found in index", + WriteIfVerbose(context, + String.Format("Keyword {0} found in index", item.KeyWord)); IndexTopic indexTopic = item.Topics[0] as IndexTopic; - return DisplayResult(keyword, indexTopic); + return DisplayResult(context, + keyword, + indexTopic); } else { - WriteIfVerbose(String.Format("Keyword {0} not found in index", + WriteIfVerbose(context, + String.Format("Keyword {0} not found in index", keyword)); return false; } @@ -108,14 +117,12 @@ namespace TechBot.Library return false; } - private void SearchFullText(string keyword) + private void SearchFullText(MessageContext context, + string keyword) { string sort = "Rating ASC"; -/* - sort = "Location ASC"); - sort = "Title ASC"); -*/ - WriteIfVerbose(String.Format("Searching fulltext database for {0}", + WriteIfVerbose(context, + String.Format("Searching fulltext database for {0}", keyword)); bool partialMatches = false; @@ -125,47 +132,58 @@ namespace TechBot.Library maxResults, partialMatches, titlesOnly); - WriteIfVerbose(String.Format("results.Rows.Count = {0}", + 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(keyword, results)) + if (!DisplayResult(context, + keyword, + results)) { - DisplayNoResult(keyword); + DisplayNoResult(context, + keyword); } } else { - DisplayNoResult(keyword); + DisplayNoResult(context, + keyword); } } - private void Search(string keyword) + private void Search(MessageContext context, + string keyword) { - if (!SearchIndex(keyword)) - { - SearchFullText(keyword); - } + if (!SearchIndex(context, + keyword)) + SearchFullText(context, + keyword); } - private bool DisplayResult(string keyword, + private bool DisplayResult(MessageContext context, + string keyword, IndexTopic indexTopic) { keyword = keyword.Trim().ToLower(); string url = indexTopic.URL; - WriteIfVerbose(String.Format("URL from index search {0}", + WriteIfVerbose(context, + String.Format("URL from index search {0}", url)); - string prototype = ExtractPrototype(url); + string prototype = ExtractPrototype(context, + url); if (prototype == null || prototype.Trim().Equals(String.Empty)) return false; string formattedPrototype = FormatPrototype(prototype); - serviceOutput.WriteLine(formattedPrototype); + serviceOutput.WriteLine(context, + formattedPrototype); return true; } - private bool DisplayResult(string keyword, + private bool DisplayResult(MessageContext context, + string keyword, DataTable results) { keyword = keyword.Trim().ToLower(); @@ -173,31 +191,38 @@ namespace TechBot.Library { DataRowView row = results.DefaultView[i]; string title = row["Title"].ToString(); - WriteIfVerbose(String.Format("Examining {0}", title)); + 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(url); + string prototype = ExtractPrototype(context, + url); if (prototype == null || prototype.Trim().Equals(String.Empty)) continue; string formattedPrototype = FormatPrototype(prototype); - serviceOutput.WriteLine(formattedPrototype); + serviceOutput.WriteLine(context, + formattedPrototype); return true; } } return false; } - private void DisplayNoResult(string keyword) + private void DisplayNoResult(MessageContext context, + string keyword) { - serviceOutput.WriteLine(String.Format("I don't know about keyword {0}", keyword)); + serviceOutput.WriteLine(context, + String.Format("I don't know about keyword {0}", + keyword)); } - private void DisplayNoKeyword() + private void DisplayNoKeyword(MessageContext context) { - serviceOutput.WriteLine("Please give me a keyword."); + serviceOutput.WriteLine(context, + "Please give me a keyword."); } private string ReplaceComments(string s) @@ -241,9 +266,11 @@ namespace TechBot.Library return s; } - private string ExtractPrototype(string url) + private string ExtractPrototype(MessageContext context, + string url) { - string page = GetPage(url); + string page = GetPage(context, + url); Match match = Regex.Match(page, "
(.+)
", RegexOptions.Multiline | @@ -273,7 +300,8 @@ namespace TechBot.Library return Regex.Replace(html, @"<(.|\n)*?>", String.Empty); } - private string GetPage(string url) + private string GetPage(MessageContext context, + string url) { string CHMFileName = ""; string topicName = ""; @@ -288,7 +316,8 @@ namespace TechBot.Library } else { - baseStream = GetBaseStreamFromCHMFileName(CHMFileName); + baseStream = GetBaseStreamFromCHMFileName(context, + CHMFileName); } if ((topicName == "") || (CHMFileName == "") || (baseStream == null)) @@ -299,11 +328,13 @@ namespace TechBot.Library return baseStream.ExtractTextFile(topicName); } - private CHMStream.CHMStream GetBaseStreamFromCHMFileName(string CHMFileName) + private CHMStream.CHMStream GetBaseStreamFromCHMFileName(MessageContext context, + string CHMFileName) { foreach (CHMFile file in chm.FileList) { - WriteIfVerbose(String.Format("Compare: {0} <> {1}", + WriteIfVerbose(context, + String.Format("Compare: {0} <> {1}", file.ChmFilePath, CHMFileName)); if (file.ChmFilePath.ToLower().Equals(CHMFileName.ToLower())) @@ -311,7 +342,8 @@ namespace TechBot.Library return file.BaseStream; } } - WriteIfVerbose(String.Format("Could not find loaded CHM file in list: {0}", + WriteIfVerbose(context, + String.Format("Could not find loaded CHM file in list: {0}", CHMFileName)); return null; } diff --git a/irc/TechBot/TechBot.Library/HelpCommand.cs b/irc/TechBot/TechBot.Library/HelpCommand.cs index b38cffb9268..4e5ce731fb2 100644 --- a/irc/TechBot/TechBot.Library/HelpCommand.cs +++ b/irc/TechBot/TechBot.Library/HelpCommand.cs @@ -21,12 +21,17 @@ namespace TechBot.Library new string[] { "help" }); } - public void Handle(string commandName, + public void Handle(MessageContext context, + string commandName, string parameters) { - serviceOutput.WriteLine("I support the following commands:"); + serviceOutput.WriteLine(context, + "I support the following commands:"); foreach (ICommand command in commands) - serviceOutput.WriteLine(command.Help()); + { + serviceOutput.WriteLine(context, + command.Help()); + } } public string Help() diff --git a/irc/TechBot/TechBot.Library/HresultCommand.cs b/irc/TechBot/TechBot.Library/HresultCommand.cs index a81567e5e50..df9ef4ead76 100644 --- a/irc/TechBot/TechBot.Library/HresultCommand.cs +++ b/irc/TechBot/TechBot.Library/HresultCommand.cs @@ -24,13 +24,15 @@ namespace TechBot.Library new string[] { "hresult" }); } - public void Handle(string commandName, + public void Handle(MessageContext context, + string commandName, string parameters) { string hresultText = parameters; if (hresultText.Equals(String.Empty)) { - serviceOutput.WriteLine("Please provide a valid HRESULT value."); + serviceOutput.WriteLine(context, + "Please provide a valid HRESULT value."); return; } @@ -38,7 +40,8 @@ namespace TechBot.Library long hresult = np.Parse(hresultText); if (np.Error) { - serviceOutput.WriteLine(String.Format("{0} is not a valid HRESULT value.", + serviceOutput.WriteLine(context, + String.Format("{0} is not a valid HRESULT value.", hresultText)); return; } @@ -46,13 +49,15 @@ namespace TechBot.Library string description = GetHresultDescription(hresult); if (description != null) { - serviceOutput.WriteLine(String.Format("{0} is {1}.", + serviceOutput.WriteLine(context, + String.Format("{0} is {1}.", hresultText, description)); } else { - serviceOutput.WriteLine(String.Format("I don't know about HRESULT {0}.", + serviceOutput.WriteLine(context, + String.Format("I don't know about HRESULT {0}.", hresultText)); } } diff --git a/irc/TechBot/TechBot.Library/ICommand.cs b/irc/TechBot/TechBot.Library/ICommand.cs index 3c9edea0694..b88c911e70a 100644 --- a/irc/TechBot/TechBot.Library/ICommand.cs +++ b/irc/TechBot/TechBot.Library/ICommand.cs @@ -5,7 +5,8 @@ namespace TechBot.Library public interface ICommand { bool CanHandle(string commandName); - void Handle(string commandName, + void Handle(MessageContext context, + string commandName, string parameters); string Help(); } diff --git a/irc/TechBot/TechBot.Library/IrcService.cs b/irc/TechBot/TechBot.Library/IrcService.cs index 42abdec94b8..efb9d60b01c 100644 --- a/irc/TechBot/TechBot.Library/IrcService.cs +++ b/irc/TechBot/TechBot.Library/IrcService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Threading; using TechBot.IRCLibrary; @@ -8,7 +9,7 @@ namespace TechBot.Library { private string hostname; private int port; - private string channelname; + private string channelnames; private string botname; private string chmPath; private string mainChm; @@ -17,13 +18,13 @@ namespace TechBot.Library private string hresultXml; private string svnCommand; private IrcClient client; - private IrcChannel channel1; + private ArrayList channels = new ArrayList(); /* IrcChannel */ private TechBotService service; private bool isStopped = false; public IrcService(string hostname, int port, - string channelname, + string channelnames, string botname, string chmPath, string mainChm, @@ -34,7 +35,7 @@ namespace TechBot.Library { this.hostname = hostname; this.port = port; - this.channelname = channelname; + this.channelnames = channelnames; this.botname = botname; this.chmPath = chmPath; this.mainChm = mainChm; @@ -65,28 +66,51 @@ namespace TechBot.Library System.Console.WriteLine("Connected..."); client.Register(botname, null); System.Console.WriteLine(String.Format("Registered as {0}...", botname)); - channel1 = client.JoinChannel(channelname); - System.Console.WriteLine(String.Format("Joined channel {0}...", channelname)); + JoinChannels(); while (!isStopped) { Thread.Sleep(1000); } - client.PartChannel(channel1, "Caught in the bitstream..."); + PartChannels(); client.Diconnect(); System.Console.WriteLine("Disconnected..."); } - + public void Stop() { isStopped = true; } - - public void WriteLine(string message) + + private void JoinChannels() { - Console.WriteLine(String.Format("Sending: {0}", message)); - channel1.Talk(message); + foreach (string channelname in channelnames.Split(new char[] { ';' })) + { + IrcChannel channel = client.JoinChannel(channelname); + channels.Add(channel); + System.Console.WriteLine(String.Format("Joined channel #{0}...", + channel.Name)); + } + } + + private void PartChannels() + { + foreach (IrcChannel channel in channels) + { + client.PartChannel(channel, "Caught in the bitstream..."); + System.Console.WriteLine(String.Format("Parted channel #{0}...", + channel.Name)); + } + } + + public void WriteLine(MessageContext context, + string message) + { + Console.WriteLine(String.Format("Sending: {0} to #{1}", + message, + context.Channel != null ? context.Channel.Name : "(null)")); + context.Channel.Talk(message); } private void ExtractMessage(string parameters, @@ -102,22 +126,65 @@ namespace TechBot.Library 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; + channelName = message.Parameters.Substring(1, index - 1); + return true; + } + + private bool ShouldAcceptMessage(IrcMessage message, + out MessageContext context) + { + if (message.Command.ToUpper().Equals("PRIVMSG")) + { + string channelName; + if (GetChannelName(message, + out channelName)) + { + foreach (IrcChannel channel in channels) + { + if (String.Compare(channel.Name, channelName, true) == 0) + { + context = new MessageContext(channel); + return true; + } + } + } + } + context = null; + return false; + } + private void client_MessageReceived(IrcMessage message) { try { - if (channel1 != null && - channel1.Name != null && + if (message.Command != null && message.Parameters != null) { string injectMessage; - ExtractMessage(message.Parameters, out injectMessage); - if ((message.Command.ToUpper().Equals("PRIVMSG")) && - (message.Parameters.ToLower().StartsWith("#" + channel1.Name.ToLower() + " "))) + ExtractMessage(message.Parameters, + out injectMessage); + MessageContext context; + if (ShouldAcceptMessage(message, + out context)) { - Console.WriteLine("Injecting: " + injectMessage); - service.InjectMessage(injectMessage); + Console.WriteLine(String.Format("Injecting: {0} from #{1}", + injectMessage, + context.Channel.Name)); + service.InjectMessage(context, + injectMessage); } else { diff --git a/irc/TechBot/TechBot.Library/MessageContext.cs b/irc/TechBot/TechBot.Library/MessageContext.cs new file mode 100644 index 00000000000..dca3925fdad --- /dev/null +++ b/irc/TechBot/TechBot.Library/MessageContext.cs @@ -0,0 +1,23 @@ +using System; +using TechBot.IRCLibrary; + +namespace TechBot.Library +{ + public class MessageContext + { + private IrcChannel channel; + + public IrcChannel Channel + { + get + { + return channel; + } + } + + public MessageContext(IrcChannel channel) + { + this.channel = channel; + } + } +} diff --git a/irc/TechBot/TechBot.Library/NtStatusCommand.cs b/irc/TechBot/TechBot.Library/NtStatusCommand.cs index 081d60a841a..6841156f1e5 100644 --- a/irc/TechBot/TechBot.Library/NtStatusCommand.cs +++ b/irc/TechBot/TechBot.Library/NtStatusCommand.cs @@ -24,13 +24,15 @@ namespace TechBot.Library new string[] { "ntstatus" }); } - public void Handle(string commandName, + public void Handle(MessageContext context, + string commandName, string parameters) { string ntstatusText = parameters; if (ntstatusText.Equals(String.Empty)) { - serviceOutput.WriteLine("Please provide a valid NTSTATUS value."); + serviceOutput.WriteLine(context, + "Please provide a valid NTSTATUS value."); return; } @@ -38,7 +40,8 @@ namespace TechBot.Library long ntstatus = np.Parse(ntstatusText); if (np.Error) { - serviceOutput.WriteLine(String.Format("{0} is not a valid NTSTATUS value.", + serviceOutput.WriteLine(context, + String.Format("{0} is not a valid NTSTATUS value.", ntstatusText)); return; } @@ -46,13 +49,15 @@ namespace TechBot.Library string description = GetNtstatusDescription(ntstatus); if (description != null) { - serviceOutput.WriteLine(String.Format("{0} is {1}.", + serviceOutput.WriteLine(context, + String.Format("{0} is {1}.", ntstatusText, description)); } else { - serviceOutput.WriteLine(String.Format("I don't know about NTSTATUS {0}.", + serviceOutput.WriteLine(context, + String.Format("I don't know about NTSTATUS {0}.", ntstatusText)); } } diff --git a/irc/TechBot/TechBot.Library/ServiceOutput.cs b/irc/TechBot/TechBot.Library/ServiceOutput.cs index c0d4474f1ae..809cc930819 100644 --- a/irc/TechBot/TechBot.Library/ServiceOutput.cs +++ b/irc/TechBot/TechBot.Library/ServiceOutput.cs @@ -4,6 +4,7 @@ namespace TechBot.Library { public interface IServiceOutput { - void WriteLine(string message); + void WriteLine(MessageContext context, + string message); } } diff --git a/irc/TechBot/TechBot.Library/SvnCommand.cs b/irc/TechBot/TechBot.Library/SvnCommand.cs index 32c77cc380d..7b2fce56cee 100644 --- a/irc/TechBot/TechBot.Library/SvnCommand.cs +++ b/irc/TechBot/TechBot.Library/SvnCommand.cs @@ -20,10 +20,12 @@ namespace TechBot.Library new string[] { "svn" }); } - public void Handle(string commandName, + public void Handle(MessageContext context, + string commandName, string parameters) { - serviceOutput.WriteLine(svnCommand); + serviceOutput.WriteLine(context, + svnCommand); } public string Help() diff --git a/irc/TechBot/TechBot.Library/TechBotService.cs b/irc/TechBot/TechBot.Library/TechBotService.cs index 32a8ec360f6..aede24db4fe 100644 --- a/irc/TechBot/TechBot.Library/TechBotService.cs +++ b/irc/TechBot/TechBot.Library/TechBotService.cs @@ -9,8 +9,6 @@ namespace TechBot.Library { public class TechBotService { - private const bool IsVerbose = false; - private IServiceOutput serviceOutput; private string chmPath; private string mainChm; @@ -37,12 +35,6 @@ namespace TechBot.Library this.svnCommand = svnCommand; } - private void WriteIfVerbose(string message) - { - if (IsVerbose) - serviceOutput.WriteLine(message); - } - public void Run() { commands.Add(new HelpCommand(serviceOutput, @@ -60,12 +52,12 @@ namespace TechBot.Library svnCommand)); } - public void InjectMessage(string message) + public void InjectMessage(MessageContext context, + string message) { if (message.StartsWith("!")) - { - ParseCommandMessage(message); - } + ParseCommandMessage(context, + message); } private bool IsCommandMessage(string message) @@ -73,7 +65,8 @@ namespace TechBot.Library return message.StartsWith("!"); } - public void ParseCommandMessage(string message) + public void ParseCommandMessage(MessageContext context, + string message) { if (!IsCommandMessage(message)) return; @@ -94,7 +87,8 @@ namespace TechBot.Library { if (command.CanHandle(commandName)) { - command.Handle(commandName, parameters); + command.Handle(context, + commandName, parameters); return; } } diff --git a/irc/TechBot/TechBot.Library/WinerrorCommand.cs b/irc/TechBot/TechBot.Library/WinerrorCommand.cs index 5e92b818cf6..ad01acaec14 100644 --- a/irc/TechBot/TechBot.Library/WinerrorCommand.cs +++ b/irc/TechBot/TechBot.Library/WinerrorCommand.cs @@ -24,13 +24,15 @@ namespace TechBot.Library new string[] { "winerror" }); } - public void Handle(string commandName, + public void Handle(MessageContext context, + string commandName, string parameters) { string winerrorText = parameters; if (winerrorText.Equals(String.Empty)) { - serviceOutput.WriteLine("Please provide a valid System Error Code value."); + serviceOutput.WriteLine(context, + "Please provide a valid System Error Code value."); return; } @@ -38,7 +40,8 @@ namespace TechBot.Library long winerror = np.Parse(winerrorText); if (np.Error) { - serviceOutput.WriteLine(String.Format("{0} is not a valid System Error Code value.", + serviceOutput.WriteLine(context, + String.Format("{0} is not a valid System Error Code value.", winerrorText)); return; } @@ -46,13 +49,15 @@ namespace TechBot.Library string description = GetWinerrorDescription(winerror); if (description != null) { - serviceOutput.WriteLine(String.Format("{0} is {1}.", + serviceOutput.WriteLine(context, + String.Format("{0} is {1}.", winerrorText, description)); } else { - serviceOutput.WriteLine(String.Format("I don't know about System Error Code {0}.", + serviceOutput.WriteLine(context, + String.Format("I don't know about System Error Code {0}.", winerrorText)); } } diff --git a/irc/TechBot/TechBot/App.config b/irc/TechBot/TechBot/App.config index bdb4e734fac..f7fa9ac9905 100644 --- a/irc/TechBot/TechBot/App.config +++ b/irc/TechBot/TechBot/App.config @@ -3,7 +3,7 @@ - + diff --git a/irc/TechBot/TechBot/ServiceThread.cs b/irc/TechBot/TechBot/ServiceThread.cs index 0fd814562ba..728eb959688 100644 --- a/irc/TechBot/TechBot/ServiceThread.cs +++ b/irc/TechBot/TechBot/ServiceThread.cs @@ -9,7 +9,7 @@ namespace TechBot { private string IRCServerHostName; private int IRCServerHostPort; - private string IRCChannelName; + private string IRCChannelNames; private string IRCBotName; private string ChmPath; private string MainChm; @@ -28,7 +28,7 @@ namespace TechBot { IRCServerHostName = ConfigurationSettings.AppSettings["IRCServerHostName"]; IRCServerHostPort = Int32.Parse(ConfigurationSettings.AppSettings["IRCServerHostPort"]); - IRCChannelName = ConfigurationSettings.AppSettings["IRCChannelName"]; + IRCChannelNames = ConfigurationSettings.AppSettings["IRCChannelNames"]; IRCBotName = ConfigurationSettings.AppSettings["IRCBotName"]; ChmPath = ConfigurationSettings.AppSettings["ChmPath"]; MainChm = ConfigurationSettings.AppSettings["MainChm"]; @@ -45,7 +45,7 @@ namespace TechBot IrcService ircService = new IrcService(IRCServerHostName, IRCServerHostPort, - IRCChannelName, + IRCChannelNames, IRCBotName, ChmPath, MainChm,