【问题标题】:IRC Reading SocketsIRC 读取套接字
【发布时间】:2012-10-15 02:28:18
【问题描述】:

我正在制作一个机器人,除了输入之外,几乎所有东西都准备好了。我想要这样的东西:“!test word”并让它输出类似“word2”的东西。这是我用来输出数据的代码。我还想知道我的用户名(操作名)。抱歉,如果页面上的缩进关闭;这对我来说很好。

while True:

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

    if data.find ('!quit') != -1:
      irc.send ('QUIT\r\n')

    if data.find ('!enc %s\r\n' % werd) != -1:
      irc.send ("PRIVMSG %s :%s\r\n" % (channel,werd))

【问题讨论】:

  • 你可以find('!test word')吗?
  • 我想我有。新问题:PRIVMSG 不工作。
  • while 循环下没有任何缩进,这对你来说是不可能的。
  • 同时,即使您做对了,只要“PING”出现在字节 4094-4098 处,它就会中断。您可以编写自己的简单缓冲代码,但如果您不是在寻找高性能,并且不介意阻塞,那么调用irc.makefile() 可能要简单得多。特别是因为 IRC 是基于行的协议,所以您可以在结果上调用 readline()(或将其用作迭代器),并确保您一次只处理一个命令。
  • 另外,data.find('!enc %s\r\n' % werd) 将搜索您碰巧将werd 设置为的任何内容。这实际上是您想要的,还是您试图使其与该正数中的任何字符串匹配,并将werd 设置为匹配的值?

标签: python bots irc


【解决方案1】:

您的代码中存在一个根本缺陷,必须先修复才能进一步了解。

IRC 是基于行的协议,但您不是逐行阅读。相反,您一次最多读取 4096 个字节。这可能会返回一行的前半部分,或者一行的中间三分之一,或者一行的后三分之一,然后是两行完整的行和第四行的前两个字符。

如果您不明白为什么会出现问题:想象一下,一个read 返回以'\r\nPI' 结尾的内容,而下一个返回以'NG foo\r\n' 开头的内容。这两个都不匹配你的find('PING'),所以你会错过这个命令。

解决此问题的最简单方法是将循环更改为以下内容:

for line in irc.makefile():

作为一个小提示,您可能想要'!quit' in data 而不是data.find ('!quit') != -1

最后,我不认为这是你真正想要的(虽然我可能是错的):

if data.find ('!enc %s\r\n' % werd) != -1:
    irc.send ("PRIVMSG %s :%s\r\n" % (channel,werd))

如果werd 是来自其他地方的静态字符串,这将起作用,但根据您的描述,听起来您希望能够捕获任何命令!enc foo\r\n 并返回PRIVMSG #chan: foo\r\n,并捕获@ 987654334@ 并返回 PRIVMSG #chan: bar\r\n,以此类推,以表示有人可能键入的任何其他可能性。为此,您可能需要一个正则表达式,或者您可能只需要稍微复杂一点的字符串处理代码(例如,用空格分割data,如果任何元素匹配'!enc',下一个元素就是要发回的单词)。

下面是一个示例,说明一种方法可能会或可能不会像您正在尝试做的事情:

m = re.search(r'!enc (.*)\r\n', line)
if m:
    irc.send('PRIVMSG %s: %s\r\n' % (channel, m.group(1)))

我想要这样的东西:“!test word”并让它输出类似“word2”的东西

好的,那么当给定“word”时,它如何确定您想要“word2”?无论规则是什么,您显然都必须在某个地方对该规则进行编码。或者,如果您在编码方面需要帮助,您必须向我们描述。

来自cmets:

我只想要“!test x”。用户输入“!test x”,我对“x”做一些事情并输出更改

我假设您在这里使用x 作为元变量,而不是文字——也就是说,如果用户使用"!test x",您对"x" 执行操作,如果用户执行"!test y",您执行操作"y"等的东西。如果我错了,请告诉我。

显然,上面的代码不会捕捉到这一点,因为它正在搜索“enc”而不是“test”。但这是一个微不足道的变化:

m = re.search(r'!test (.*)\r\n', line)

至于在输出之前对x“做点什么”,m.group(1)就是上面的x,所以:

if m:
    irc.send('PRIVMSG %s: %s\r\n' % (channel, do_stuff_to(m.group(1))))

如果您不确定要发送、接收和解析什么,您可以随时添加打印语句来测试:

m = re.search(r'!test (.*)\r\n', line)
print m, m.groups() if m else ''
if m:
    print 'got %s, sending %s' % (m.group(1), do_stuff_to(m.group(1))))
    irc.send('PRIVMSG %s: %s\r\n' % (channel, do_stuff_to(m.group(1))))

如果您想查看套接字上发生了什么,有两种方法可以做到这一点:安装wireshark 并使用它来监视线路上的消息,或者使用netcat 设置一个假服务器。前者我就不解释了,因为要解释的太多了,而且已经有很好的教程了。但对于后者,就这么简单:打开终端并运行nc -kl 8888。然后让你的机器人连接到localhost:8888 而不是远程服务器。观察机器人发送给您的内容,然后将回复键入或粘贴到终端窗口中。 (在除 Windows 之外的几乎所有平台上,nc 都是内置的;在 Windows 上,您需要从某个地方获取 netcat 或 ncat,但我很确定 Wikipedia 页面有链接。)如果您需要进行大量调试,您可以将 netcat 设置为代理,仅在您的机器人和真实服务器之间来回转发消息并打印出所有通过的信息。

【讨论】:

  • 我只想要“!test x”。用户输入“!test x”,我对“x”做一些事情并输出更改。
  • 新编辑的版本是否回答了您的问题?我不得不承认,我发现很难理解你是什么,在这里没有问题。而且您还没有回答原始帖子中的 cmets。
  • irc.send('PRIVMSG %s: %s\r\n' % (channel, m.group(1))) 没有发送任何数据。我试过不带变量发送它,它仍然不会发送!
  • 我很困惑。在上面,您说“PRIVMSG 有效;仍然无法分离!test ”。上面的代码显示了如何将它分开,但在这里你说 PRIVMSG 没有发送任何数据。如果您可以在某处发布完整的程序以及您的测试场景,也许有人可以帮助您调试。但是您应该尝试自己调试它——例如,只需将一堆打印语句放入其中以确保变量在每个点都是您所期望的。
  • 快速思考:您的channel 变量是否包含“#”前缀?有没有可能它有一个'。还是里面的“*”?我已经有一段时间没有写 IRC 代码了,但如果我没记错的话,PRIVMSG channel foo 发送给名为channel 的用户,而不是名为#channel 的频道,#channel.two 发送给所有反向 DNS 为 @987654356 的用户@ 而不是一个名为 #channel.two 的频道……最后一个想法,但我会把它放在答案中而不是在这里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-24
  • 2017-10-19
  • 2011-10-29
  • 1970-01-01
相关资源
最近更新 更多