【问题标题】:Python IRC Bot won't join channels on some servers, and I don't know how to make it respond to user inputPython IRC Bot 不会加入某些服务器上的频道,我不知道如何让它响应用户输入
【发布时间】:2012-06-23 03:50:09
【问题描述】:

我有一个 Python IRC 机器人,我开始着手练习我的 Python。但是,对于某些服务器,它不会加入频道,但它可以成功登录。我还希望它对像 !test 这样的用户命令做出反应,但我不知道该怎么做。在它工作的服务器上,它成功地ping回来了。

from socket import socket, AF_INET, SOCK_STREAM
network = raw_input("Server: ")
port = 6667
chan = raw_input("Channel: ")
nick = raw_input("Nick: ")
irc=socket(AF_INET,SOCK_STREAM)
irc.connect((network, port))
a=irc.recv (4096)
print a
irc.send('NICK ' + nick + '\r\n')
irc.send('USER john_bot john_bot bla :john_bot\r\n')
irc.send('JOIN :' + chan + '\r\n')
irc.send('PRIVMSG ' + chan + ' :Hello.\r\n')

def ircSend(msg):
     print(msg)
     irc.send(msg)

while True:
    data = irc.recv(4096)
    print data
    if data.find('PING') != -1:
       ircSend('PONG ' + data.split()[1] + '\r\n')

【问题讨论】:

  • 这是一个使用套接字的学习练习吗?实际上,您希望查看主要为您完成的事情,例如 twistedmatrix.com/documents/8.2.0/api/…,并从中派生出您想要的功能集。
  • 糟糕,发布了旧链接 - 现在是 12.1 版(觉得 8 看起来有点滑稽) - twistedmatrix.com

标签: python irc bots


【解决方案1】:

在某些服务器上,您必须先用 PONG 响应 PING,然后才能真正执行任何操作。

ircSend('NICK ' + nick + '\r\n')
ircSend('USER john_bot john_bot bla :john_bot\r\n')

data = ircRecv() # explained later
if data.find('PING') != -1:
    ircSend('PONG ' + data.split()[1] + '\r\n')

ircSend('JOIN :' + chan + '\r\n')
ircSend('PRIVMSG ' + chan + ' :Hello.\r\n')

你真的不需要这个

a=irc.recv (4096)
print a

有时 IRC 服务器会同时发送多条线路(例如 MOTD 或 NAMES)。只要总字节数不超过 4096 就可以很好地处理它(有些行会分成两行)

data = irc.recv(4096)
for line in data.split('\r\n'):
    # process the line

如果一行会被切成两半是一个问题(这种情况很少发生,比如 PING 恰好在那里),我们可以一次接收一行并将其余字符留给套接字的缓冲区。但是这可能效率低一些(我还没有测试过,所以可能根本不重要)

def ircRecv():
    line = ''
    while 1: # same as while True:
        character = irc.recv(1)
        if character == '\n':
            break # exit the loop
        elif character != '\r':
            line += character
    print line
    return line

来自 IRC RFC 的第 8 页:

<message>  ::= [':' <prefix> <SPACE> ] <command> <params> <crlf>
<prefix>   ::= <servername> | <nick> [ '!' <user> ] [ '@' <host> ]
<command>  ::= <letter> { <letter> } | <number> <number> <number>
<SPACE>    ::= ' ' { ' ' }
<params>   ::= <SPACE> [ ':' <trailing> | <middle> <params> ]
<middle>   ::= <Any *non-empty* sequence of octets not including SPACE
           or NUL or CR or LF, the first of which may not be ':'>
<trailing> ::= <Any, possibly *empty*, sequence of octets not including
             NUL or CR or LF>
<crlf>     ::= CR LF

这意味着您始终可以像这样轻松且确定地获取消息的发件人:

# put this inside the main loop
# this will throw an IndexError when the connection is closed,
# an empty line does not contain any spaces
line = ircRecv()
if line.split()[0].find('!') != -1:
    # the first character must be a colon because <command> can't include
    # an exclamation mark
    someOneElsesNick = line[1:line.find('!')]
    command = line.split()[1]

有人打招呼时回答!

    if command == 'PRIVMSG':
        destination = line.split()[2] # channel or bot's nick
        # <trailing>, in this case, the message
        message = line[line[1:].find(':')+2 : ] # everything after the 2nd colon

        # we add one since we don't want include the <trailing> colon in
        # the message and an other one because line[1:].find() is one smaller 
        # number than line.find() would be

        # if we receive a private message, we have to respond to the sender,
        # not to ourself
        if destination == nick:
            destination = someOneElsesNick

        if message.startswith('hi!'):
            ircSend('PRIVMSG ' + destination + ' :Hi, '
            + someOneElsesNick + '!\r\n')

有关更多信息,请查看 IRC RFC:http://www.ietf.org/rfc/rfc1459.txt(尤其是第 2.3.1 和 4 节)。如果您不想处理 IRC 协议,请使用 Twisted :) http://twistedmatrix.com/trac/

【讨论】:

    猜你喜欢
    • 2016-12-21
    • 1970-01-01
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 2020-07-14
    • 2020-11-03
    • 2013-06-27
    • 1970-01-01
    相关资源
    最近更新 更多