watcher

watch channels. channels events can be of remote origin.

class fbf.plugs.extra.watcher.Watched(filename)

Bases: fbf.lib.persist.PlugPersist

Watched object contains channels and subscribers.

available(channel)

check if channel is on whitelist.

channels(channel)

return channels on whitelist.

check(channel)

check if channel has subscribers.

disable(channel)

remove channel from whitelist.

enable(channel)

add channel to whitelist.

reset(channel)

unsubscribe a jid from a channel.

subscribe(botname, type, channel, jid)

subscrive a jid to a channel.

subscribers(channel)

get all subscribers of a channel.

unsubscribe(botname, type, channel, jid)

unsubscribe a jid from a channel.

fbf.plugs.extra.watcher.handle_watcherlist(bot, event)

no arguments - see what channels we are watching.

fbf.plugs.extra.watcher.handle_watcherreset(bot, event)

no arguments - reset all watcher for a channel.

fbf.plugs.extra.watcher.handle_watcherstart(bot, event)

arguments: [<channel>] - start watching a target (channel/wave).

fbf.plugs.extra.watcher.handle_watcherstop(bot, event)

arguments: [<channel>] - stop watching a channel.

fbf.plugs.extra.watcher.handle_watchersubscribers(bot, event)

” no arguments - show channels that are watching us.

fbf.plugs.extra.watcher.prewatchcallback(bot, event)

watch callback precondition.

fbf.plugs.extra.watcher.watchcallback(bot, event)

the watcher callback, see if channels are followed and if so send data.

fbf.plugs.extra.watcher.writeout(botname, type, channel, txt, eventjson)

output the watched event to the channel.

CODE

# fbf/plugs/common/watcher.py
#
#

""" watch channels. channels events can be of remote origin. """

fbf imports

from fbf.lib.commands import cmnds
from fbf.lib.callbacks import callbacks, remote_callbacks, last_callbacks, first_callbacks
from fbf.lib.persist import PlugPersist
from fbf.lib.fleet import getfleet
from fbf.utils.exception import handle_exception
from fbf.lib.examples import examples
from fbf.utils.locking import locked
from fbf.utils.generic import stripcolor
from fbf.lib.eventbase import EventBase

plugin imports

from fbf.utils.format import formatevent

basic imports

import copy
import logging

defines

cpy = copy.deepcopy

Watched class

class Watched(PlugPersist):

    """ Watched object contains channels and subscribers. """

    def __init__(self, filename):
        PlugPersist.__init__(self, filename)
        self.data.channels = self.data.channels or {}
        self.data.whitelist = self.data.whitelist or []
        self.data.descriptions = self.data.descriptions or {}

    def subscribe(self, botname, type, channel, jid):
        """ subscrive a jid to a channel. """
        channel = channel.lower()
        jid = str(jid)
        if channel not in self.data.channels: self.data.channels[channel] = []
        if not [botname, type, jid] in self.data.channels[channel]:
            self.data.channels[channel].append([botname, type, jid])
            self.save()
        return True

    def unsubscribe(self, botname, type, channel, jid):
        """ unsubscribe a jid from a channel. """
        channel = channel.lower()
        self.data.channels[channel].remove([botname, type, str(jid)])
        self.save()
        return True

    def reset(self, channel):
        """ unsubscribe a jid from a channel. """
        channel = channel.lower()
        self.data.channels[channel] = []
        self.save()
        return True

    def subscribers(self, channel):
        """ get all subscribers of a channel. """
        channel = channel.lower()
        try: return self.data.channels[channel]
        except KeyError: return []

    def check(self, channel):
        """ check if channel has subscribers. """
        channel = channel.lower()
        return channel in self.data.channels

    def enable(self, channel):
        """ add channel to whitelist. """
        channel = channel.lower()
        if not channel in self.data.whitelist:
            self.data.whitelist.append(channel)
            self.save()

    def disable(self, channel):
        """ remove channel from whitelist. """
        channel = channel.lower()
        try: self.data.whitelist.remove(channel)
        except ValueError: return False
        self.save()
        return True

    def available(self, channel):
        """ check if channel is on whitelist. """
        channel = channel.lower()
        return channel in self.data.whitelist

    def channels(self, channel):
        """ return channels on whitelist. """
        channel = channel.lower()
        res = []
        for chan, targets in self.data.channels.items():
            if channel in str(targets): res.append(chan)
        return res

watched object

watched = Watched('channels')

functions

bots = {}

def writeout(botname, type, channel, txt, eventjson):
    """ output the watched event to the channel. """
    event = EventBase().load(eventjson)
    global bots
    watchbot = None
    if botname in bots: watchbot = bots[botname]
    if not watchbot: watchbot = getfleet().byname(botname)
    if not watchbot: watchbot = getfleet().makebot(type, botname)
    if watchbot:
         if not botname in bots: bots[botname] = watchbot
         txt = watchbot.normalize(txt)
         txt = stripcolor(txt)
         watchbot.outnocb(channel, txt, event=event)

callbacks

