3

I am having an issue with my IRC Bot I am trying to write in c# just as a way to help get my head around the IRC protocol, I am planning on writing a client/server in the future but as you can prolly guess I am far off this :P

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;

namespace LolBot
{
struct IRCConfig
{
    public string server;
    public int port;
    public string nick;
    public string name;

}

class IRCBot
{
    TcpClient IRCConnection = null;
    IRCConfig config;
    NetworkStream ns = null;
    StreamReader sr = null;
    StreamWriter sw = null;

    public IRCBot(IRCConfig config)
    {
        this.config = config;
        try
        {
            IRCConnection = new TcpClient(config.server, config.port);
        }
        catch
        {
            Console.WriteLine("Connection Error");
        }

        try
        {
            ns = IRCConnection.GetStream();
            sr = new StreamReader(ns);
            sw = new StreamWriter(ns);
            sendData("USER", config.nick + config.name);
            sendData("NICK", config.nick);
        }
        catch
        {
            Console.WriteLine("Communication error");
        }
        finally
        {
            if (sr != null)
                sr.Close();
            if (sw != null)
                sw.Close();
            if (ns != null)
                ns.Close();
            if (IRCConnection != null)
                IRCConnection.Close();
        }

    }

    public void sendData(string cmd, string param)
    {
        if (param == null)
        {
            sw.WriteLine(cmd);
            sw.Flush();
            Console.WriteLine(cmd);
        }
        else
        {
            sw.WriteLine(cmd + " " + param);
            sw.Flush();
            Console.WriteLine(cmd + " " + param);
        }
    }

    public void IRCWork()
    {
        string[] ex;
        string data;
        bool shouldRun = true;
        while (shouldRun)
        {
            data = sr.ReadLine();
            Console.WriteLine(data);
            char[] charSeparator = new char[] { ' ' };
            ex = data.Split(charSeparator, 5);

            if (ex[0] == "PING")
            {
                sendData("PONG", ex[1]);
            }

            if (ex.Length > 4) //is the command received long enough to be a bot command?
            {
                string command = ex[3]; //grab the command sent

                switch (command)
                {
                    case ":!join":
                        sendData("JOIN", ex[4]); //if the command is !join send the "JOIN" command to the server with the parameters set by the user
                        break;
                    case ":!say":
                        sendData("PRIVMSG", ex[2] + " " + ex[4]); //if the command is !say, send a message to the chan (ex[2]) followed by the actual message (ex[4]).
                        break;
                    case ":!quit":
                        sendData("QUIT", ex[4]); //if the command is quit, send the QUIT command to the server with a quit message
                        shouldRun = false; //turn shouldRun to false - the server will stop sending us data so trying to read it will not work and result in an error. This stops the loop from running and we will close off the connections properly
                        break;
                }
            }
        }
    }
}


class Program
{
    static void Main(string[] args)
    {
        IRCConfig conf = new IRCConfig();
        conf.name = "LolBot";
        conf.nick = "LolBot";
        conf.port = 6667;
        conf.server = "irc.strictfp.com";
        new IRCBot(conf);
        Console.WriteLine("Bot quit/crashed");
        Console.ReadLine();
    }
}

}

Whenever I execute the Bot, it comes up with:

USER AspiBot google.com google.com :AspiBot
NICK AspiBot
Bot quit/crashed

I don't really understand why it is quiting before connecting to the server and I am also looking on how to set it up to join a channel, I am aware that I need to use JOIN but I'm not sure how to implent it.

Hello World
  • 1,379
  • 4
  • 20
  • 41

1 Answers1

3

You should probably not do so much in the constructor, but the problem you are encountering here is that you are not calling IRCWork() after newing up the bot.

var bot = new IRCBot(conf);
bot.IRCWork();

EDIT You are also closing all of your connections in the finally block of your constructor, so IRCWork() isn't going to work anyway. Try implementing IDisposable, and putting your close logic in Dispose():

using (var bot = new IRCBot(conf))
{
    bot.IRCWork();
}

Quick refactor of posted code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;

namespace LolBot
{
    internal struct IRCConfig
    {
        public string server;
        public int port;
        public string nick;
        public string name;

    }

