Question

I've written some code using the information here as a guide line,

List users in IRC channel using Twisted Python IRC framework

I can successfully log the NAMES list to the console, however I've so far been unable to retrieve it to work with it further. Here is an excerpt of the code related to this matter:

class Alfred(irc.IRCClient):
    """ An IRC bot """

    # Voodoo magic for names
    def __init__(self, *args, **kwargs):
        self._namescallback = {}


    def names(self, channel):
        channel = channel.lower()
        d = defer.Deferred()
        if channel not in self._namescallback:
           self. _namescallback[channel] = ([], [])

        self._namescallback[channel][0].append(d)
        self.sendLine("NAMES %s" % channel)
        return d


    def irc_RPL_NAMREPLY(self, prefix, params):
        channel = params[2].lower()
        nicklist = params[3].split(' ')

        if channel not in self._namescallback:
            return

        n = self._namescallback[channel][1]
        n += nicklist


    def irc_RPL_ENDOFNAMES(self, prefix, params):
        channel = params[1].lower()
        if channel not in self._namescallback:
            return

        callbacks, namelist = self._namescallback[channel]

        for cb in callbacks:
            cb.callback(namelist)

        del self._namescallback[channel]

    # End of voodoo magic

    def get_names(self, nicklist):
        # Log the output to the log
        log.msg(nicklist)


    def has_op(self, channel, user):
        self.names('#' + channel).addCallback(self.get_names)


    def change_mode(self, channel, user, msg):
        target = msg[5:-3]
        params = [channel, '+o']

        self.has_op(channel, user)
        self.mode(channel, True, '+o', user=target)

What I want to achieve is to within the has_op function get a hold of the so called nicklist. So far I've been unable to do this using a trial and error approach, where I've tried to use print and return statements in reasonable places but this has yielded no output what so ever or instance / attribute errors. Obviously, I'm at a loss and I really need some guidance.

Was it helpful?

Solution

The idea of doing this "within" has_op is probably preventing you from making progress.

Make it work at all and then consider how you might improve the factoring of the implementation.

Notice that get_names has the data that you're interested in already. What do you want to do with that information? Check to see if it contains a certain name? For that, you'll need to know which name you're considering. To do this, you can use the feature of Deferred.addCallback that lets you pass an extra argument to the callback:

def get_names(self, nicklist, user):
    if user in nicklist:
        log.msg("%r has op!" % (user,))

def has_op(self, channel, user):
    self.names('#' + channel).addCallback(self.get_names, user)

Now perhaps what you really want isn't to log this information but to make a decision based on it in change_mode (I'm only guessing, of course).

If this is so, then you want to take advantage of another Deferred feature - the ability of each callback attached to a Deferred to process and change the result of the Deferred.

You can change has_op so that instead of logging information it also returns a Deferred - but this Deferred can have a True result if the given user has op in the given channel and a False result of they don't.

def get_names(self, nicklist, user):
    return user in nicklist

def has_op(self, channel, user):
    return self.names('#' + channel).addCallback(self.get_names, user)

Now you can use this functionality in change_mode:

def change_mode(self, channel, user, msg):
    target = msg[5:-3]

    checking = self.has_op(channel, user)
    checking.addCallback(self._ofIfNotOp, channel, target)

def _opIfNotOp(self, isOp, channel, user):
    if not isOp:
        self.mode(channel, True, '+o', user=user)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top