HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Simple IRC Bot in C#

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
simpleircbot

Problem

This was a simple IRC bot I threw together a long time ago, found recently, and was curious as to if there were any kind of significant improvements that could be made.

```
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

public class IRCbot
{
// server to connect to (edit at will)
public static string SERVER = "irc.changeme.com";
// server port (6667 by default)
private static int PORT = 6667;
// user information defined in RFC 2812 (IRC: Client Protocol) is sent to the IRC server
private static string USER = "USER IRCbot 0 * :IRCbot";
// the bot's nickname
private static string NICK = "IRCbot";
// channel to join
private static string CHANNEL = "#opers";

static void Main(string[] args)
{
NetworkStream stream;
TcpClient irc;
string inputLine;
StreamReader reader;
StreamWriter writer;

try
{
irc = new TcpClient(SERVER, PORT);
stream = irc.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
writer.WriteLine("NICK " + NICK);
writer.Flush();
writer.WriteLine(USER);
writer.Flush();

while (true)
{
while ((inputLine = reader.ReadLine()) != null)
{
Console.WriteLine("PONG " + PongReply);
writer.WriteLine("PONG " + PongReply);
writer.Flush();
//continue;
}

switch (splitInput[1])
{
case "001":
writer.WriteLine("JOIN " + CHANNEL);
writer.Flush();
break;
default:
break;
}
}

// close

Solution


  • you should separate the IRCBot from the Main into its own class with it's own fields/properties



  • you should specify all required parameters via the construtor so that it is not possible to create an invalid ircbot



  • I don't think it's a good idea to make the retry recursive - IMHO it would be better to create a loop and limit the retries so that you don't have an infite loop (ok, unless it was desired)



  • you really should use the using statement. In your current implementation the resources will be closed only if there was no execption - if an exception occurs the Closees won't be called. You also don't free the resources because you don't call the Dispose, you just close them and then create new resources on retry, this is a memory leak.



Here's an example:

public class IRCbot
{
    // server to connect to (edit at will)
    private readonly string _server;
    // server port (6667 by default)
    private readonly int _port;
    // user information defined in RFC 2812 (IRC: Client Protocol) is sent to the IRC server 
    private readonly string _user;

    // the bot's nickname
    private readonly string _nick;
    // channel to join
    private readonly string _channel;

    private readonly int _maxRetries;

    public IRCbot(string server, int port, string user, string nick, string channel, int maxRetries = 3)
    {
        _server = server;
        _port = port;
        _user = user;
        _nick = nick;
        _channel = channel;
        _maxRetries = maxRetries;
    }

    public void Start()
    {
        var retry = false;
        var retryCount = 0;
        do
        {
            try
            {
                using (var irc = new TcpClient(_server, _port))
                using (var stream = irc.GetStream())
                using (var reader = new StreamReader(stream))
                using (var writer = new StreamWriter(stream))
                {
                    writer.WriteLine("NICK " + _nick);
                    writer.Flush();
                    writer.WriteLine(_user);
                    writer.Flush();

                    while (true)
                    {
                        string inputLine;
                        while ((inputLine = reader.ReadLine()) != null)
                        {
                            Console.WriteLine("PONG " + PongReply);
                                writer.WriteLine("PONG " + PongReply);
                                writer.Flush();
                                //continue;
                            }

                            switch (splitInput[1])
                            {
                                case "001":
                                    writer.WriteLine("JOIN " + _channel);
                                    writer.Flush();
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // shows the exception, sleeps for a little while and then tries to establish a new connection to the IRC server
                Console.WriteLine(e.ToString());
                Thread.Sleep(5000);
                retry = ++retryCount <= _maxRetries;
            }
        } while (retry);
    }
}


Usage:

void Main()
{
    var ircBot = new IRCbot(
        server: "irc.changeme.com",
        port: 6667,
        user: "USER IRCbot 0 * :IRCbot",
        nick: "IRCbot",
        channel: "#opers"
    );

    ircBot.Start();
}

Code Snippets

public class IRCbot
{
    // server to connect to (edit at will)
    private readonly string _server;
    // server port (6667 by default)
    private readonly int _port;
    // user information defined in RFC 2812 (IRC: Client Protocol) is sent to the IRC server 
    private readonly string _user;

    // the bot's nickname
    private readonly string _nick;
    // channel to join
    private readonly string _channel;

    private readonly int _maxRetries;

    public IRCbot(string server, int port, string user, string nick, string channel, int maxRetries = 3)
    {
        _server = server;
        _port = port;
        _user = user;
        _nick = nick;
        _channel = channel;
        _maxRetries = maxRetries;
    }

    public void Start()
    {
        var retry = false;
        var retryCount = 0;
        do
        {
            try
            {
                using (var irc = new TcpClient(_server, _port))
                using (var stream = irc.GetStream())
                using (var reader = new StreamReader(stream))
                using (var writer = new StreamWriter(stream))
                {
                    writer.WriteLine("NICK " + _nick);
                    writer.Flush();
                    writer.WriteLine(_user);
                    writer.Flush();

                    while (true)
                    {
                        string inputLine;
                        while ((inputLine = reader.ReadLine()) != null)
                        {
                            Console.WriteLine("<- " + inputLine);

                            // split the lines sent from the server by spaces (seems to be the easiest way to parse them)
                            string[] splitInput = inputLine.Split(new Char[] { ' ' });

                            if (splitInput[0] == "PING")
                            {
                                string PongReply = splitInput[1];
                                //Console.WriteLine("->PONG " + PongReply);
                                writer.WriteLine("PONG " + PongReply);
                                writer.Flush();
                                //continue;
                            }

                            switch (splitInput[1])
                            {
                                case "001":
                                    writer.WriteLine("JOIN " + _channel);
                                    writer.Flush();
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // shows the exception, sleeps for a little while and then tries to establish a new connection to the IRC server
                Console.WriteLine(e.ToString());
                Thread.Sleep(5000);
                retry = ++retryCount <= _maxRetries;
 
void Main()
{
    var ircBot = new IRCbot(
        server: "irc.changeme.com",
        port: 6667,
        user: "USER IRCbot 0 * :IRCbot",
        nick: "IRCbot",
        channel: "#opers"
    );

    ircBot.Start();
}

Context

StackExchange Code Review Q#142653, answer score: 13

Revisions (0)

No revisions yet.