Python 扭曲的 irc:在 privmsg 方法中等待 whois 回复

Posted

技术标签:

【中文标题】Python 扭曲的 irc:在 privmsg 方法中等待 whois 回复【英文标题】:Python twisted irc: Wait for a whois reply inside privmsg method 【发布时间】:2013-06-01 18:38:31 【问题描述】:

我正在尝试使用 twisted.words.protocols.irc 模块制作 IRC 机器人。

机器人将解析来自通道的消息并解析它们以获取命令字符串。

一切正常,除非我需要机器人通过发送 whois 命令来识别昵称。在 privmsg 方法(我从中进行解析的方法)返回之前,不会处理 whois 回复。 示例:

from twisted.words.protocols import irc

class MyBot(irc.IRClient):

..........

    def privmsg(self, user, channel, msg):
        """This method is called when the client recieves a message"""
        if msg.startswith(':whois '):
            nick = msg.split()[1]
            self.whois(nick)
            print(self.whoislist)

    def irc_RPL_WHOISCHANNELS(self, prefix, params):
        """This method is called when the client recieves a reply for whois"""
        self.whoislist[prefix] = params

有没有办法让机器人在 self.whois(nick) 之后等待回复?

也许使用线程(我没有任何经验)

【问题讨论】:

【参考方案1】:

Deferred 是 Twisted 的核心概念,您必须熟悉它才能使用 Twisted。

基本上,您的 whois 检查函数应该返回一个 Deferred,当您收到 whois-reply 时将触发该函数。

【讨论】:

我想也许我没有给这个问题正确的标题,或者我没有正确理解文档,irc_RPL_WHOISCHANNELS 是返回数据的方法,而不是 whois,但是 irc_RPL_WHOISCHANNELS 永远不会执行,除非如果调用 whois 的方法 privmsg 退出。所以要重新格式化我的问题,我如何运行 privmsg 并仍然让 irc_RPL_WHOISCHANNELS 同时运行? 好吧,让我们暂时忘记Deferreds。你可以在你的类中有一个字段,其中包含一个标志“已收到消息,等待 whois 回复”,当你收到 whois 回复时,你会检查这个标志。【参考方案2】:

我设法通过将所有处理程序方法作为线程运行来解决这个问题,然后设置一个字段,如下 kirelagin 的建议,在运行 whois 查询并修改接收数据的方法之前 在收到回复时更改字段。它不是最优雅的解决方案,但它确实有效。

修改代码:

class MyBot(irc.IRClient):
..........

    def privmsg(self, user, channel, msg):
        """This method is called when the client recieves a message"""
        if msg.startswith(':whois '):
            nick = msg.split()[1]

            self.whois_status = 'REQUEST'
            self.whois(nick)
            while not self.whois_status == 'ACK':
                sleep(1)

            print(self.whoislist)

    def irc_RPL_WHOISCHANNELS(self, prefix, params):
        """This method is called when the client recieves a reply for whois"""
        self.whoislist[prefix] = params

    def handleCommand(self, command, prefix, params):
        """Determine the function to call for the given command and call
        it with the given arguments.
        """
        method = getattr(self, "irc_%s" % command, None)
        try:
            # all handler methods are now threaded.
            if method is not None:
                thread.start_new_thread(method, (prefix, params))
            else:
                thread.start_new_thread(self.irc_unknown, (prefix, command, params))
        except:
            irc.log.deferr()

    def irc_RPL_WHOISCHANNELS(self, prefix, params):
        """docstring for irc_RPL_WHOISCHANNELS"""
        self.whoislist[prefix] = params

    def irc_RPL_ENDOFWHOIS(self, prefix, params):
        self.whois_status = 'ACK'

【讨论】:

哦,sleep(1) 是绝对不行的。 当整个 Twisted 是关于避免线程时在线程中运行……好吧…… 我知道它不是最好的解决方案,但它是我能想到的最好的方法。但现在你知道我想做什么了,为什么不向我展示使用扭曲的最佳方法呢?关于 sleep(1),这只是一个示例,实际的 bot 更高,并且也有超时,因此它不会永远运行。 这根本不是解决方案。它非常破碎,你应该立即摆脱它。 仅使用 reactor.callInThread 线程化 privmsg 怎么样?这对我来说也很有效,因为它是阻塞的。

以上是关于Python 扭曲的 irc:在 privmsg 方法中等待 whois 回复的主要内容,如果未能解决你的问题,请参考以下文章

IRC Bot - 防洪(python)

以编程方式发送 IRC 命令

带有listentcp的扭曲IRCClient

在扭曲的 IRC 机器人中获取频道主题

Irc-bot 使用扭曲与期刊印刷

如何使基于扭曲的 irc 客户端通过 socks 代理连接?