def prewatchcallback(bot, event):
    """ watch callback precondition. """
    if event.isdcc: return False
    logging.debug("watcher - checking %s - %s" % (event.channel, event.userhost))
    if not event.channel: return False
    if not event.txt: return
    return watched.check(str(event.channel)) and event.how != "background" and event.forwarded

def watchcallback(bot, event):
    """ the watcher callback, see if channels are followed and if so send data. """
    #if not event.allowwatch: logging.warn("watch - allowwatch is not set - ignoring %s" % event.userhost) ; return
    subscribers = watched.subscribers(event.channel)
    watched.data.descriptions[event.channel.lower()] = event.title
    logging.info("watcher - %s - %s" % (event.channel, str(subscribers)))
    for item in subscribers:
        try:
            try: (botname, type, channel) = item
            except ValueError: continue
            if not event.allowatch: pass
            elif channel not in event.allowwatch: logging.warn("watcher - allowwatch denied %s - %s" % (channel, event.allowwatch)) ; continue
            m = formatevent(bot, event, subscribers, True)
            if event.cbtype in ['OUTPUT', 'JOIN', 'PART', 'QUIT', 'NICK']: txt = "[!] %s" % m.txt
            else: txt = "[%s] %s" % (m.nick or event.nick or event.auth, m.txt)
            if txt.count('] [') > 2: logging.debug("watcher - %s - skipping %s" % (type, txt)) ; continue
            logging.warn("watcher - forwarding to %s" % channel)
            writeout(botname, type, channel, txt, event.tojson())
        except Exception as ex: handle_exception()

first_callbacks.add('BLIP_SUBMITTED', watchcallback, prewatchcallback)
first_callbacks.add('PRIVMSG', watchcallback, prewatchcallback)
first_callbacks.add('JOIN', watchcallback, prewatchcallback)
first_callbacks.add('PART', watchcallback, prewatchcallback)
first_callbacks.add('QUIT', watchcallback, prewatchcallback)
first_callbacks.add('NICK', watchcallback, prewatchcallback)
first_callbacks.add('OUTPUT', watchcallback, prewatchcallback)
first_callbacks.add('MESSAGE', watchcallback, prewatchcallback)
first_callbacks.add('CONSOLE', watchcallback, prewatchcallback)
first_callbacks.add('WEB', watchcallback, prewatchcallback)
first_callbacks.add('DISPATCH', watchcallback, prewatchcallback)
first_callbacks.add('TORNADO', watchcallback, prewatchcallback)

watcher-start command

def handle_watcherstart(bot, event):
    """ arguments: [<channel>] - start watching a target (channel/wave). """
    target = event.rest or event.channel
    watched.subscribe(bot.cfg.name, bot.type, target, event.channel)
    if not target in event.chan.data.watched:
        event.chan.data.watched.append(target)
        event.chan.save()
    event.done()

cmnds.add('watcher-start', handle_watcherstart, 'OPER')
cmnds.add('watch', handle_watcherstart, 'USER')
examples.add('watcher-start', 'start watching a channel. ', 'watcher-start <channel>')

watcher-reset command

def handle_watcherreset(bot, event):
    """ no arguments - reset all watcher for a channel. """
    watched.reset(event.channel)
    event.done()

cmnds.add('watcher-reset', handle_watcherreset, ['OPER', 'USER', 'GUEST'])
examples.add('watcher-reset', 'stop watching', 'watcher-reset')

watcher-stop command

def handle_watcherstop(bot, event):
    """ arguments: [<channel>] - stop watching a channel. """
    if not event.rest: target = event.origin
    else: target = event.rest.strip()
    try: watched.unsubscribe(bot.cfg.name, bot.type, target, event.channel)
    except Exception as ex: event.reply("error removing watcher: %s" % str(ex)) ; return
    if target in event.chan.data.watched:
        event.chan.data.watched.remove(target)
        event.chan.save()
    event.done()

cmnds.add('watcher-stop', handle_watcherstop, ['OPER', 'USER', 'GUEST'])
examples.add('watcher-stop', 'stop watching a channel', 'watcher-stop #dunkbots')

watcher-list command

def handle_watcherlist(bot, event):
    """ no arguments - see what channels we are watching. """
    chans = watched.channels(event.channel)
    if chans:
        res = []
        for chan in chans:
            try: res.append(chan)
            except KeyError: res.append(chan)
        event.reply("channels watched on %s: " % event.channel, res)

cmnds.add('watcher-list', handle_watcherlist, ['OPER', 'USER', 'GUEST'])
examples.add('watcher-list', 'show what channels we are watching', 'watcher-list')

watcher-subscribers command

def handle_watchersubscribers(bot, event):
    """" no arguments - show channels that are watching us. """
    event.reply("watchers for %s: " % event.channel, watched.subscribers(event.channel))

cmnds.add('watcher-subscribers', handle_watchersubscribers, ['OPER', 'USER', 'GUEST'])
examples.add('watcher-subscribers', 'show channels that are watching us. ', 'watcher-list')