Support multiple channels

svn path=/trunk/; revision=13604
This commit is contained in:
Casper Hornstrup 2005-02-16 21:07:55 +00:00
parent 6536947239
commit 70350430a5
15 changed files with 251 additions and 109 deletions

View file

@ -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" />

View file

@ -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);
}
}
}

View file

@ -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 <apiname>";
}
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,
"<PRE class=\"?syntax\"?>(.+)</PRE>",
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;
}

View file

@ -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()

View file

@ -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));
}
}

View file

@ -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();
}

View file

@ -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
{

View file

@ -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;
}
}
}

View file

@ -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));
}
}

View file

@ -4,6 +4,7 @@ namespace TechBot.Library
{
public interface IServiceOutput
{
void WriteLine(string message);
void WriteLine(MessageContext context,
string message);
}
}

View file

@ -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()

View file

@ -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;
}
}

View file

@ -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));
}
}

View file

@ -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" />

View file

@ -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,