Contents
Introduction
I wrote SmartIrc4net for having a high-level IRC API for .NET/C#. I started long time ago with IRC programming for PHP, I wrote Net_SmartIRC. Net_SmartIRC [^] is a PEAR class. Later, I was disappointed that the OO features of PHP are so limited. I was starting to port the project to C++, after a few weeks I stopped, so many things are missing and have to be written (even simple things like string manipulation). Then I found C#. And I ported SmartIRC in about 1-2 weeks! After that the API got better and better, it's just great what it is now... so here we are SmartIrc4net.
Top 
Object Design
This library has a 3 layered API, allows developers to pick the layer/features he needs. You could use any layer for writing IRC applications, the question is how much IRC abstraction and features you need. You have the choice!
Top 
Layer 1: IrcConnection
This layer is a low-level API and manages the messagebuffer (for reading and writing)
Top 
Layer 2: IrcCommands (extends IrcConnection)
This layer is a middle-level API. It contains all IRC RFC commands plus some useful and easy to use IRC methods (like Join, Part, Op, Deop, Ban, Unban etc.).
Top 
Layer 3: IrcClient (extends IrcCommands)
This layer is a high-level API with all features you could need for IRC programming, like channel syncing (keeping track of channels in objects with modes/topic/users), user syncing (for nicks, indents, hosts, realnames, servers, and hopcounts). This layer is fully event driven, all received data is parsed into different events with special arguments for each event (this makes it very easy to use the received IRC data without checking each time the RFC!)
Top 
How to use SmartIrc4net
Here is an example of how to use the library using the high-level API:
using System;
using System.Collections;
using System.Threading;
using Meebey.SmartIrc4net;
// This is an VERY basic example how your IRC application could be written
// its mainly for showing how to use the API, this program just connects sends
// a few message to a channel and waits for commands on the console
// (raw RFC commands though! it's later explained).
// There are also a few commands the IRC bot/client allows via private message.
public class Test
{
// make an instance of the high-level API
public static IrcClient irc = new IrcClient();
// this method we will use to analyse queries (also known as private messages)
public static void OnQueryMessage(object sender, IrcEventArgs e)
{
switch (e.Data.MessageArray[0]) {
// debug stuff
case "dump_channel":
string requested_channel = e.Data.MessageArray[1];
// getting the channel (via channel sync feature)
Channel channel = irc.GetChannel(requested_channel);
// here we send messages
irc.SendMessage(SendType.Message, e.Data.Nick, "CHANNEL'"+REQUESTED_CHANNEL+"'");
irc.SendMessage(SendType.Message, e.Data.Nick, "Name:'"+channel.Name+"'");
irc.SendMessage(SendType.Message, e.Data.Nick, "Topic:'"+channel.Topic+"'");
irc.SendMessage(SendType.Message, e.Data.Nick, "Mode:'"+channel.Mode+"'");
irc.SendMessage(SendType.Message, e.Data.Nick, "Key:'"+channel.Key+"'");
irc.SendMessage(SendType.Message, e.Data.Nick,"UserLimit: '"+channel.UserLimit+"'");
// here we go through all users of the channel and show their
// hashtable key and nickname
string nickname_list = "";
nickname_list += "Users: ";
IDictionaryEnumerator it = channel.Users.GetEnumerator();
while(it.MoveNext()) {
string key = (string)it.Key;
ChannelUser channeluser = (ChannelUser)it.Value;
nickname_list += key+" => "+channeluser.Nick+", ";
}
irc.SendMessage(SendType.Message, e.Data.Nick, nickname_list);
irc.SendMessage(SendType.Message, e.Data.Nick, "");
break;
case "gc":
GC.Collect();
break;
// typical commands
case "join":
irc.RfcJoin(e.Data.MessageArray[1]);
break;
case "part":
irc.RfcPart(e.Data.MessageArray[1]);
break;
case "die":
Exit();
break;
}
}
// this method handles when we receive "ERROR" from the IRC server
public static void OnError(object sender, ErrorEventArgs e)
{
System.Console.WriteLine("Error: "+e.ErrorMessage);
Exit();
}
// this method will get all IRC messages
public static void OnRawMessage(object sender, IrcEventArgs e)
{
System.Console.WriteLine("Received: "+e.Data.RawMessage);
}
public static void Main(string[] args)
{
Thread.CurrentThread.Name = "Main";
// wait time between messages, we can set this lower on own irc servers
irc.SendDelay = 200;
// we use channel sync, means we can use irc.GetChannel() and so on
irc.ActiveChannelSyncing = true;
// here we connect the events of the API to our written methods
// most have own event handler types, because they ship different data
irc.OnQueryMessage += new IrcEventHandler(OnQueryMessage);
irc.OnError += new ErrorEventHandler(OnError);
irc.OnRawMessage += new IrcEventHandler(OnRawMessage);
string[] serverlist;
// the server we want to connect to, could be also a simple string
serverlist = new string[] {"irc.fu-berlin.de"};
int port = 6667;
string channel = "#smartirc";
try {
// here we try to connect to the server and exceptions get handled
irc.Connect(serverlist, port);
} catch (ConnectionException e) {
// something went wrong, the reason will be shown
System.Console.WriteLine("couldn't connect! Reason: "+e.Message);
Exit();
}
try {
// here we logon and register our nickname and so on
irc.Login("SmartIRC", "SmartIrc4net Test Bot");
// join the channel
irc.RfcJoin(channel);
for (int i = 0; i < 3; i++) {
// here we send just 3 different types of messages, 3 times for
// testing the delay and flood protection (messagebuffer work)
irc.SendMessage(SendType.Message, channel, "test message "+i.ToString());
irc.SendMessage(SendType.Action, channel, "thinks this is cool "+i.ToString());
irc.SendMessage(SendType.Notice, channel, "SmartIrc4net rocks "+i.ToString());
}
// spawn a new thread to read the stdin of the console, this we use
// for reading IRC commands from the keyboard while the IRC connection
// stays in its own thread
new Thread(new ThreadStart(ReadCommands)).Start();
// here we tell the IRC API to go into a receive mode, all events
// will be triggered by _this_ thread (main thread in this case)
// Listen() blocks by default, you can also use ListenOnce() if you
// need that does one IRC operation and then returns, so you need then
// an own loop
irc.Listen();
// when Listen() returns our IRC session is over, to be sure we call
// disconnect manually
irc.Disconnect();
} catch (ConnectionException) {
// this exception is handled becaused Disconnect() can throw a not
// connected exception
Exit();
} catch (Exception e) {
// this should not happen by just in case we handle it nicely
System.Console.WriteLine("Error occurred! Message: "+e.Message);
System.Console.WriteLine("Exception: "+e.StackTrace);
Exit();
}
}
public static void ReadCommands()
{
// here we read the commands from the stdin and send it to the IRC API
// WARNING, it uses WriteLine() means you need to enter RFC commands
// like "JOIN #test" and then "PRIVMSG #test :hello to you"
while (true) {
irc.WriteLine(System.Console.ReadLine());
}
}
public static void Exit()
{
// we are done, lets exit...
System.Console.WriteLine("Exiting...");
System.Environment.Exit(0);
}
}
Connect to your favorite IRC server, set the IRC server in the source. Join the #smartirc channel. Compile the source, spawn the bot. The bot should join #smartirc and say three messages, after that send him a private message: "/msg smartirc say #smartirc hello!".
Top 
Official Project Page
SmartIrc4net is an own project which you can find here [^]. There you get the current versions, can report bugs or post help requests on the forum. Comments, suggestions and criticism are welcome!
Top 
Have fun
There you go, have fun with bot coding! ;)
PS: I started a project called Gnosmirc which uses SmartIrc4net, it's a GUI (Gnome# based) IRC client. This project is of course OpenSource (licensed under the GPL), take a look it at here: Gnosmirc [^]
Top 