关于c#:ircDotNet bot无法从IRC频道获取消息,长时间登录/注销

ircDotNet bot fails to get messages from IRC channel, long login/logout

我正在尝试为IRC通道编写bot,它将从通道读取消息,识别它们是否是命令,并根据发送的命令执行一些操作。我之所以选择ircdotnet,是因为它是唯一一个包含了一些如何使用它的示例的库,但是它们实际上已经非常过时了,只有一半是有效的。我在C和编程方面的经验不足,根本不允许我在没有好例子的情况下理解东西:(

所以我的程序现在做的是:

  • 使用密码登录到服务器
  • 加入通道
  • 注销(非常麻烦)

我不能捕捉和发送任何来自和到一个频道的信息,我不能立即注销。

用于登录的全局类和事件中无处不在的IRCClient类示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 public IrcRegistrationInfo  irc_iri
        {
            get
            {
                return new IrcUserRegistrationInfo()
                {
                    NickName ="jsBot",
                    UserName ="jsBot",
                    RealName ="jsBot",
                    Password ="oauth:p4$$w0rdH3Re48324729214812489"
                };
            }
        }
   public IrcClient gIrcClient = new IrcClient();

所有当前事件:

1
2
3
4
5
6
7
8
9
10
private void Form1_Load(object sender, EventArgs e)
    {
        try
        {
            gIrcClient.Connected += ircClient_Connected;
            gIrcClient.Disconnected += gIrcClient_Disconnected;
            gIrcClient.FloodPreventer = new IrcStandardFloodPreventer(1, 10000);
        }
        catch (Exception ex) { MessageBox.Show(ex.ToString());}
    }

登录按钮代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;

            if (!gIrcClient.IsConnected)
            {
                button1.Text ="Connecting...";
                gIrcClient.Connect("irc.twitch.tv", 6667, false, irc_iri);
            }
            else
            {
                button1.Text ="Disconnecting...";
                gIrcClient.Quit(5000,"bye");
            }
        }

逻辑是:程序检查IRCClient是否连接,并执行一些操作。然后在该操作之后,相应的事件将升起,再次启用该按钮。但退出功能工作很慢,或者根本不工作,bot将一直在通道中,直到我不关闭程序(也许我需要释放ircclient?)

连接和断开事件。在连接事件中,bot将加入通道。按下Connect(连接)按钮后约30秒,Bot出现在频道上,但在2-3秒后引发Connected(连接)事件。断开-断开事件也会很快发生,但bot在通道上停留的时间更长(约120秒)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  void ircClient_Connected(object sender, EventArgs e)
        {
            try
            {
                if (button1.InvokeRequired)
                {
                    MethodInvoker del = delegate {
                        button1.Text ="Disconnect";
                        button1.Enabled = true; };
                    button1.Invoke(del);
                }
                else
                {
                    button1.Text ="Disconnect";
                    button1.Enabled = true;
                }
                gIrcClient.Channels.Join("#my_channel");  
                gIrcClient.LocalUser.JoinedChannel += LocalUser_JoinedChannel;            
            }
            catch (Exception ex) { MessageBox.Show(ex.Message); }
        }

        void gIrcClient_Disconnected(object sender, EventArgs e)
        {
            if (!gIrcClient.IsConnected)
            {
                try
                {
                    if (button1.InvokeRequired)
                    {
                        MethodInvoker del = delegate
                        {
                            button1.Text ="Connect";
                            button1.Enabled = true;
                        };
                        button1.Invoke(del);
                    }
                    else
                    {
                        button1.Text ="Connect";
                        button1.Enabled = true;
                    }
                }
                catch (Exception ex) { MessageBox.Show(ex.Message); }
            }
            else gIrcClient.Disconnect();
        }

加入通道和消息接收事件。他们从不抚养孩子,不知道为什么。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 void LocalUser_JoinedChannel(object sender, IrcChannelEventArgs e)
        {
            try
            {                
                gIrcClient.Channels[0].MessageReceived += Form1_MessageReceived;
                gIrcClient.LocalUser.SendMessage(e.Channel,"test");
                MessageBox.Show(gIrcClient.Channels[0].Users[0].User.NickName);
                MessageBox.Show("bot_join_channel_event_raised");
            }
            catch (Exception ex) { MessageBox.Show(ex.Message); }
        }

        void Form1_MessageReceived(object sender, IrcMessageEventArgs e)
        {
            try
            {
                if (e.Text.Equals("asd"))
                    gIrcClient.LocalUser.SendMessage(e.Targets,"received");
            }
            catch (Exception ex) { MessageBox.Show(ex.Message); }
        }

所以,主要的问题是:我如何捕捉来自频道的消息,以及如何向频道发送消息?我会很感激任何例子。您可以在以下位置找到所有代码:http://pastebin.com/tbkfl3vq谢谢


在添加事件之前尝试加入频道。

1
2
  gIrcClient.Channels.Join("#my_channel");  
  gIrcClient.LocalUser.JoinedChannel += LocalUser_JoinedChannel;

我的建议是先尝试添加事件,如下所示:

1
2
  gIrcClient.LocalUser.JoinedChannel += LocalUser_JoinedChannel;
  gIrcClient.Channels.Join("#my_channel");

irc.net库中有一个bug,twitch.tv使用的是一个非标准的消息回复,它正在触发irc.net。

我在这里创建了一个描述它的bug。但基本上抽搐发出"欢迎,GLHF!"作为RPL_欢迎信息。IRC RFC描述了"欢迎使用互联网中继网络"消息的格式。@。

irc.net将glhf从欢迎消息中解析为您的昵称,该昵称用于触发JoinedChannel和MessageReceived事件等操作。

我的解决方案是下载源代码,并在接收到RPL_欢迎信息时指出它在哪里设置了昵称。它从传递给ircclient构造函数的ircRegistrationInfo中正确设置昵称,不需要从twitch的欢迎消息中进行解析。不确定这是否适用于其他IRC服务器。

该函数在ircclientmessageprocessing.cs中称为processmessagereplywelcome:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    /// <summary>
    /// Process RPL_WELCOME responses from the server.
    /// </summary>
    /// <param name="message">The message received from the server.</param>
    [MessageProcessor("001")]
    protected void ProcessMessageReplyWelcome(IrcMessage message)
    {
        Debug.Assert(message.Parameters[0] != null);

        Debug.Assert(message.Parameters[1] != null);
        this.WelcomeMessage = message.Parameters[1];

        // Extract nick name, user name, and host name from welcome message. Use fallback info if not present.
        var nickNameIdMatch = Regex.Match(this.WelcomeMessage.Split(' ').Last(), regexNickNameId);
        //this.localUser.NickName = nickNameIdMatch.Groups["nick"].GetValue() ?? this.localUser.NickName;
        this.localUser.UserName = nickNameIdMatch.Groups["user"].GetValue() ?? this.localUser.UserName;
        this.localUser.HostName = nickNameIdMatch.Groups["host"].GetValue() ?? this.localUser.HostName;

        this.isRegistered = true;
        OnRegistered(new EventArgs());
    }

一个更复杂的解决方案可能是细化昵称regex,使其与glhf不匹配!,我认为这不是一个有效的昵称。

IRC.NET使用区分大小写的字符串比较按昵称查找用户。因此,您为昵称传递到ircRegistrationInfo的值必须与twitch在与您相关的消息中使用的大小写匹配。都是小写的。