我的IRC机器人不会收到大约一半的聊天命令.我在自定义渠道上使用freenode服务器.无论如何我可以改善这个吗?
图:
import sys import socket import string HOST="irc.freenode.net" PORT=6667 NICK="FedoraCoinBot" IDENT="CephonBot" REALNAME="CephonBot" CHAN="#cephbot" readbuffer="" s=socket.socket( ) s.connect((HOST, PORT)) s.send("NICK %s\r\n" % NICK) s.send("USER %s %s bla :%s\r\n" % (IDENT, HOST, REALNAME)) s.send("JOIN :%s\r\n" % CHAN) s.send("PRIVMSG %s :%s\r\n" % (CHAN, "Hi! I am a FedoraCoin Bot!")) s.send("PRIVMSG %s :%s\r\n" % (CHAN, "Designed by Cephon ;)")) # Loop while 1: text=s.recv(2040) print text readbuffer=readbuffer+s.recv(1024) temp=string.split(readbuffer, "\n") readbuffer=temp.pop( ) if text.find('!help') !=-1: s.send("PRIVMSG %s :%s\r\n" % (CHAN, "You said help")) for line in temp: line=string.rstrip(line) line=string.split(line) # Let's make it so that we don't get kicked -.- if(line[0]=="PING"): s.send("PONG %s\r\n" % line[1])
poke.. 5
让我们来看看输入处理的一些部分:
text=s.recv(2040) print text
首先,您会收到一些文字并打印出来.这是你在控制台输出中唯一看到的东西.
readbuffer=readbuffer+s.recv(1024)
接下来,您将阅读更多文本 - 后来从未打印过.因此它不会出现在您的控制台输出中,但它是唯一考虑用于实际命令解析的文本(您再也不会text
从上面访问).
temp=string.split(readbuffer, "\n")
你把它分成几行 - 没关系.但要小心,因为你收到了1024个字节,这并不意味着最后一行已经是来自服务器的完整响应.它可能会在两者之间中断,所以你应该等到你再收到另一个换行符(也就是说,在你读完它之前永远不会处理最后一行).
readbuffer=temp.pop( )
你得到第一行但是把readbuffer
它分配给我认为是包含所有剩余文本的缓冲区?您应该更清楚地了解变量的用途.
if text.find('!help') !=-1: s.send("PRIVMSG %s :%s\r\n" % (CHAN, "You said help"))
在这里,你text
再次检查.因此,只有!help
恰好在最初的2040字节中,才会处理它.其中的其他命令将被忽略; 并且!help
该块之外的命令也将被忽略.此外,这也将(错误地)处理诸如"看看机器人可以做什么,键入!帮助"等消息.
for line in temp: line=string.rstrip(line) line=string.split(line)
您正在迭代其余的行,并修改它们.然后你扔掉了变化.修改line
将不会在中更改数值temp
列表.
if(line[0]=="PING"): s.send("PONG %s\r\n" % line[1])
并且line
将是单行的单个字符串.因此,访问[0]
第一个字符永远不会等于四个字符的字符串.
因此,要解决此问题,您应该清理消息解析.您应该始终将新的读取文本附加到同一缓冲区.当你处理一行时,只需从该缓冲区中获取一行(第一行)并处理它.并真正分别处理每一行.像这样的东西:
buffer = '' while True: buffer += s.recv(1024) # are there completed lines we can parse? if '\n' in buffer: # only split once, keep the rest of the buffer line, buffer = buffer.split('\n', 1) # handle line if line.startswith('PING'): s.send('PONG {}\n'.format(line[5:])) elif line.startswith('PRIVMSG'): # this is an actual message; parse it, and handle the message pass
最后,从我自己的经验,你真的不应该抛弃这样的连接命令(NICK
,USER
和JOIN
那些).许多服务器会在您过早发送它们时忽略它们.而是先等待适当的响应,例如欢迎消息,它会告诉您服务器已为您的消息做好准备.
让我们来看看输入处理的一些部分:
text=s.recv(2040) print text
首先,您会收到一些文字并打印出来.这是你在控制台输出中唯一看到的东西.
readbuffer=readbuffer+s.recv(1024)
接下来,您将阅读更多文本 - 后来从未打印过.因此它不会出现在您的控制台输出中,但它是唯一考虑用于实际命令解析的文本(您再也不会text
从上面访问).
temp=string.split(readbuffer, "\n")
你把它分成几行 - 没关系.但要小心,因为你收到了1024个字节,这并不意味着最后一行已经是来自服务器的完整响应.它可能会在两者之间中断,所以你应该等到你再收到另一个换行符(也就是说,在你读完它之前永远不会处理最后一行).
readbuffer=temp.pop( )
你得到第一行但是把readbuffer
它分配给我认为是包含所有剩余文本的缓冲区?您应该更清楚地了解变量的用途.
if text.find('!help') !=-1: s.send("PRIVMSG %s :%s\r\n" % (CHAN, "You said help"))
在这里,你text
再次检查.因此,只有!help
恰好在最初的2040字节中,才会处理它.其中的其他命令将被忽略; 并且!help
该块之外的命令也将被忽略.此外,这也将(错误地)处理诸如"看看机器人可以做什么,键入!帮助"等消息.
for line in temp: line=string.rstrip(line) line=string.split(line)
您正在迭代其余的行,并修改它们.然后你扔掉了变化.修改line
将不会在中更改数值temp
列表.
if(line[0]=="PING"): s.send("PONG %s\r\n" % line[1])
并且line
将是单行的单个字符串.因此,访问[0]
第一个字符永远不会等于四个字符的字符串.
因此,要解决此问题,您应该清理消息解析.您应该始终将新的读取文本附加到同一缓冲区.当你处理一行时,只需从该缓冲区中获取一行(第一行)并处理它.并真正分别处理每一行.像这样的东西:
buffer = '' while True: buffer += s.recv(1024) # are there completed lines we can parse? if '\n' in buffer: # only split once, keep the rest of the buffer line, buffer = buffer.split('\n', 1) # handle line if line.startswith('PING'): s.send('PONG {}\n'.format(line[5:])) elif line.startswith('PRIVMSG'): # this is an actual message; parse it, and handle the message pass
最后,从我自己的经验,你真的不应该抛弃这样的连接命令(NICK
,USER
和JOIN
那些).许多服务器会在您过早发送它们时忽略它们.而是先等待适当的响应,例如欢迎消息,它会告诉您服务器已为您的消息做好准备.