Import TechBot

svn path=/trunk/; revision=13064
This commit is contained in:
Casper Hornstrup 2005-01-15 19:27:25 +00:00
parent 568b27baeb
commit 9dab4509fa
94 changed files with 24386 additions and 0 deletions

View file

@ -0,0 +1,319 @@
using System;
using System.IO;
using System.Data;
using System.Text.RegularExpressions;
using HtmlHelp;
using HtmlHelp.ChmDecoding;
namespace TechBot.Library
{
public class ApiCommand : BaseCommand, ICommand
{
private const bool IsVerbose = false;
private HtmlHelpSystem chm;
private IServiceOutput serviceOutput;
private string chmPath;
private string mainChm;
public ApiCommand(IServiceOutput serviceOutput,
string chmPath,
string mainChm)
{
this.serviceOutput = serviceOutput;
this.chmPath = chmPath;
this.mainChm = mainChm;
Run();
}
private void WriteIfVerbose(string message)
{
if (IsVerbose)
serviceOutput.WriteLine(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 bool CanHandle(string commandName)
{
return CanHandle(commandName,
new string[] { "api" });
}
public void Handle(string commandName,
string parameters)
{
if (parameters.Trim().Equals(String.Empty))
DisplayNoKeyword();
else
Search(parameters);
}
public string Help()
{
return "!api <apiname>";
}
private bool SearchIndex(string keyword)
{
if (chm.HasIndex)
{
IndexItem item = chm.Index.SearchIndex(keyword,
IndexType.KeywordLinks);
if (item != null && item.Topics.Count > 0)
{
WriteIfVerbose(String.Format("Keyword {0} found in index",
item.KeyWord));
IndexTopic indexTopic = item.Topics[0] as IndexTopic;
return DisplayResult(keyword, indexTopic);
}
else
{
WriteIfVerbose(String.Format("Keyword {0} not found in index",
keyword));
return false;
}
}
else
return false;
}
private void SearchFullText(string keyword)
{
string sort = "Rating ASC";
/*
sort = "Location ASC");
sort = "Title ASC");
*/
WriteIfVerbose(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(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))
{
DisplayNoResult(keyword);
}
}
else
{
DisplayNoResult(keyword);
}
}
private void Search(string keyword)
{
if (!SearchIndex(keyword))
{
SearchFullText(keyword);
}
}
private bool DisplayResult(string keyword,
IndexTopic indexTopic)
{
keyword = keyword.Trim().ToLower();
string url = indexTopic.URL;
WriteIfVerbose(String.Format("URL from index search {0}",
url));
string prototype = ExtractPrototype(url);
if (prototype == null || prototype.Trim().Equals(String.Empty))
return false;
string formattedPrototype = FormatPrototype(prototype);
serviceOutput.WriteLine(formattedPrototype);
return true;
}
private bool DisplayResult(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(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);
if (prototype == null || prototype.Trim().Equals(String.Empty))
continue;
string formattedPrototype = FormatPrototype(prototype);
serviceOutput.WriteLine(formattedPrototype);
return true;
}
}
return false;
}
private void DisplayNoResult(string keyword)
{
serviceOutput.WriteLine(String.Format("I don't know about keyword {0}", keyword));
}
private void DisplayNoKeyword()
{
serviceOutput.WriteLine("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(string url)
{
string page = GetPage(url);
Match match = Regex.Match(page,
"<PRE class=\"?syntax\"?>(.+)</PRE>",
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("</PRE>");
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(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(CHMFileName);
}
if ((topicName == "") || (CHMFileName == "") || (baseStream == null))
{
return "";
}
return baseStream.ExtractTextFile(topicName);
}
private CHMStream.CHMStream GetBaseStreamFromCHMFileName(string CHMFileName)
{
foreach (CHMFile file in chm.FileList)
{
WriteIfVerbose(String.Format("Compare: {0} <> {1}",
file.ChmFilePath,
CHMFileName));
if (file.ChmFilePath.ToLower().Equals(CHMFileName.ToLower()))
{
return file.BaseStream;
}
}
WriteIfVerbose(String.Format("Could not find loaded CHM file in list: {0}",
CHMFileName));
return null;
}
}
}

View file

@ -0,0 +1,32 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following
// attributes.
//
// change them to the information which is associated with the assembly
// you compile.
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has following format :
//
// Major.Minor.Build.Revision
//
// You can specify all values by your own or you can build default build and revision
// numbers with the '*' character (the default):
[assembly: AssemblyVersion("1.0.*")]
// The following attributes specify the key for the sign of your assembly. See the
// .NET Framework documentation for more information about signing.
// This is not required, if you don't want signing let these attributes like they're.
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]

View file

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<project name="TechBot.Library" default="build">
<property name="output.dir" value="..\bin" />
<target name="build" description="Build component">
<mkdir dir="${output.dir}" />
<csc target="library"
output="${output.dir}\TechBot.Library.dll"
optimize="true"
debug="true"
doc="${output.dir}\TechBot.Library.xml"
warninglevel="0">
<sources>
<include name="*.cs" />
</sources>
<references>
<include name="${output.dir}\CHMLibrary.dll" />
<include name="${output.dir}\TechBot.IRCLibrary.dll" />
</references>
</csc>
</target>
</project>

View file

@ -0,0 +1,37 @@
using System;
using System.Collections;
namespace TechBot.Library
{
public class HelpCommand : BaseCommand, ICommand
{
private IServiceOutput serviceOutput;
private ArrayList commands;
public HelpCommand(IServiceOutput serviceOutput,
ArrayList commands)
{
this.serviceOutput = serviceOutput;
this.commands = commands;
}
public bool CanHandle(string commandName)
{
return CanHandle(commandName,
new string[] { "help" });
}
public void Handle(string commandName,
string parameters)
{
serviceOutput.WriteLine("I support the following commands:");
foreach (ICommand command in commands)
serviceOutput.WriteLine(command.Help());
}
public string Help()
{
return "!help";
}
}
}

View file

@ -0,0 +1,81 @@
using System;
using System.Xml;
namespace TechBot.Library
{
public class HresultCommand : BaseCommand, ICommand
{
private IServiceOutput serviceOutput;
private string hresultXml;
private XmlDocument hresultXmlDocument;
public HresultCommand(IServiceOutput serviceOutput,
string hresultXml)
{
this.serviceOutput = serviceOutput;
this.hresultXml = hresultXml;
hresultXmlDocument = new XmlDocument();
hresultXmlDocument.Load(hresultXml);
}
public bool CanHandle(string commandName)
{
return CanHandle(commandName,
new string[] { "hresult" });
}
public void Handle(string commandName,
string parameters)
{
string hresultText = parameters;
if (hresultText.Equals(String.Empty))
{
serviceOutput.WriteLine("Please provide a valid HRESULT value.");
return;
}
NumberParser np = new NumberParser();
long hresult = np.Parse(hresultText);
if (np.Error)
{
serviceOutput.WriteLine(String.Format("{0} is not a valid HRESULT value.",
hresultText));
return;
}
string description = GetHresultDescription(hresult);
if (description != null)
{
serviceOutput.WriteLine(String.Format("{0} is {1}.",
hresultText,
description));
}
else
{
serviceOutput.WriteLine(String.Format("I don't know about HRESULT {0}.",
hresultText));
}
}
public string Help()
{
return "!hresult <value>";
}
private string GetHresultDescription(long hresult)
{
XmlElement root = hresultXmlDocument.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;
}
}
}

View file

@ -0,0 +1,28 @@
using System;
namespace TechBot.Library
{
public interface ICommand
{
bool CanHandle(string commandName);
void Handle(string commandName,
string parameters);
string Help();
}
public class BaseCommand
{
protected bool CanHandle(string commandName,
string[] availableCommands)
{
foreach (string availableCommand in availableCommands)
{
if (String.Compare(availableCommand, commandName, true) == 0)
return true;
}
return false;
}
}
}

View file

@ -0,0 +1,142 @@
using System;
using System.Threading;
using TechBot.IRCLibrary;
namespace TechBot.Library
{
public class IrcService : IServiceOutput
{
private string hostname;
private int port;
private string channelname;
private string botname;
private string chmPath;
private string mainChm;
private string ntstatusXml;
private string winerrorXml;
private string hresultXml;
private string svnCommand;
private IrcClient client;
private IrcChannel channel1;
private TechBotService service;
private bool isStopped = false;
public IrcService(string hostname,
int port,
string channelname,
string botname,
string chmPath,
string mainChm,
string ntstatusXml,
string winerrorXml,
string hresultXml,
string svnCommand)
{
this.hostname = hostname;
this.port = port;
this.channelname = channelname;
this.botname = botname;
this.chmPath = chmPath;
this.mainChm = mainChm;
this.ntstatusXml = ntstatusXml;
this.winerrorXml = winerrorXml;
this.hresultXml = hresultXml;
this.svnCommand = svnCommand;
}
public void Run()
{
service = new TechBotService(this,
chmPath,
mainChm,
ntstatusXml,
winerrorXml,
hresultXml,
svnCommand);
service.Run();
client = new IrcClient();
client.Encoding = System.Text.Encoding.GetEncoding("iso-8859-1");
client.MessageReceived += new MessageReceivedHandler(client_MessageReceived);
client.ChannelUserDatabaseChanged += new ChannelUserDatabaseChangedHandler(client_ChannelUserDatabaseChanged);
System.Console.WriteLine(String.Format("Connecting to {0} port {1}",
hostname, port));
client.Connect(hostname, port);
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));
while (!isStopped)
{
Thread.Sleep(1000);
}
client.PartChannel(channel1, "Caught in the bitstream...");
client.Diconnect();
System.Console.WriteLine("Disconnected...");
}
public void Stop()
{
isStopped = true;
}
public void WriteLine(string message)
{
Console.WriteLine(String.Format("Sending: {0}", message));
channel1.Talk(message);
}
private void ExtractMessage(string parameters,
out string message)
{
int startIndex = parameters.IndexOf(':');
if (startIndex != -1)
{
message = parameters.Substring(startIndex + 1);
}
else
{
message = parameters;
}
}
private void client_MessageReceived(IrcMessage message)
{
try
{
if (channel1 != null &&
channel1.Name != null &&
message.Parameters != null)
{
string injectMessage;
ExtractMessage(message.Parameters, out injectMessage);
if ((message.Command.ToUpper().Equals("PRIVMSG")) &&
(message.Parameters.ToLower().StartsWith("#" + channel1.Name.ToLower() + " ")))
{
Console.WriteLine("Injecting: " + injectMessage);
service.InjectMessage(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)
{
}
}
}

View file

@ -0,0 +1,81 @@
using System;
using System.Xml;
namespace TechBot.Library
{
public class NtStatusCommand : BaseCommand, ICommand
{
private IServiceOutput serviceOutput;
private string ntstatusXml;
private XmlDocument ntstatusXmlDocument;
public NtStatusCommand(IServiceOutput serviceOutput,
string ntstatusXml)
{
this.serviceOutput = serviceOutput;
this.ntstatusXml = ntstatusXml;
ntstatusXmlDocument = new XmlDocument();
ntstatusXmlDocument.Load(ntstatusXml);
}
public bool CanHandle(string commandName)
{
return CanHandle(commandName,
new string[] { "ntstatus" });
}
public void Handle(string commandName,
string parameters)
{
string ntstatusText = parameters;
if (ntstatusText.Equals(String.Empty))
{
serviceOutput.WriteLine("Please provide a valid NTSTATUS value.");
return;
}
NumberParser np = new NumberParser();
long ntstatus = np.Parse(ntstatusText);
if (np.Error)
{
serviceOutput.WriteLine(String.Format("{0} is not a valid NTSTATUS value.",
ntstatusText));
return;
}
string description = GetNtstatusDescription(ntstatus);
if (description != null)
{
serviceOutput.WriteLine(String.Format("{0} is {1}.",
ntstatusText,
description));
}
else
{
serviceOutput.WriteLine(String.Format("I don't know about NTSTATUS {0}.",
ntstatusText));
}
}
public string Help()
{
return "!ntstatus <value>";
}
private string GetNtstatusDescription(long ntstatus)
{
XmlElement root = ntstatusXmlDocument.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;
}
}
}

View file

@ -0,0 +1,32 @@
using System;
using System.Globalization;
namespace TechBot.Library
{
public class NumberParser
{
public bool Error = false;
public long Parse(string s)
{
try
{
Error = false;
if (s.StartsWith("0x"))
return Int64.Parse(s.Substring(2),
NumberStyles.HexNumber);
else
return Int64.Parse(s);
}
catch (FormatException)
{
Error = true;
}
catch (OverflowException)
{
Error = true;
}
return -1;
}
}
}

View file

@ -0,0 +1,9 @@
using System;
namespace TechBot.Library
{
public interface IServiceOutput
{
void WriteLine(string message);
}
}

View file

@ -0,0 +1,34 @@
using System;
namespace TechBot.Library
{
public class SvnCommand : BaseCommand, ICommand
{
private IServiceOutput serviceOutput;
private string svnCommand;
public SvnCommand(IServiceOutput serviceOutput,
string svnCommand)
{
this.serviceOutput = serviceOutput;
this.svnCommand = svnCommand;
}
public bool CanHandle(string commandName)
{
return CanHandle(commandName,
new string[] { "svn" });
}
public void Handle(string commandName,
string parameters)
{
serviceOutput.WriteLine(svnCommand);
}
public string Help()
{
return "!svn";
}
}
}

View file

@ -0,0 +1,16 @@
<Combine fileversion="1.0" name="TechBot.Library" description="">
<StartMode startupentry="TechBot.Library" single="True">
<Execute entry="TechBot.Library" type="None" />
</StartMode>
<Entries>
<Entry filename=".\.\TechBot.Library.prjx" />
</Entries>
<Configurations active="Debug">
<Configuration name="Release">
<Entry name="TechBot.Library" configurationname="Debug" build="False" />
</Configuration>
<Configuration name="Debug">
<Entry name="TechBot.Library" configurationname="Debug" build="False" />
</Configuration>
</Configurations>
</Combine>

View file

@ -0,0 +1,39 @@
<Project name="TechBot.Library" standardNamespace="TechBot.Library" description="" newfilesearch="None" enableviewstate="True" version="1.1" projecttype="C#">
<Contents>
<File name=".\AssemblyInfo.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\Default.build" subtype="Code" buildaction="Nothing" dependson="" data="" />
<File name=".\TechBotService.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\ServiceOutput.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\IrcService.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\ApiCommand.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\ICommand.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\HelpCommand.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\NtStatusCommand.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\NumberParser.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\HresultCommand.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\WinerrorCommand.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name=".\SvnCommand.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
</Contents>
<References>
<Reference type="Project" refto="CHMLibrary" localcopy="True" />
<Reference type="Project" refto="TechBot.IRCLibrary" localcopy="True" />
</References>
<DeploymentInformation target="" script="" strategy="File" />
<Configuration runwithwarnings="True" name="Debug">
<CodeGeneration runtime="MsNet" compiler="Csc" compilerversion="" warninglevel="4" nowarn="" includedebuginformation="True" optimize="False" unsafecodeallowed="False" generateoverflowchecks="True" mainclass="" target="Library" definesymbols="" generatexmldocumentation="False" win32Icon="" noconfig="False" nostdlib="False" />
<Execution commandlineparameters="" consolepause="False" />
<Output directory="..\bin\Debug" assembly="TechBot.Library" executeScript="" executeBeforeBuild="" executeAfterBuild="" executeBeforeBuildArguments="" executeAfterBuildArguments="" />
</Configuration>
<Configurations active="Debug">
<Configuration runwithwarnings="True" name="Debug">
<CodeGeneration runtime="MsNet" compiler="Csc" compilerversion="" warninglevel="4" nowarn="" includedebuginformation="True" optimize="False" unsafecodeallowed="False" generateoverflowchecks="True" mainclass="" target="Library" definesymbols="" generatexmldocumentation="False" win32Icon="" noconfig="False" nostdlib="False" />
<Execution commandlineparameters="" consolepause="False" />
<Output directory="..\bin\Debug" assembly="TechBot.Library" executeScript="" executeBeforeBuild="" executeAfterBuild="" executeBeforeBuildArguments="" executeAfterBuildArguments="" />
</Configuration>
<Configuration runwithwarnings="True" name="Release">
<CodeGeneration runtime="MsNet" compiler="Csc" compilerversion="" warninglevel="4" nowarn="" includedebuginformation="False" optimize="True" unsafecodeallowed="False" generateoverflowchecks="False" mainclass="" target="Library" definesymbols="" generatexmldocumentation="False" win32Icon="" noconfig="False" nostdlib="False" />
<Execution commandlineparameters="" consolepause="False" />
<Output directory="..\bin\Release" assembly="TechBot.Library" executeScript="" executeBeforeBuild="" executeAfterBuild="" executeBeforeBuildArguments="" executeAfterBuildArguments="" />
</Configuration>
</Configurations>
</Project>

View file

@ -0,0 +1,103 @@
using System;
using System.Collections;
using System.IO;
using System.Data;
using System.Threading;
using TechBot.IRCLibrary;
namespace TechBot.Library
{
public class TechBotService
{
private const bool IsVerbose = false;
private IServiceOutput serviceOutput;
private string chmPath;
private string mainChm;
private string ntstatusXml;
private string winerrorXml;
private string hresultXml;
private string svnCommand;
private ArrayList commands = new ArrayList();
public TechBotService(IServiceOutput serviceOutput,
string chmPath,
string mainChm,
string ntstatusXml,
string winerrorXml,
string hresultXml,
string svnCommand)
{
this.serviceOutput = serviceOutput;
this.chmPath = chmPath;
this.mainChm = mainChm;
this.ntstatusXml = ntstatusXml;
this.winerrorXml = winerrorXml;
this.hresultXml = hresultXml;
this.svnCommand = svnCommand;
}
private void WriteIfVerbose(string message)
{
if (IsVerbose)
serviceOutput.WriteLine(message);
}
public void Run()
{
commands.Add(new HelpCommand(serviceOutput,
commands));
commands.Add(new ApiCommand(serviceOutput,
chmPath,
mainChm));
commands.Add(new NtStatusCommand(serviceOutput,
ntstatusXml));
commands.Add(new WinerrorCommand(serviceOutput,
winerrorXml));
commands.Add(new HresultCommand(serviceOutput,
hresultXml));
commands.Add(new SvnCommand(serviceOutput,
svnCommand));
}
public void InjectMessage(string message)
{
if (message.StartsWith("!"))
{
ParseCommandMessage(message);
}
}
private bool IsCommandMessage(string message)
{
return message.StartsWith("!");
}
public void ParseCommandMessage(string message)
{
if (!IsCommandMessage(message))
return;
message = message.Substring(1).Trim();
int index = message.IndexOf(' ');
string commandName;
string parameters = "";
if (index != -1)
{
commandName = message.Substring(0, index).Trim();
parameters = message.Substring(index).Trim();
}
else
commandName = message.Trim();
foreach (ICommand command in commands)
{
if (command.CanHandle(commandName))
{
command.Handle(commandName, parameters);
return;
}
}
}
}
}

View file

@ -0,0 +1,81 @@
using System;
using System.Xml;
namespace TechBot.Library
{
public class WinerrorCommand : BaseCommand, ICommand
{
private IServiceOutput serviceOutput;
private string winerrorXml;
private XmlDocument winerrorXmlDocument;
public WinerrorCommand(IServiceOutput serviceOutput,
string winerrorXml)
{
this.serviceOutput = serviceOutput;
this.winerrorXml = winerrorXml;
winerrorXmlDocument = new XmlDocument();
winerrorXmlDocument.Load(winerrorXml);
}
public bool CanHandle(string commandName)
{
return CanHandle(commandName,
new string[] { "winerror" });
}
public void Handle(string commandName,
string parameters)
{
string winerrorText = parameters;
if (winerrorText.Equals(String.Empty))
{
serviceOutput.WriteLine("Please provide a valid System Error Code value.");
return;
}
NumberParser np = new NumberParser();
long winerror = np.Parse(winerrorText);
if (np.Error)
{
serviceOutput.WriteLine(String.Format("{0} is not a valid System Error Code value.",
winerrorText));
return;
}
string description = GetWinerrorDescription(winerror);
if (description != null)
{
serviceOutput.WriteLine(String.Format("{0} is {1}.",
winerrorText,
description));
}
else
{
serviceOutput.WriteLine(String.Format("I don't know about System Error Code {0}.",
winerrorText));
}
}
public string Help()
{
return "!winerror <value>";
}
private string GetWinerrorDescription(long winerror)
{
XmlElement root = winerrorXmlDocument.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;
}
}
}