    internal class IRCBot : IDisposable
    {
        private TcpClient IRCConnection = null;
        private IRCConfig config;
        private NetworkStream ns = null;
        private StreamReader sr = null;
        private StreamWriter sw = null;

        public IRCBot(IRCConfig config)
        {
            this.config = config;
        }

        public void Connect()
        {
            try
            {
                IRCConnection = new TcpClient(config.server, config.port);
            }
            catch
            {
                Console.WriteLine("Connection Error");
                throw;
            }

            try
            {
                ns = IRCConnection.GetStream();
                sr = new StreamReader(ns);
                sw = new StreamWriter(ns);
                sendData("USER", config.nick + config.name);
                sendData("NICK", config.nick);
            }
            catch
            {
                Console.WriteLine("Communication error");
                throw;
            }
        }

        public void sendData(string cmd, string param)
        {
            if (param == null)
            {
                sw.WriteLine(cmd);
                sw.Flush();
                Console.WriteLine(cmd);
            }
            else
            {
                sw.WriteLine(cmd + " " + param);
                sw.Flush();
                Console.WriteLine(cmd + " " + param);
            }
        }

        public void IRCWork()
        {
            string[] ex;
            string data;
            bool shouldRun = true;
            while (shouldRun)
            {
                data = sr.ReadLine();
                Console.WriteLine(data);
                char[] charSeparator = new char[] {' '};
                ex = data.Split(charSeparator, 5);

                if (ex[0] == "PING")
                {
                    sendData("PONG", ex[1]);
                }

                if (ex.Length > 4) //is the command received long enough to be a bot command?
                {
                    string command = ex[3]; //grab the command sent

                    switch (command)
                    {
                        case ":!join":
                            sendData("JOIN", ex[4]);
                                //if the command is !join send the "JOIN" command to the server with the parameters set by the user
                            break;
                        case ":!say":
                            sendData("PRIVMSG", ex[2] + " " + ex[4]);
                                //if the command is !say, send a message to the chan (ex[2]) followed by the actual message (ex[4]).
                            break;
                        case ":!quit":
                            sendData("QUIT", ex[4]);
                                //if the command is quit, send the QUIT command to the server with a quit message
                            shouldRun = false;
                                //turn shouldRun to false - the server will stop sending us data so trying to read it will not work and result in an error. This stops the loop from running and we will close off the connections properly
                            break;
                    }
                }
            }
        }

        public void Dispose()
        {
            if (sr != null)
                sr.Close();
            if (sw != null)
                sw.Close();
            if (ns != null)
                ns.Close();
            if (IRCConnection != null)
                IRCConnection.Close();
        }
    }


    internal class Program
    {
        private static void Main(string[] args)
        {
            IRCConfig conf = new IRCConfig();
            conf.name = "LolBot";
            conf.nick = "LolBot";
            conf.port = 6667;
            conf.server = "irc.strictfp.com";
            using (var bot = new IRCBot(conf))
            {
                bot.Connect();
                bot.IRCWork();
            }
            Console.WriteLine("Bot quit/crashed");
            Console.ReadLine();
        }
    }
}
Steve Czetty
  • 6,147
  • 9
  • 39
  • 48
  • I've never used the Disposable stuff, could you explain it to me and how I would implement it please? – Hello World Jun 01 '12 at 15:17
  • Refactored your code as an example. Didn't test it at all, though. – Steve Czetty Jun 01 '12 at 15:24
  • Yeah all is working now apart from I'm getting a registration timeout but that is a seperate problem, thanks for the help man! – Hello World Jun 01 '12 at 15:35
  • Great. I use your code in WinFolrms, i get error: irc-hispano.org 461 USER :Not enough parameters – Kiquenet Sep 12 '12 at 21:13
  • Like I said, never tested it. I imagine the USER command isn't quite right. Maybe it should be `sendData("USER", config.nick + " " + config.name);`? I don't remember the IRC protocol off the top of my head anymore. – Steve Czetty Sep 12 '12 at 21:48
  • Try `sendData("USER", config.nick + " 0 * " + config.name);` According to http://www.faqs.org/rfcs/rfc2812.html you need four parameters to the USER command: ` ` – Daniel Morritt Sep 19 '13 at 08:08