2015-12-25 68 views
0

我正在運行IRC bot,我終於想出瞭如何正確獲取用戶的身份驗證。我現在正在執行這個檢查來引用我的數據庫,而不是依靠他們的用戶名。來自其他來源的扭曲延期變量

我有一個命令

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

我需要從該得到由outcoming源(IRC服務器)調用的函數得到的變量,所以我不能只的addCallback

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

我通過收到驗證通過

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

我似乎無法弄清楚究竟如何發送變量返回t o第一個功能,甚至是如何等待該信號返回。我的第一個函數會在irc_330()開始前通過任何事情。

我能想到的唯一解決方案是創建一個回調函數,它將等待函數內部的調用,然後返回我需要的函數。但這似乎並不正確。

回答

4

你在這裏遇到的問題是IRCClient的API相當於 crummy(對不起!)。具體而言,它具有如.whois()的API,其中 應該返回Deferred,但不。

您可以通過你自己的這些API裏面做的解決這個問題, 其實,返回Deferred

總的想法是,IRC請求和響應沒有請求ID,所以他們總是按順序回答。這意味着您需要建立一個 先進先出請求的隊列,以便您可以在答覆 到達時將它們與答覆進行匹配。此外,由於IRC服務器可能會發送 或者可能不會將特定字段作爲響應的一部分發送,因此您需要將延遲觸發與查詢 (在您的情況下爲WHOIS,因此爲RPL_ENDOFWHOIS)的結尾相匹配。

這裏的僅僅是一個示例實現:

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與給定斷屑槽的 帳戶名火災。

希望這會有所幫助!