Support multiple channels
Modified: trunk/irc/TechBot/TechBot/App.config
Modified: trunk/irc/TechBot/TechBot/ServiceThread.cs
Modified: trunk/irc/TechBot/TechBot.Console/App.config
Modified: trunk/irc/TechBot/TechBot.Console/Main.cs
Modified: trunk/irc/TechBot/TechBot.Library/ApiCommand.cs
Modified: trunk/irc/TechBot/TechBot.Library/HelpCommand.cs
Modified: trunk/irc/TechBot/TechBot.Library/HresultCommand.cs
Modified: trunk/irc/TechBot/TechBot.Library/ICommand.cs
Modified: trunk/irc/TechBot/TechBot.Library/IrcService.cs
Added: trunk/irc/TechBot/TechBot.Library/MessageContext.cs
Modified: trunk/irc/TechBot/TechBot.Library/NtStatusCommand.cs
Modified: trunk/irc/TechBot/TechBot.Library/ServiceOutput.cs
Modified: trunk/irc/TechBot/TechBot.Library/SvnCommand.cs
Modified: trunk/irc/TechBot/TechBot.Library/TechBotService.cs
Modified: trunk/irc/TechBot/TechBot.Library/WinerrorCommand.cs

Modified: trunk/irc/TechBot/TechBot/App.config
--- trunk/irc/TechBot/TechBot/App.config	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot/App.config	2005-02-16 21:07:55 UTC (rev 13604)
@@ -3,7 +3,7 @@
 	<appSettings>
 		<add key="IRCServerHostName" value="irc.eu.freenode.net" />
 		<add key="IRCServerHostPort" value="6667" />
-		<add key="IRCChannelName" value="channel" />
+		<add key="IRCChannelNames" value="channel1;channel2" />
 		<add key="IRCBotName" value="MyBot" />
 		<add key="ChmPath" value="C:\IRC\TechBot\CHM" />
 		<add key="MainChm" value="kmarch.chm" />

Modified: trunk/irc/TechBot/TechBot/ServiceThread.cs
--- trunk/irc/TechBot/TechBot/ServiceThread.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot/ServiceThread.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -9,7 +9,7 @@
 	{
 		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 @@
 		{
 			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 @@
 			
 			IrcService ircService = new IrcService(IRCServerHostName,
 			                                       IRCServerHostPort,
-			                                       IRCChannelName,
+			                                       IRCChannelNames,
 			                                       IRCBotName,
 			                                       ChmPath,
 			                                       MainChm,

Modified: trunk/irc/TechBot/TechBot.Console/App.config
--- trunk/irc/TechBot/TechBot.Console/App.config	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Console/App.config	2005-02-16 21:07:55 UTC (rev 13604)
@@ -3,7 +3,7 @@
 	<appSettings>
 		<add key="IRCServerHostName" value="irc.eu.freenode.net" />
 		<add key="IRCServerHostPort" value="6667" />
-		<add key="IRCChannelName" value="channel" />
+		<add key="IRCChannelNames" value="channel1;channel2" />
 		<add key="IRCBotName" value="MyBot" />
 		<add key="ChmPath" value="C:\IRC\TechBot\CHM" />
 		<add key="MainChm" value="kmarch.chm" />

Modified: trunk/irc/TechBot/TechBot.Console/Main.cs
--- trunk/irc/TechBot/TechBot.Console/Main.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Console/Main.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -6,7 +6,8 @@
 {
 	public class ConsoleServiceOutput : IServiceOutput
 	{
-		public void WriteLine(string message)
+		public void WriteLine(MessageContext context,
+		                      string message)
 		{
 			System.Console.WriteLine(message);
 		}
@@ -49,11 +50,11 @@
 			}
 		}
 
-		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 @@
 		{
 			IrcService ircService = new IrcService(IRCServerHostName,
 			                                       IRCServerHostPort,
-			                                       IRCChannelName,
+			                                       IRCChannelNames,
 			                                       IRCBotName,
 			                                       ChmPath,
 			                                       MainChm,
@@ -180,7 +181,8 @@
 			while (true)
 			{
 				string s = System.Console.ReadLine();
-				service.InjectMessage(s);
+				service.InjectMessage(null,
+				                      s);
 			}
 		}
 	}

Modified: trunk/irc/TechBot/TechBot.Library/ApiCommand.cs
--- trunk/irc/TechBot/TechBot.Library/ApiCommand.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/ApiCommand.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -26,10 +26,12 @@
 			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 @@
 			                 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 @@
 			return "!api <apiname>";
 		}
 		
-		private bool SearchIndex(string keyword)
+		private bool SearchIndex(MessageContext context,
+		                         string keyword)
 		{
 			if (chm.HasIndex)
 			{
@@ -92,14 +97,18 @@
 				                                       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 @@
 				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 @@
 			                                      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 @@
 			{
 				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 @@
 			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,
 			                          "<PRE class=\"?syntax\"?>(.+)</PRE>",
 			                          RegexOptions.Multiline |
@@ -273,7 +300,8 @@
 			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 @@
 			}
 			else
 			{
-				baseStream = GetBaseStreamFromCHMFileName(CHMFileName);
+				baseStream = GetBaseStreamFromCHMFileName(context,
+				                                          CHMFileName);
 			}
 
 			if ((topicName == "") || (CHMFileName == "") || (baseStream == null))
@@ -299,11 +328,13 @@
 			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 @@
 					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;
 		}

Modified: trunk/irc/TechBot/TechBot.Library/HelpCommand.cs
--- trunk/irc/TechBot/TechBot.Library/HelpCommand.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/HelpCommand.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -21,12 +21,17 @@
 			                 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()

Modified: trunk/irc/TechBot/TechBot.Library/HresultCommand.cs
--- trunk/irc/TechBot/TechBot.Library/HresultCommand.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/HresultCommand.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -24,13 +24,15 @@
 			                 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 @@
 			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 @@
 			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));
 			}
 		}

