来自其他来源的扭曲延迟变量

时间:2015-12-25 01:55:04

标签: python twisted deferred

我正在运行一个IRC机器人,我终于想出了如何正确地获取用户的身份验证。我现在正在寻求实施此检查以引用我的数据库,而不是依赖于他们的用户名。

我有一个命令

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

我需要从outcoming source(IRC服务器)调用的函数中获取变量,因此我不能只使用AddCallback

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

我正在通过

收到身份验证
def irc_330(self, prefix, params):
    auth = params[2]

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

我能想到的唯一解决方案是创建一个回调函数,它将等待函数内部的调用,然后返回我需要的函数。但这似乎并不正确。

1 个答案:

答案 0 :(得分:4)

您遇到的问题是,IRCClient的API是相当的 很抱歉(对不起!)。具体来说,它有像.whois()这样的API 应该返回Deferred,但不要

您可以通过制作这些API的自己的版本来修复此问题, 实际上,返回Deferred

一般的想法是,IRC请求和响应没有请求ID,所以 他们总是按顺序回答。这意味着你需要建立一个队列 先进/先出请求,以便您可以将它们作为回复与回复相匹配 到达。此外,您需要将延迟触发与查询的 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方法返回一个Deferred方法 给定缺口的帐户名称。

希望这有帮助!