3

IRC ボットに問題があります。IRC プロトコルを理解するための方法として、c# で記述しようとしています。将来的にクライアント/サーバーを作成する予定ですが、ご想像のとおり、これからはほど遠い: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();
    }
}

}

ボットを実行すると、次のように表示されます。

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

サーバーに接続する前に終了する理由がよくわかりません。また、チャネルに参加するように設定する方法も探しています。JOIN を使用する必要があることは認識していますが、それを実装する方法がわかりません。 .

4

1 に答える 1

3

おそらくコンストラクターで多くのことを行うべきではありませんが、ここで遭遇する問題はIRCWork()、ボットを新しくした後に呼び出しを行っていないことです。

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

EDITまた、コンストラクターの finally ブロックですべての接続を閉じているため、IRCWork() はとにかく機能しません。を実装してみIDisposableて、閉じるロジックを に入れてみてくださいDispose():

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

投稿されたコードのクイック リファクタリング

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();
        }
    }
}
于 2012-06-01T14:59:15.437 に答える