Modified: trunk/irc/TechBot/TechBot.Library/ICommand.cs
--- trunk/irc/TechBot/TechBot.Library/ICommand.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/ICommand.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -5,7 +5,8 @@
 	public interface ICommand
 	{
 		bool CanHandle(string commandName);
-		void Handle(string commandName,
+		void Handle(MessageContext context,
+		            string commandName,
 		            string parameters);
 		string Help();
 	}

Modified: trunk/irc/TechBot/TechBot.Library/IrcService.cs
--- trunk/irc/TechBot/TechBot.Library/IrcService.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/IrcService.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -1,4 +1,5 @@
 using System;
+using System.Collections;
 using System.Threading;
 using TechBot.IRCLibrary;
 
@@ -8,7 +9,7 @@
 	{
 		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 @@
 		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 @@
 		{
 			this.hostname = hostname;
 			this.port = port;
-			this.channelname = channelname;
+			this.channelnames = channelnames;
 		    this.botname = botname;
 		    this.chmPath = chmPath;
 		    this.mainChm = mainChm;
@@ -65,30 +66,53 @@
 			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,
 		                            out string message)
 		{
@@ -102,22 +126,65 @@
 				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
 					{

Added: trunk/irc/TechBot/TechBot.Library/MessageContext.cs
--- trunk/irc/TechBot/TechBot.Library/MessageContext.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/MessageContext.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -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;
+		}
+	}
+}

Modified: trunk/irc/TechBot/TechBot.Library/NtStatusCommand.cs
--- trunk/irc/TechBot/TechBot.Library/NtStatusCommand.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/NtStatusCommand.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -24,13 +24,15 @@
 			                 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 @@
 			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 @@
 			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));
 			}
 		}

Modified: trunk/irc/TechBot/TechBot.Library/ServiceOutput.cs
--- trunk/irc/TechBot/TechBot.Library/ServiceOutput.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/ServiceOutput.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -4,6 +4,7 @@
 {
 	public interface IServiceOutput
 	{
-		void WriteLine(string message);
+		void WriteLine(MessageContext context,
+		               string message);
 	}
 }

Modified: trunk/irc/TechBot/TechBot.Library/SvnCommand.cs
--- trunk/irc/TechBot/TechBot.Library/SvnCommand.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/SvnCommand.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -20,10 +20,12 @@
 			                 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()

Modified: trunk/irc/TechBot/TechBot.Library/TechBotService.cs
--- trunk/irc/TechBot/TechBot.Library/TechBotService.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/TechBotService.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -9,8 +9,6 @@
 {
 	public class TechBotService
 	{
-		private const bool IsVerbose = false;
-		
 		private IServiceOutput serviceOutput;
 		private string chmPath;
 		private string mainChm;
@@ -37,12 +35,6 @@
 			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 @@
 			                            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 @@
 			return message.StartsWith("!");
 		}
 
-		public void ParseCommandMessage(string message)
+		public void ParseCommandMessage(MessageContext context,
+		                                string message)
 		{
 			if (!IsCommandMessage(message))
 				return;
@@ -94,7 +87,8 @@
 			{
 				if (command.CanHandle(commandName))
 				{
-					command.Handle(commandName, parameters);
+					command.Handle(context,
+					               commandName, parameters);
 					return;
 				}
 			}

Modified: trunk/irc/TechBot/TechBot.Library/WinerrorCommand.cs
--- trunk/irc/TechBot/TechBot.Library/WinerrorCommand.cs	2005-02-16 18:21:21 UTC (rev 13603)
+++ trunk/irc/TechBot/TechBot.Library/WinerrorCommand.cs	2005-02-16 21:07:55 UTC (rev 13604)
@@ -24,13 +24,15 @@
 			                 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 @@
 			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 @@
 			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));
 			}
 		}