.. _fbf.plugs.extra.watcher: watcher ~~~~~~~ .. automodule:: fbf.plugs.extra.watcher :show-inheritance: :members: :undoc-members: CODE ---- :: # fbf/plugs/common/watcher.py # # """ watch channels. channels events can be of remote origin. """ .. _fbf.plugs.extra.watcher_fbf_imports: 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 .. _fbf.plugs.extra.watcher_plugin_imports: plugin imports ----------------- :: from fbf.utils.format import formatevent .. _fbf.plugs.extra.watcher_basic_imports: basic imports ---------------- :: import copy import logging .. _fbf.plugs.extra.watcher_defines_: defines ---------- :: cpy = copy.deepcopy .. _fbf.plugs.extra.watcher_Watched_class: 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 .. _fbf.plugs.extra.watcher_watched_object: watched object ----------------- :: watched = Watched('channels') .. _fbf.plugs.extra.watcher_functions_: 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) .. _fbf.plugs.extra.watcher_callbacks_: 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) .. _fbf.plugs.extra.watcher_watcher-start_command: watcher-start command ------------------------ :: def handle_watcherstart(bot, event): """ arguments: [] - 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 ') .. _fbf.plugs.extra.watcher_watcher-reset_command: 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') .. _fbf.plugs.extra.watcher_watcher-stop_command: watcher-stop command ----------------------- :: def handle_watcherstop(bot, event): """ arguments: [] - 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') .. _fbf.plugs.extra.watcher_watcher-list_command: 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') .. _fbf.plugs.extra.watcher_watcher-subscribers_command: 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')