来自另一个来源的扭曲延迟变量

Twisted deferred variable from another source

我是 运行 一个 IRC 机器人,我终于弄明白了如何通过 whois 正确地获得用户的授权。我现在正在寻求实现此检查以引用我的数据库,而不是依赖于他们的用户名。

我有一个命令

def privmsg(self, user, channel, msg):
    if msg.startswith(".join"):
        # sends whois signal
        irc.IRCClient.whois(self, user, None)

我需要从输出源(IRC 服务器)调用的函数中获取变量,因此我不能只是 AddCallback

        auth = ???
        player = db.getplayer(auth)

我正在通过

接收授权
def irc_330(self, prefix, params):
    auth = params[2]

我似乎无法弄清楚如何将变量发送回第一个函数,甚至如何等待该信号返回。我的第一个函数将传递 irc_330() 在它开始之前所做的任何事情。

我能想到的唯一解决方案是创建一个回调函数,该函数将等待其中的函数调用,然后 return 我需要什么。但这似乎根本不对。

您 运行 遇到的问题是 IRCClient 的 API 相当 糟糕(对此感到抱歉!)。具体来说,它有 API 个像 .whois() 这样的 应该 return一个Deferred,但不要。

您可以通过制作这些 API 的 自己的 版本来解决此问题, 事实上,return一个Deferred.

一般的想法是 IRC 请求和响应没有请求 ID,所以 他们总是按顺序回答。这意味着你需要建立一个队列 first-in/first-out 个请求,以便您可以将它们与回复匹配 到达。此外,您需要将延迟触发与查询的 end 相匹配 (在您的情况下,WHOIS,因此 RPL_ENDOFWHOIS),因为 IRC 服务器可能 或者可能不会发送特定字段作为响应的一部分。

下面是一个示例实现:

from collections import deque
from twisted.internet.defer import Deferred
from twisted.words.protocols.irc import IRCClient

class NoAccount(Exception):
    "No account found."

class MyClient(IRCClient, object):

    def __init__(self):
        self._whoisQueue = deque()

    def deferredWhois(self, nick):
        result = Deferred()
        self._whoisQueue.append((result, nick))
        self.whois(nick)
        return result

    def irc_330(self, prefix, params):
        self._currentActiveNick = params[2]

    def irc_RPL_ENDOFWHOIS(self, prefix, params):
        deferredToFire, who = self._whoisQueue.popleft()
        currentActiveNick = self._currentActiveNick
        self._currentActiveNick = None

        if currentActiveNick is None:
            deferredToFire.errback(NoAccount(who))
        else:
            deferredToFire.callback(currentActiveNick)

这使得 deferredWhois 方法 return 成为 Deferred 给定昵称的帐户名称。

希望对您有所帮助!