.. _fbf.plugs.extra.hubbub: hubbub ~~~~~~ .. automodule:: fbf.plugs.extra.hubbub :show-inheritance: :members: :undoc-members: CODE ---- :: # fbf/plugs/extra/hubbub.py # # """ the hubbub mantra is of the following: use the hb-register command to register url and start a feed in in one pass. """ .. _fbf.plugs.extra.hubbub_fbf_imports: fbf imports -------------- :: from fbf.lib.callbacks import callbacks from fbf.lib.commands import cmnds from fbf.lib.examples import examples from fbf.lib.persist import Persist, PlugPersist from fbf.utils.pdol import Pdol from fbf.utils.pdod import Pdod from fbf.utils.generic import jsonstring from fbf.utils.lazydict import LazyDict from fbf.utils.url import useragent, geturl2 from fbf.utils.statdict import StatDict from fbf.utils.exception import handle_exception from fbf.lib.fleet import getfleet from fbf.lib.channelbase import ChannelBase from fbf.utils.url import posturl from fbf.lib.errors import NoSuchBotType, RequireError from fbf.lib.threads import start_new_thread from fbf.lib.datadir import getdatadir from fbf.lib.fbfimport import import_byfile from fbf.imports import getfeedparser from fbf.api.hooks import get_hooks, post_hooks from fbf.utils.creds import getcredsmod feedparser = getfeedparser() .. _fbf.plugs.extra.hubbub_basic_imports: basic imports ---------------- :: import base64 import logging import urllib.request, urllib.parse, urllib.error import urllib.parse import uuid import os import time import socket .. _fbf.plugs.extra.hubbub_subscribe_function: subscribe function --------------------- :: def subscribe(url, host): """ subscribe to an hubbub feed. """ subscribe_args = { 'hub.callback': urllib.parse.urljoin('https://', host, '/hubbub'), 'hub.mode': 'subscribe', 'hub.topic': url, 'hub.verify': 'async', 'hub.verify_token': str(uuid.uuid4()), } headers = {} credentials = getcredsmod(doraise=True) if credentials.HUB_CREDENTIALS: auth_string = "Basic " + str(base64.b64encode(bytes("%s:%s" % tuple(credentials.HUB_CREDENTIALS), "utf-8")), "utf-8") headers['Authorization'] = auth_string logging.warn("subscribe - trying %s (%s)" % (credentials.HUB_URL, url)) logging.warn("subscribe - %s" % str(headers)) response = posturl(credentials.HUB_URL, headers, subscribe_args) return response .. _fbf.plugs.extra.hubbub_tinyurl_import: tinyurl import ----------------- :: try: from fbf.utils.tinyurl import get_tinyurl except ImportError: def get_tinyurl(url): return [url, ] .. _fbf.plugs.extra.hubbub_defines_: defines ---------- :: allowedtokens = ['updated', 'link', 'summary', 'tags', 'author', 'content', 'title', 'subtitle'] savelist = [] possiblemarkup = {'separator': 'set this to desired item separator', \ 'all-lines': "set this to 1 if you don't want items to be aggregated", \ 'tinyurl': "set this to 1 when you want to use tinyurls", 'skipmerge': \ "set this to 1 if you want to skip merge commits", 'reverse-order': 'set \ this to 1 if you want the items displayed with oldest item first'} def find_self_url(links): """ find home url of feed. """ for link in links: if link.rel == 'self': return link.href .. _fbf.plugs.extra.hubbub_NoSuchFeed_exception: NoSuchFeed exception ----------------------- :: class NoSuchFeed(Exception): """ there is no such feed in the feed database. """ pass .. _fbf.plugs.extra.hubbub_hubbub_get_function: hubbub_get function ---------------------- :: def hubbub_get(bot, event): logging.warn('incoming GET') #print dir(event.handler) #print dir(event.request) #print event.request #print event.request.arguments if event.request.arguments['hub.mode'][0] == 'unsubscribe': event.request.headers['Content-Type'] = 'text/plain' event.reply(event.request.arguments['hub.challenge'][0]) event.finish() return if event.request.arguments['hub.mode'][0] != 'subscribe': event.handler.send_error(400) ; return event.request.headers['Content-Type'] = 'text/plain' event.reply(event.request.arguments['hub.challenge'][0]) event.finish() .. _fbf.plugs.extra.hubbub_hubbub_post_function: hubbub_post function ----------------------- :: def hubbub_post(bot, event): """Handles new content notifications.""" logging.warn("incoming POST") try: watcher.incoming(event.request.body) except IndexError: logging.error("hubbub plugin did not load properly") except Exception as ex: handle_exception() event.handler.send_error(500) event.finish() .. _fbf.plugs.extra.hubbub_HubbubItem_class: HubbubItem class ------------------- :: class HubbubItem(Persist): """ item that contains hubbub data """ def __init__(self, name, url="", owner="", itemslist=['title', 'link'], watchchannels=[], running=1): filebase = getdatadir() + os.sep + 'plugs' + os.sep + 'fbf.plugs.extra.hubbub' + os.sep + name Persist.__init__(self, filebase + os.sep + name + '.core') if not self.data: self.data = {} self.data = LazyDict(self.data) self.data['name'] = self.data.name or str(name) self.data['url'] = self.data.url or str(url) self.data['owner'] = self.data.owner or str(owner) self.data['watchchannels'] = self.data.watchchannels or list(watchchannels) self.data['running'] = self.data.running or running self.itemslists = Pdol(filebase + os.sep + name + '.itemslists') self.markup = Pdod(filebase + os.sep + name + '.markup') def save(self): """ save the hubbub items data. """ Persist.save(self) self.itemslists.save() self.markup.save() def ownercheck(self, userhost): """ check is userhost is the owner of the feed. """ try: return self.data.owner == userhost except KeyError: pass return False def fetchdata(self): """ get data of rss feed. """ url = self.data['url'] if not url: logging.warn("%s doesnt have url set" % self.data.name) return [] result = feedparser.parse(url, agent=useragent()) logging.debug("got result from %s" % url) if result and 'bozo_exception' in result: logging.info('%s bozo_exception: %s' % (url, result['bozo_exception'])) try: status = result.status logging.info("status is %s" % status) except AttributeError: status = 200 if status != 200 and status != 301 and status != 302: raise RssStatus(status) return result.entries .. _fbf.plugs.extra.hubbub_HubbubWatcher_class: HubbubWatcher class ---------------------- :: class HubbubWatcher(PlugPersist): """ this watcher helps with the handling of incoming POST. also maitains index of feed names. """ def __init__(self, filename, host): PlugPersist.__init__(self, filename) if not self.data: self.data = LazyDict() if 'names' not in self.data: self.data['names'] = [] if 'urls' not in self.data: self.data['urls'] = {} if 'feeds' not in self.data: self.data['feeds'] = {} if 'host' not in self.data: self.data['host'] = host self.feeds = {} def add(self, name, url, owner): """ add a feed to the database. """ if not name in self.data['names']: self.data['names'].append(name) self.data['urls'][url] = name self.save() item = HubbubItem(name, url, owner) if item.data.url != url: return False item.save() self.feeds[name] = item return True def byname(self, name): """ retrieve a feed by it's name. """ if name in self.feeds: return self.feeds[name] item = HubbubItem(name) if item.data.url: self.feeds[name] = item ; return item def byurl(self, url): """ retrieve a feed by it's url. """ try: name = self.data['urls'][url] return self.byname(name) except KeyError: pass def cloneurl(self, url, auth): """ add feeds from remote url. """ data = geturl2(url) got = [] for line in data.split('\n'): try: (name, url) = line.split() except ValueError: logging.debug("can't split %s line" % line) continue if url.endswith('
'): url = url[:-4] self.add(name, url, auth) got.append(name) return got def watch(self, name): """ make feed ready for watching and mark it running. """ logging.debug('trying %s hubbub feed' % name) item = self.byname(name) if item == None: raise NoSuchFeed(name) if not item.data.running: item.data.running = 1 item.data.stoprunning = 0 item.save() subscribe(item.data['url'], self.data.host) logging.info('started %s watch' % name) def work(self, botname, type, channel, entries, url, *args, **kwargs): logging.debug("in work .. %s" % str(entries)) try: item = self.byurl(url) name = item.data.name try: fleet = getfleet() bot = fleet.byname(botname) if not bot: logging.warn("can't find %s bot in fleet" % botname) ; return except NoSuchBotType as ex: logging.warn("%s" % str(ex)) ; return if not bot: logging.error("can't find %s bot in fleet" % type) ; return res2 = entries if not res2: logging.info("no updates for %s (%s) feed available" % (item.data.name, channel)) ; return if item.markup.get(jsonstring([name, channel]), 'reverse-order'): res2 = res2[::-1] if item.markup.get(jsonstring([name, channel]), 'all-lines'): for i in res2: response = self.makeresponse(name, [i, ], channel) try: bot.say(channel, response) except Exception as ex: handle_exception() else: sep = item.markup.get(jsonstring([name, channel]), 'separator') if sep: response = self.makeresponse(name, res2, channel, sep=sep) else: response = self.makeresponse(name, res2, channel) bot.say(channel, response) except Exception as ex: handle_exception() def incoming(self, data): """ process incoming hubbub data. """ result = feedparser.parse(data) url = find_self_url(result.feed.links) logging.debug("%s - %s" % (url, data)) try: item = self.byurl(url) if not item: logging.warn("can't find feed for %s" % url) ; return if not item.data.running: logging.warn("%s is not in running mode" % item.data.url) ; return if not item.data.url or item.data.url == 'urlnotset': item.data.url = url item.save() if item: loopover = item.data.watchchannels name = item.data.name else: logging.warn("can't find %s item" % url) ; return logging.warn("loopover in %s peek is: %s" % (name, loopover)) counter = 1 for i in loopover: if len(i) == 3: try: (botname, type, channel) = i except: try: (botname, type, channel) = loads(i) except: logging.warn('%s is not in the format (botname, bottype, channel)' % str(item)) continue else: logging.warn('%s is not in the format (botname, bottype, channel)' % item.data.url) continue counter += 1 start_new_thread(self.work, (botname, type, channel, result.entries, url), {"_countdown": counter}) except Exception as ex: handle_exception(txt=url) return True def getall(self): """ reconstruct all feeditems into self.feeds. """ for name in self.data['names']: self.feeds[name] = HubbubItem(name) return self.feeds def ownercheck(self, name, userhost): """ check if userhost is the owner of feed. """ try: return self.byname(name).ownercheck(userhost) except (KeyError, AttributeError): pass return False def makeresult(self, name, target, data): """ make a result (txt) of a feed depending on its itemlist (tokens) and markup. """ item = self.byname(name) res = [] for j in data: tmp = {} if not item.itemslists.data[jsonstring([name, target])]: return [] for i in item.itemslists.data[jsonstring([name, target])]: try: tmp[i] = str(j[i]) except KeyError: continue res.append(tmp) return res def makeresponse(self, name, res, channel, sep=" .. "): """ loop over result to make a response. """ item = self.byname(name) result = "[%s] - " % name try: itemslist = item.itemslists.data[jsonstring([name, channel])] except KeyError: item = self.byname(name) if item == None: return "no %s rss item" % name else: item.itemslists.data[jsonstring([name, channel])] = ['title', 'link'] item.itemslists.save() for j in res: if item.markup.get(jsonstring([name, channel]), 'skipmerge') and 'Merge branch' in j['title']: continue resultstr = "" for i in item.itemslists.data[jsonstring([name, channel])]: try: ii = getattr(j, i) if not ii: continue ii = str(ii) if ii.startswith('http://'): if item.markup.get(jsonstring([name, channel]), 'tinyurl'): try: tinyurl = get_tinyurl(ii) logging.debug('rss - tinyurl is: %s' % str(tinyurl)) if not tinyurl: resultstr += "%s - " % ii else: resultstr += "%s - " % tinyurl[0] except Exception as ex: handle_exception() resultstr += "%s - " % item else: resultstr += "%s - " % ii else: resultstr += "%s - " % ii.strip() except (KeyError, AttributeError) as ex: logging.info('%s - %s' % (name, str(ex))) continue resultstr = resultstr[:-3] if resultstr: result += "%s %s " % (resultstr, sep) return result[:-(len(sep)+2)] def stopwatch(self, name): """ disable running status of the feed. """ try: feed = self.byname(name) feed.data.running = 0 feed.save() return True except KeyError: pass return False def list(self): """ return feed names. """ feeds = self.data['names'] return feeds def runners(self): """ show names/channels of running watchers. """ result = [] for name in self.data['names']: z = self.byname(name) if z.data.running == 1 and not z.data.stoprunning: result.append((z.data.name, z.data.watchchannels)) return result def listfeeds(self, botname, type, channel): """ show names/channels of running watcher. """ result = [] for name in self.data['names']: z = self.byname(name) if not z or not z.data.running: continue if jsonstring([botname, type, channel]) in z.data.watchchannels or [botname, type, channel] in z.data.watchchannels: result.append(z.data.name) return result def getfeeds(self, channel, botname, type=None): """ get all feeds running in a channel. """ chan = ChannelBase(channel, botname) return chan.data.feeds def url(self, name): """ return url of a feed. """ feed = self.byname(name) if feed: return feed.data.url def seturl(self, name, url): """ set url of hubbub feed. """ feed = self.byname(name) feed.data.url = url feed.save() return True def fetchdata(self, name): """ fetch the feed ourselves instead of receiving push items. """ return self.byname(name).fetchdata() def scan(self, name): """ scan a rss url for tokens. """ keys = [] items = self.fetchdata(name) for item in items: for key in item: if key in allowedtokens: keys.append(key) statdict = StatDict() for key in keys: statdict.upitem(key) return statdict.top() def startwatchers(self): """ enable all runnable feeds """ for name in self.data['names']: z = self.byname(name) if z.data.running: self.watch(z.data.name) def start(self, botname, type, name, channel): """ start a feed in a channel. """ item = self.byname(name) if not item: logging.info("we don't have a %s feed" % name) return False target = channel if not jsonstring([botname, type, target]) in item.data.watchchannels and not [botname, type, target] in item.data.watchchannels: item.data.watchchannels.append([botname, type, target]) item.itemslists.data[jsonstring([name, target])] = ['title', 'link'] item.markup.set(jsonstring([name, target]), 'tinyurl', 1) item.data.running = 1 item.data.stoprunning = 0 item.save() watcher.watch(name) logging.debug("started %s feed in %s channel" % (name, channel)) return True def stop(self, botname, type, name, channel): """ stop watching a feed. """ item = self.byname(name) if not item: return False try: logging.warn("trying to remove %s from %s feed list" % (name, channel)) chan = ChannelBase(channel, botname) chan.data.feeds.remove(name) chan.save() except ValueError: logging.warn("can't remove %s from %s feed list" % (name, channel)) try: item.data.watchchannels.remove([botname, type, channel]) item.save() logging.debug("stopped %s feed in %s channel" % (name, channel)) except ValueError: return False return True .. _fbf.plugs.extra.hubbub_plugin_initialisation: plugin initialisation ------------------------ :: def init(): get_hooks.register("/api/hubbub", hubbub_get) post_hooks.register("/api/hubbub", hubbub_post) .. _fbf.plugs.extra.hubbub_plugins_shutdown: plugins shutdown ------------------- :: def shutdown(): get_hooks.unregister("/api/hubbub") post_hooks.unregister("/api/hubbub") .. _fbf.plugs.extra.hubbub_dummycb_to_make_sure_this_plugin_loads_on_startup: dummycb to make sure this plugin loads on startup ---------------------------------------------------- :: def dummycb(bot, event): pass callbacks.add("START", dummycb) .. _fbf.plugs.extra.hubbub_work_function: work function ---------------- :: def work(botname, type, channel, result, item, *args, **kwargs): """ worker function used in defer. """ watcher.work(botname, type, channel, result, item, *args, **kwargs) .. _fbf.plugs.extra.hubbub_the_watcher_object: the watcher object --------------------- :: watcher = HubbubWatcher('hubbub', socket.gethostname()) .. _fbf.plugs.extra.hubbub_size_function: size function ---------------- :: def size(): """ return number of watched rss entries. """ return watcher.size() .. _fbf.plugs.extra.hubbub_hb-subscribe_command: hb-subscribe command ----------------------- :: def handle_hubbubsubscribe(bot, event): """ arguments: [] - subscribe to a hubbub feed, provide a url if the feed is not yet registered. """ for name in event.args: item = watcher.byname(name) if not item: event.reply("%s feed is not yet added .. see hb-add" % name) ; continue url = item.data.url if not url: event.reply('please provide a url for %s feed' % name) ; return if not url.startswith('http://'): event.reply('%s doesnt start with "http://"' % url) if name not in watcher.data['urls']: watcher.add(name, url, event.channel) if not watcher.byname(name): watcher.add(name, url, event.channel) response = subscribe(url, socket.gethostname()) event.reply("subscription send: %s - %s" % (url, response.status)) cmnds.add('hb-subscribe', handle_hubbubsubscribe, ['USER',]) examples.add('hb-subscribe', 'subscribe to a feed', 'hb-subscribe fbf https://github.com/feedbackflow/fbfbot/commits/master.atom') .. _fbf.plugs.extra.hubbub_hb-add_command: hb-add command ----------------- :: def handle_hubbubadd(bot, ievent): """ arguments: - add a hubbub item (name/url combo). """ try: (name, url) = ievent.args except ValueError: ievent.missing(' ') ; return try: result = subscribe(url, socket.gethostname()) except RequireError as ex: ievent.reply(str(ex)) ; return if int(result.status) > 200 and int(result.status) < 300: watcher.add(name, url, ievent.userhost) ievent.reply('%s feed added' % name) else: ievent.reply('%s feed NOT added. status code is %s' % (name, result.status)) cmnds.add('hb-add', handle_hubbubadd, 'USER') examples.add('hb-add', 'hubbub-add to the watcher', 'hb-add fbf https://github.com/feedbackflow/fbfbot/commits/master.atom') .. _fbf.plugs.extra.hubbub_hb-watch_command: hb-watch command ------------------- :: def handle_hubbubwatch(bot, ievent): """ arguments: - enable a feed for watching (per channel). """ try: name = ievent.args[0] except IndexError: ievent.missing('') ; return item = watcher.byname(name) if item == None: ievent.reply("we don't have a %s hubbub item" % name) ; return got = None if not item.data.running or item.data.stoprunning: item.data.running = 1 item.data.stoprunning = 0 got = True item.save() try: watcher.watch(name) except Exception as ex: ievent.reply(str(ex)) ; return if got: ievent.reply('watcher started') else: ievent.reply('already watching %s' % name) cmnds.add('hb-watch', handle_hubbubwatch, 'USER') examples.add('hb-watch', 'hubbub-watch [seconds to sleep] .. go watching ', 'hb-watch gozerbot') .. _fbf.plugs.extra.hubbub_hb-start_command: hb-start command ------------------- :: def handle_hubbubstart(bot, ievent): """ arguments: - start sending feeds to an user or channel. """ feeds = ievent.args if not feeds: ievent.missing('') ; return started = [] cantstart = [] if feeds[0] == 'all': feeds = watcher.list() for name in feeds: if watcher.start(bot.cfg.name, bot.type, name, ievent.channel): started.append(name) if name not in ievent.chan.data.feeds: ievent.chan.data.feeds.append(name) ievent.chan.save() else: cantstart.append(name) if started: ievent.reply('started: ', started) else: ievent.reply("sorry can't start: ", cantstart) cmnds.add('hb-start', handle_hubbubstart, ['USER', 'GUEST']) examples.add('hb-start', 'hubbub-start .. start a hubbub feed (per user/channel) ', 'hb-start gozerbot') .. _fbf.plugs.extra.hubbub_hb-stop_command: hb-stop command ------------------ :: def handle_hubbubstop(bot, ievent): """ arguments: - stop a hubbub feed to a user or channel. """ if not ievent.args: ievent.missing('') ; return feeds = ievent.args stopped = [] cantstop = [] if feeds[0] == 'all': feeds = watcher.listfeeds(bot.cfg.name, bot.type, ievent.channel) for name in feeds: if watcher.stop(bot.cfg.name, bot.type, name, ievent.channel): stopped.append(name) if name in ievent.chan.data.feeds: ievent.chan.data.feeds.remove(name) ievent.chan.save() else: cantstop.append(name) if stopped: ievent.reply('feeds stopped: ', feeds) elif cantstop: ievent.reply('failed to stop %s feed' % cantstop) ievent.done() cmnds.add('hb-stop', handle_hubbubstop, ['USER', 'GUEST']) examples.add('hb-stop', 'hubbub-stop .. stop a hubbub feed (per user/channel) ', 'hb-stop gozerbot') .. _fbf.plugs.extra.hubbub_hb-stopall_command: hb-stopall command --------------------- :: def handle_hubbubstopall(bot, ievent): """ no arguments - stop all hubbub feeds to a channel. """ if not ievent.rest: target = ievent.channel else: target = ievent.rest stopped = [] feeds = watcher.getfeeds(target, bot.cfg.name) if feeds: for feed in feeds: if watcher.stop(bot.cfg.name, bot.type, feed, target): if feed in ievent.chan.data.feeds: ievent.chan.data.feeds.remove(feed) ievent.chan.save() stopped.append(feed) ievent.reply('stopped feeds: ', stopped) else: ievent.reply('no feeds running in %s' % target) cmnds.add('hb-stopall', handle_hubbubstopall, ['HUBBUB', 'OPER']) examples.add('hb-stopall', 'hubbub-stopall .. stop all hubbub feeds (per user/channel) ', 'hb-stopall') .. _fbf.plugs.extra.hubbub_hb-channels_command: hb-channels command ---------------------- :: def handle_hubbubchannels(bot, ievent): """ arguments: - show channels of hubbub feed. """ try: name = ievent.args[0] except IndexError: ievent.missing("") ; return item = watcher.byname(name) if item == None: ievent.reply("we don't have a %s hubbub object" % name) ; return if not item.data.watchchannels: ievent.reply('%s is not in watch mode' % name) ; return result = [] for i in item.data.watchchannels: result.append(str(i)) ievent.reply("channels of %s: " % name, result) cmnds.add('hb-channels', handle_hubbubchannels, ['OPER', ]) examples.add('hb-channels', 'hb-channels .. show channels', 'hb-channels gozerbot') .. _fbf.plugs.extra.hubbub_hb-addchannel_command: hb-addchannel command ------------------------ :: def handle_hubbubaddchannel(bot, ievent): """ arguments: [] [] - add a channel to hubbub feed. """ try: (name, botname, type, channel) = ievent.args except ValueError: try: botname = bot.cfg.name (name, type, channel) = ievent.args except ValueError: try: botname = bot.cfg.name type = bot.type (name, channel) = ievent.args type = bot.type except ValueError: try: botname = bot.cfg.name name = ievent.args[0] type = bot.type channel = ievent.channel except IndexError: ievent.missing(' [][] ') ; return item = watcher.byname(name) if item == None: ievent.reply("we don't have a %s hubbub object" % name) ; return if not item.data.running: ievent.reply('%s watcher is not running' % name) ; return if jsonstring([botname, type, channel]) in item.data.watchchannels or [botname, type, channel] in item.data.watchchannels: ievent.reply('we are already monitoring %s on (%s,%s)' % (name, type, channel)) return item.data.watchchannels.append([botname, type, channel]) item.save() ievent.reply('%s added to %s hubbub item' % (channel, name)) cmnds.add('hb-addchannel', handle_hubbubaddchannel, ['OPER', ]) examples.add('hb-addchannel', 'add a channel to a feeds watchlist', '1) hb-addchannel gozerbot #dunkbots 2) hb-addchannel gozerbot main #dunkbots') .. _fbf.plugs.extra.hubbub_hb-setitems_command: hb-setitems command ---------------------- :: def handle_hubbubsetitems(bot, ievent): """ arguments: - set items (tokens) of a feed, see hb-scan for a list of possible tokens. """ try: (name, items) = ievent.args[0], ievent.args[1:] except (ValueError, IndexError): ievent.missing(' ') ; return target = ievent.channel feed = watcher.byname(name) if not feed: ievent.reply("we don't have a %s feed" % name) ; return feed.itemslists.data[jsonstring([name, target])] = items feed.itemslists.save() ievent.reply('%s added to (%s,%s) itemslist' % (items, name, target)) cmnds.add('hb-setitems', handle_hubbubsetitems, ['GUEST', 'USER']) examples.add('hb-setitems', 'set tokens of the itemslist (per user/channel)', 'hb-setitems gozerbot author author link pubDate') .. _fbf.plugs.extra.hubbub_hb-additem_command: hb-additem command --------------------- :: def handle_hubbubadditem(bot, ievent): """ arguments: - add an item (token) to a feeds itemslist, this list is used to determine what to display. """ try: (name, item) = ievent.args except ValueError: ievent.missing(' ') ; return target = ievent.channel feed = watcher.byname(name) if not feed: ievent.reply("we don't have a %s feed" % name) ; return try: feed.itemslists.data[jsonstring([name, target])].append(item) except KeyError: feed.itemslists.data[jsonstring([name, target])] = ['title', 'link'] feed.itemslists.save() ievent.reply('%s added to (%s,%s) itemslist' % (item, name, target)) cmnds.add('hb-additem', handle_hubbubadditem, ['GUEST', 'USER']) examples.add('hb-additem', 'add a token to the itemslist (per user/channel)', 'hb-additem gozerbot link') .. _fbf.plugs.extra.hubbub_hb-delitem_command: hb-delitem command --------------------- :: def handle_hubbubdelitem(bot, ievent): """ arguments: - delete item (token) from a feeds itemlist. """ try: (name, item) = ievent.args except ValueError: ievent.missing(' ') ; return target = ievent.channel feed = watcher.byname(name) if not feed: ievent.reply("we don't have a %s feed" % name) ; return try: feed.itemslists.data[jsonstring([name, target])].remove(item) feed.itemslists.save() except (NoSuchFeed, ValueError): ievent.reply("we don't have a %s feed" % name) ; return ievent.reply('%s removed from (%s,%s) itemslist' % (item, name, target)) cmnds.add('hb-delitem', handle_hubbubdelitem, ['GUEST', 'USER']) examples.add('hb-delitem', 'remove a token from the itemslist (per user/channel)', 'hb-delitem gozerbot link') .. _fbf.plugs.extra.hubbub_hb-markuplist_command: hb-markuplist command ------------------------ :: def handle_hubbubmarkuplist(bot, ievent): """ no arguments - show possible markups that can be used. """ ievent.reply('possible markups ==> ' , possiblemarkup) cmnds.add('hb-markuplist', handle_hubbubmarkuplist, ['USER', 'GUEST']) examples.add('hb-markuplist', 'show possible markup entries', 'hb-markuplist') .. _fbf.plugs.extra.hubbub_hb-markup_command: hb-markup command -------------------- :: def handle_hubbubmarkup(bot, ievent): """ arguments: - show the markup of a feed (channel specific). """ try: name = ievent.args[0] except IndexError: ievent.missing('') ; return target = ievent.channel feed = watcher.byname(name) if not feed: ievent.reply("we don't have a %s feed" % name) ; return try: ievent.reply(str(feed.markup[jsonstring([name, target])])) except KeyError: pass cmnds.add('hb-markup', handle_hubbubmarkup, ['GUEST', 'USER']) examples.add('hb-markup', 'show markup list for a feed (per user/channel)', 'hb-markup gozerbot') .. _fbf.plugs.extra.hubbub_hb-addmarkup_command: hb-addmarkup command ----------------------- :: def handle_hubbubaddmarkup(bot, ievent): """ arguments: - add a markup to a feeds markuplist, this list determines how we display things. """ try: (name, item, value) = ievent.args except ValueError: ievent.missing(' ') ; return target = ievent.channel try: value = int(value) except ValueError: pass feed = watcher.byname(name) if not feed: ievent.reply("we don't have a %s feed" % name) ; return try: feed.markup.set(jsonstring([name, target]), item, value) feed.markup.save() ievent.reply('%s added to (%s,%s) markuplist' % (item, name, target)) except KeyError: ievent.reply("no (%s,%s) feed available" % (name, target)) cmnds.add('hb-addmarkup', handle_hubbubaddmarkup, ['GUEST', 'USER']) examples.add('hb-addmarkup', 'add a markup option to the markuplist (per user/channel)', 'hb-addmarkup gozerbot all-lines 1') .. _fbf.plugs.extra.hubbub_hb-delmarkup_command: hb-delmarkup command ----------------------- :: def handle_hubbubdelmarkup(bot, ievent): """ arguments: - delete markup item from a feed's markuplist. """ try: (name, item) = ievent.args except ValueError: ievent.missing(' ') ; return target = ievent.channel feed = watcher.byname(name) if not feed: ievent.reply("we don't have a %s feed" % name) ; return try: del feed.markup[jsonstring([name, target])][item] except (KeyError, TypeError): ievent.reply("can't remove %s from %s feed's markup" % (item, name)) ; return feed.markup.save() ievent.reply('%s removed from (%s,%s) markuplist' % (item, name, target)) cmnds.add('hb-delmarkup', handle_hubbubdelmarkup, ['GUEST', 'USER']) examples.add('hb-delmarkup', 'remove a markup option from the markuplist (per user/channel)', 'hb-delmarkup gozerbot all-lines') .. _fbf.plugs.extra.hubbub_hb-delchannel_command: hb-delchannel command ------------------------ :: def handle_hubbubdelchannel(bot, ievent): """ arguments: [] [] [] - delete channel from hubbub feed. """ bottype = None try: (name, botname, bottype, channel) = ievent.args except ValueError: try: botname = bot.cfg.name (name, type, channel) = ievent.args except ValueError: try: botname = bot.cfg.name name = ievent.args[0] type = bot.type channel = ievent.channel except IndexError: ievent.missing(' [] [] []') return item = watcher.byname(name) if item == None: ievent.reply("we don't have a %s object" % name) ; return if jsonstring([botname, type, channel]) in item.data.watchchannels: item.data.watchchannels.remove(jsonstring([botname, type, channel])) ievent.reply('%s removed from %s hubbub item' % (channel, name)) elif [type, channel] in item.data.watchchannels: item.data.watchchannels.remove([botname, type, channel]) ievent.reply('%s removed from %s hubbub item' % (channel, name)) else: ievent.reply('we are not monitoring %s on (%s,%s)' % (name, type, channel)) return item.save() cmnds.add('hb-delchannel', handle_hubbubdelchannel, ['OPER', ]) examples.add('hubbub-delchannel', 'remove a channel from a feeds watchlist', '1) hb-delchannel gozerbot #dunkbots 2) hb-delchannel gozerbot main #dunkbots') .. _fbf.plugs.extra.hubbub_hb-stopwatch_command: hb-stopwatch command ----------------------- :: def handle_hubbubstopwatch(bot, ievent): """ arguments: - stop watching a feed. """ try: name = ievent.args[0] except IndexError: ievent.missing('') ; return item = watcher.byname(name) if not item: ievent.reply("there is no %s item" % name) ; return if not watcher.stopwatch(name): ievent.reply("can't stop %s watcher" % name) ; return ievent.reply('stopped %s hubbub watch' % name) cmnds.add('hb-stopwatch', handle_hubbubstopwatch, ['OPER', ]) examples.add('hb-stopwatch', 'hubbub-stopwatch .. stop polling ', 'hb-stopwatch gozerbot') .. _fbf.plugs.extra.hubbub_hb-get_command: hb-get command ----------------- :: def handle_hubbubget(bot, ievent): """ arguments: - fetch feed data. """ try: name = ievent.args[0] except IndexError: ievent.missing('') ; return channel = ievent.channel item = watcher.byname(name) if item == None: ievent.reply("we don't have a %s item" % name) ; return try: result = watcher.fetchdata(name) except Exception as ex: ievent.reply('%s error: %s' % (name, str(ex))) ; return if item.markup.get(jsonstring([name, channel]), 'reverse-order'): result = result[::-1] response = watcher.makeresponse(name, result, ievent.channel) if response: ievent.reply("results of %s: %s" % (name, response)) else: ievent.reply("can't make a reponse out of %s" % name) cmnds.add('hb-get', handle_hubbubget, ['HUBBUB', 'USER'], threaded=True) examples.add('hb-get', 'hubbub-get .. get data from ', 'hb-get gozerbot') .. _fbf.plugs.extra.hubbub_hb-running_command: hb-running command --------------------- :: def handle_hubbubrunning(bot, ievent): """ no arguments - show which feeds are running. """ result = watcher.runners() resultlist = [] teller = 1 for i in result: resultlist.append("%s %s" % (i[0], i[1])) if resultlist: ievent.reply("running hubbub watchers: ", resultlist, nr=1) else: ievent.reply('nothing running yet') cmnds.add('hb-running', handle_hubbubrunning, ['HUBBUB', 'USER']) examples.add('hb-running', 'hubbub-running .. get running feeds', 'hb-running') .. _fbf.plugs.extra.hubbub_hb-list_command: hb-list command ------------------ :: def handle_hubbublist(bot, ievent): """ no arguments - return list of available feeds. """ result = watcher.list() result.sort() if result: ievent.reply("hubbub items: ", result) else: ievent.reply('no hubbub items yet') cmnds.add('hb-list', handle_hubbublist, ['GUEST', 'USER']) examples.add('hb-list', 'get list of hubbub items', 'hb-list') .. _fbf.plugs.extra.hubbub_hb-url_command: hb-url command ----------------- :: def handle_hubbuburl(bot, ievent): """ arguments: - return url of feed. """ try: name = ievent.args[0] except IndexError: ievent.missing('') ; return if not watcher.ownercheck(name, ievent.userhost): ievent.reply("you are not the owner of the %s feed" % name) return result = watcher.url(name) if not result: ievent.reply("can't fetch url for %s" % name) ; return try: if ':' in result.split('/')[1]: if not ievent.msg: ievent.reply('run this command in a private message') ; return except (TypeError, ValueError, IndexError): pass ievent.reply('url of %s: %s' % (name, result)) cmnds.add('hb-url', handle_hubbuburl, ['OPER', ]) examples.add('hb-url', 'hb-url .. get url from hubbub item', 'hb-url gozerbot') .. _fbf.plugs.extra.hubbub_hb-itemslist_command: hb-itemslist command ----------------------- :: def handle_hubbubitemslist(bot, ievent): """ arguments: - show itemslist (tokens) of hubbub item. """ try:name = ievent.args[0] except IndexError: ievent.missing('') ; return feed = watcher.byname(name) if not feed: ievent.reply("we don't have a %s feed" % name) ; return try: itemslist = feed.itemslists.data[jsonstring([name, ievent.channel])] except KeyError: ievent.reply("no itemslist set for (%s, %s)" % (name, ievent.channel)) ; return ievent.reply("itemslist of (%s, %s): " % (name, ievent.channel), itemslist) cmnds.add('hb-itemslist', handle_hubbubitemslist, ['GUEST', 'USER']) examples.add('hb-itemslist', 'hb-itemslist .. get itemslist of ', 'hb-itemslist gozerbot') .. _fbf.plugs.extra.hubbub_hb-scan_command: hb-scan command ------------------ :: def handle_hubbubscan(bot, ievent): """ arguments: - scan feed for available tokens. """ try: name = ievent.args[0] except IndexError: ievent.missing('') ; return if not watcher.byname(name): ievent.reply('no %s feeds available' % name) ; return try: result = watcher.scan(name) except Exception as ex: ievent.reply(str(ex)) ; return if result == None: ievent.reply("can't get data for %s" % name) ; return res = [] for i in result: res.append("%s=%s" % i) ievent.reply("tokens of %s: " % name, res) cmnds.add('hb-scan', handle_hubbubscan, ['USER', 'GUEST']) examples.add('hb-scan', 'hb-scan .. get possible items of ', 'hb-scan gozerbot') .. _fbf.plugs.extra.hubbub_hb-feeds_command: hb-feeds command ------------------- :: def handle_hubbubfeeds(bot, ievent): """ arguments: [] - show what feeds are running in a channel. """ try: channel = ievent.args[0] except IndexError: channel = ievent.channel try: result = watcher.getfeeds(channel, bot.cfg.name) if result: ievent.reply("feeds running: ", result) else: ievent.reply('no feeds running') except Exception as ex: ievent.reply("ERROR: %s" % str(ex)) cmnds.add('hb-feeds', handle_hubbubfeeds, ['USER', 'GUEST']) examples.add('hb-feeds', 'hb-feeds .. show what feeds are running in a channel', '1) hb-feeds 2) hb-feeds #dunkbots') .. _fbf.plugs.extra.hubbub_hb-register_command: hb-register command ---------------------- :: def handle_hubbubregister(bot, ievent): """ arguments: - register a url and start the feed in one pass. """ target = ievent.channel if len(ievent.args) > 2: ievent.reply("feed name needs to be 1 word.") ; return try: (name, url) = ievent.args except ValueError: try: name = ievent.args[0] except IndexError: ievent.reply("i need a feed name and a feed url to work with") ; return item = watcher.byname(name) if item: if not name in watcher.getfeeds(ievent.channel, bot.cfg.name): watcher.start(bot.cfg.name, bot.type, name, target) if name not in ievent.chan.data.feeds: ievent.chan.data.feeds.append(name) ievent.chan.save() ievent.reply('started %s feed. entries will show up when the feed is updated.' % name) else: ievent.reply("feed %s is already running." % name) else: ievent.reply("i don't know a %s feed. please enter name and url." % name) return if not url.startswith("http"): ievent.reply("the feedurl needs to start with http(s)://") ; return try: result = subscribe(url, socket.gethostname()) except RequireError as ex: ievent.reply(str(ex)) ; return if int(result.status) > 200 and int(result.status) < 300: if watcher.add(name, url, ievent.userhost): watcher.start(bot.cfg.name, bot.type, name, target) ievent.reply('started %s feed. entries will show up when the feed is updated.' % name) return else: ievent.reply("there already exists a %s feed. please choose a different name" % name) return else: ievent.reply('feed %s NOT added. Status code is %s. please check if the feed is valid.' % (name, result.status)) cmnds.add('hb-register', handle_hubbubregister, ['USER', 'GUEST']) examples.add('hb-register', 'hb-register .. register url and start it in one pass', 'hb-register fbfrepo https://github.com/feedbackflow/fbfbot/commits/master.atom')