gplugs.rss

the rss mantra is of the following:

as OPER:

. add a url with rss-add . start the watcher with rss-watch

now the user can start the bot sending messages of the feed to him with rss-start. if an OPER gives a rss-start command in a channel data will be send to the channel.

exception gplugs.rss.Rss301

Bases: gplugs.rss.RssException

exception gplugs.rss.RssBozoException

Bases: gplugs.rss.RssException

exception gplugs.rss.RssException

Bases: exceptions.Exception

exception gplugs.rss.RssNoSuchItem

Bases: gplugs.rss.RssException

exception gplugs.rss.RssStatus

Bases: gplugs.rss.RssException

class gplugs.rss.Rssdict(filename)

Bases: gozerbot.persist.persist.PlugPersist

dict of rss entries

add(*args, **kwargs)

the locked function.

byname(name)

return rss item by name

delete(*args, **kwargs)

the locked function.

getdata(name)

get data of rss feed

size()

return number of rss entries

class gplugs.rss.Rssitem(name='', url='', itemslist=[], watchchannels=[], sleeptime=1800, running=0, d={})

Bases: gozerbot.utils.lazydict.LazyDict

item that contains rss data

class gplugs.rss.Rsswatcher(filename)

Bases: gplugs.rss.Rssdict

rss watchers

all(name, item)
changeinterval(name, interval)
dowatch(name, sleeptime=1800)
feeds(*args, **kwargs)

the locked function.

list(*args, **kwargs)

the locked function.

makeresponse(name, res, channel, sep='x02||x02')
makeresult(name, target, data)
peek(name, *args)
runners(*args, **kwargs)

the locked function.

scan(name)

scan a rss url for used xml items

search(name, item, search)
searchall(item, search)
seturl(*args, **kwargs)

the locked function.

startwatchers(*args, **kwargs)

the locked function.

stopwatch(*args, **kwargs)

the locked function.

stopwatchers(*args, **kwargs)

the locked function.

sync(name)
url(*args, **kwargs)

the locked function.

watch(name)

start a watcher thread

gplugs.rss.checkfordate(data, date)
gplugs.rss.handle_rssadd(bot, ievent)

rss-add <name> <url> .. add a rss item

gplugs.rss.handle_rssaddchannel(bot, ievent)

rss-addchannel <name> [<botname>] <channel> .. add a channel to rss item

gplugs.rss.handle_rssadditem(bot, ievent)
gplugs.rss.handle_rssaddmarkup(bot, ievent)
gplugs.rss.handle_rssall(bot, ievent)
gplugs.rss.handle_rsschannels(bot, ievent)

rss-channels <name> .. show channels of rss feed

gplugs.rss.handle_rssdel(bot, ievent)

rss-del <name> .. delete a rss item

gplugs.rss.handle_rssdelchannel(bot, ievent)

rss-delchannel <name> [<botname>] <channel> .. delete channel from rss item

gplugs.rss.handle_rssdelitem(bot, ievent)
gplugs.rss.handle_rssdelmarkup(bot, ievent)
gplugs.rss.handle_rssdescription(bot, ievent)
gplugs.rss.handle_rssdump(bot, ievent)
gplugs.rss.handle_rssfeeds(bot, ievent)

rss-feeds <channel> .. show what feeds are running in a channel

gplugs.rss.handle_rssget(bot, ievent)

rss-get <name> .. fetch rss data

gplugs.rss.handle_rssitemslist(bot, ievent)

rss-itemslist <name> .. show itemslist of rss item

gplugs.rss.handle_rsslist(bot, ievent)

rss-list .. return list of rss items

gplugs.rss.handle_rssmarkup(bot, ievent)
gplugs.rss.handle_rssmarkuplist(bot, ievent)
gplugs.rss.handle_rsspeek(bot, ievent)
gplugs.rss.handle_rssrunning(bot, ievent)

rss-running .. show which watchers are running

gplugs.rss.handle_rssscan(bot, ievent)

rss-scan <name> .. scan rss item for used xml items

gplugs.rss.handle_rsssearch(bot, ievent)
gplugs.rss.handle_rsssetitems(bot, ievent)
gplugs.rss.handle_rsssetsleeptime(bot, ievent)

rss-setsleeptime <name> <seconds> .. set sleeptime of rss item

gplugs.rss.handle_rssseturl(bot, ievent)

rss-seturl <name> <url> .. set url of rss item

gplugs.rss.handle_rsssleeptime(bot, ievent)

rss-sleeptime <name> .. get sleeptime of rss item

gplugs.rss.handle_rssstart(bot, ievent)

rss-start <name> .. start a rss feed to a user

gplugs.rss.handle_rssstop(bot, ievent)

rss-start <name> .. start a rss feed to a user

gplugs.rss.handle_rssstopwatch(bot, ievent)

rss-stopwatch <name> .. stop a watcher thread

gplugs.rss.handle_rsssync(bot, ievent)

rss-sync <name> .. sync rss item data

gplugs.rss.handle_rssurl(bot, ievent)

rss-url <name> .. return url of rss item

gplugs.rss.handle_rsswatch(bot, ievent)

rss-watch <name> .. start watcher thread

gplugs.rss.init()

called after plugin import

gplugs.rss.shutdown()

called before plugin import

gplugs.rss.size()

return number of watched rss entries

gplugs.rss.txtindicts(result, d)

return lowlevel values in (nested) dicts

CODE

# plugs/rss.py
#
#

"""
    the rss mantra is of the following:

    as OPER:

        . add a url with rss-add
        . start the watcher with rss-watch

    now the user can start the bot sending messages of the feed to him with
    rss-start. if an OPER gives a rss-start command in a channel data will be
    send to the channel.

"""

__gendocfirst__ = ['rss-add', 'rss-watch', 'rss-start']
__gendocskip__ = ['rss-dump', ]
__status__ = "seen"

gozerbot imports

from gozerbot.persist.persist import PlugPersist
from gozerbot.generic import geturl2, handle_exception, rlog, lockdec, strippedtxt, fromenc, striphtml, useragent, jsonstring
from gozerbot.utils.rsslist import rsslist
from gozerbot.utils.statdict import Statdict
from gozerbot.utils.lazydict import LazyDict
from gozerbot.fleet import fleet
from gozerbot.commands import cmnds
from gozerbot.examples import examples
from gozerbot.datadir import datadir
from gozerbot.utils.dol import Dol
from gozerbot.persist.pdod import Pdod
from gozerbot.persist.pdol import Pdol
from gozerbot.plughelp import plughelp
from gozerbot.periodical import periodical
from gozerbot.aliases import aliasset
from gozerbot.users import users
from gozerbot.tests import tests
import gozerbot.threads.thr as thr
try:
    from gplugs.tinyurl import get_tinyurl
except:
    def get_tinyurl(url):
        return url

simplejson import

from simplejson import loads

basic imports

import feedparser
import time
import os
import types
import thread
import socket
import xml

plughelp

plughelp.add('rss', 'manage rss feeds')

locks

rsslock = thread.allocate_lock()
locked = lockdec(rsslock)

defines

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 rss items displayed with oldest item first', \
'striphtml': 'strip html from output'}

txtindicts function

def txtindicts(result, d):
    """ return lowlevel values in (nested) dicts """
    for j in d.values():
        if type(j) == types.DictType:
            txtindicts(result, j)
        else:
            result.append(j)

checkfordate function

def checkfordate(data, date):
    for item in data:
        try:
            d = item['updated']
        except KeyError:
            continue
        if date == d:
            return True
    return False

exceptions

class RssException(Exception):
    pass

class Rss301(RssException):
    pass

class RssStatus(RssException):
    pass

class RssBozoException(RssException):
    pass

class RssNoSuchItem(RssException):
    pass

Rssitem class

class Rssitem(LazyDict):

    """ item that contains rss data """

    def __init__(self, name="", url="", itemslist=[], watchchannels=[], sleeptime=30*60, running=0, d={}):
        if not d:
            LazyDict.__init__(self)
            self['name'] = name
            self['url'] = url
            self['itemslist'] = list(itemslist)
            self['watchchannels'] = list(watchchannels)
            self['sleeptime'] = int(sleeptime)
            self['running'] = int(running)
            self['stoprunning'] = 0
            self['botname'] = None
        else:
            LazyDict.__init__(self, d)

Rssdict class

class Rssdict(PlugPersist):

    """ dict of rss entries """

    def __init__(self, filename):
        PlugPersist.__init__(self, filename)
        if not self.data:
            self.data = {}
        else:
            tmp = {}
            for name, item in self.data.iteritems():
                tmp[name] = Rssitem(d=item)
            self.data = tmp
        if self.data.has_key('itemslists'):
            del self.data['itemslists']
        self.itemslists = Pdol(datadir + os.sep + 'plugs' + os.sep + 'rss' + os.sep + filename + '.itemslists')
        self.handlers = {}
        self.results = {}
        self.jobids = {}
        self.rawresults = {}
        self.results = Dol()
        self.modified = {}
        self.etag = {}
        self.markup = Pdod(datadir + os.sep + 'plugs' + os.sep + 'rss' + os.sep + filename + '.markup')

    def size(self):
        """ return number of rss entries """
        return len(self.data)

    @locked
    def add(self, name, url):
        """ add rss item """
        rlog(10, 'rss', 'adding %s %s' % (name, url))
        self.data[name] = Rssitem(name, url, ['title', ])
        self.save()

    @locked
    def delete(self, name):
        """ delete rss item by name """
        target = None
        for j, i in self.data.iteritems():
           if i.name == name:
               target = i
        if target:
            try:
                target.running = 0
                del self.data[name]
                self.save()
            except:
                pass

    def byname(self, name):
        """ return rss item by name """
        try:
            return self.data[name]
        except:
            return

    def getdata(self, name):
        """ get data of rss feed """
        rssitem = self.byname(name)
        if rssitem == None:
            raise RssNoSuchItem("no %s rss item found" % name)
        try:
            modified = self.modified[name]
        except KeyError:
            modified = None
        try:
            etag = self.etag[name]
        except KeyError:
            etag = None
        rlog(9, 'rss', 'fetching %s' % rssitem.url)
        result = feedparser.parse(rssitem.url, modified=modified, etag=etag, agent=useragent())
        if result and result.has_key('bozo_exception'):
            rlog(1, 'rss', '%s bozo_exception: %s' % (name, result['bozo_exception']))
        try:
            status = result.status
        except AttributeError:
            status = 200
        if status != 200 and status != 301 and status != 302 and status != 304:
            raise RssStatus(status)
        try:
            self.modified[name] = result.modified
        except AttributeError:
            pass
        try:
            self.etag[name] = result.etag
        except AttributeError:
            pass
        if status == 304:
            rlog(0, 'rss', 'recieved 304 from %s rss feed' % name)
            return self.rawresults[name]
        else:
            self.rawresults[name] = result.entries
        return result.entries

Rsswatcher class

class Rsswatcher(Rssdict):

    """ rss watchers """

    def __init__(self, filename):
        Rssdict.__init__(self, filename)

    def sync(self, name):
        result = self.getdata(name)
        if result:
            self.results[name] = result

    def changeinterval(self, name, interval):
        periodical.changeinterval(self.jobids[name], interval)

    @locked
    def startwatchers(self):
        """ start watcher threads """
        for j, z in self.data.iteritems():
            if z.running:
                thr.start_new_thread(self.watch, (z.name, ))

    @locked
    def stopwatchers(self):
        """ stop all watcher threads """
        for j, z in self.data.iteritems():
            if z.running:
                z.stoprunning = 1
        periodical.killgroup('rss')

    def dowatch(self, name, sleeptime=1800):
        rssitem = self.byname(name)
        if not rssitem:
            rlog(10, 'rss', "no %s rss item available" % name)
            return
        while 1:
            try:
                self.watch(name)
            except Exception, ex:
                rlog(100, 'rss', '%s feed error: %s' % (name, str(ex)))
                rlog(100, 'rss', '%s sleeping %s seconds for retry' % (name, sleeptime))
                time.sleep(sleeptime)
                if not rssitem.running:
                    break
            else:
                break

    def makeresult(self, name, target, data):
        res = []
        for j in data:
            tmp = {}
            if not self.itemslists[jsonstring([name, target])]:
                return []
            for i in self.itemslists[jsonstring([name, target])]:
                try:
                    tmp[i] = unicode(j[i])
                except KeyError:
                    continue
            res.append(tmp)
        return res

    def watch(self, name):
        """ start a watcher thread """
        # get basic data
        rlog(10, 'rss', 'trying %s rss feed watcher' % name)
        try:
            result = self.getdata(name)
        except RssException, ex:
            rlog(10, 'rss', "%s error: %s" % (name, str(ex)))
            result = []
        rssitem = self.byname(name)
        if not rssitem:
            raise RssNoItem()
        # poll every sleeptime seconds
        self.results[name] = result
        pid = periodical.addjob(rssitem.sleeptime, 0, self.peek, name, name)
        self.jobids[name] = pid
        rssitem.running = 1
        rssitem.stoprunning = 0
        self.data[name] = rssitem
        self.save()
        rlog(10, 'rss', 'started %s rss watch' % name)

    def makeresponse(self, name, res, channel, sep="\002||\002"):
        # loop over result to make a response
        result = u""
        itemslist = self.itemslists[jsonstring([name, channel])]
        if not itemslist:
            rssitem = self.byname(name)
            if not rssitem:
                return "no %s rss item" % name
            else:
                self.itemslists.extend(jsonstring([name, channel]), rssitem.itemslist)
                self.itemslists.save()
        for j in res:
            if self.markup.get(jsonstring([name, channel]), 'skipmerge') and 'Merge branch' in j['title']:
                continue
            resultstr = u""
            for i in self.itemslists[jsonstring([name, channel])]:
                try:
                    item = unicode(j[i])
                    if not item: continue
                    if item.startswith('http://'):
                        if self.markup.get(jsonstring([name, channel]), 'tinyurl'):
                            try:
                                tinyurl = get_tinyurl(item)
                                if not tinyurl: resultstr += u"<%s> - " % item
                                else: resultstr += u"<%s> - " % tinyurl[0]
                            except Exception, ex:
                                handle_exception()
                                resultstr += u"<%s> - " % item
                        else:
                            resultstr += u"<%s> - " % item
                    elif self.markup.get(jsonstring([name, channel]) , 'striphtml'):
                        resultstr += u"%s - " % striphtml(item.strip())
                    else:
                        resultstr += u"%s - " % item.strip()
                except KeyError: continue
            resultstr = resultstr[:-3]
            if resultstr: result += u"%s %s " % (resultstr, sep)
        return result[:-(len(sep)+2)]

    def peek(self, name, *args):
        rssitem = self.byname(name)
        if not rssitem or not rssitem.running or rssitem.stoprunning:
            return
        try:
            try:
                res = self.getdata(name)
            except socket.timeout:
                rlog(10, 'rss', 'socket timeout of %s' % name)
                return
            except RssException, ex:
                rlog(10, 'rss', '%s error: %s' % (name, str(ex)))
                return
            if not res:
                return
            res2 = []
            for j in res:
                try:
                    d = j['updated']
                except KeyError:
                    if j not in self.results[name]:
                        self.results[name].append(j)
                        res2.append(j)
                else:
                    if not checkfordate(self.results[name], d):
                        self.results[name].append(j)
                        res2.append(j)
            if not res2:
                return
            for item in rssitem.watchchannels:
                try:
                    (botname, channel) = item
                except:
                    try:
                        (botname, channel) = loads(item)
                    except:
                        rlog(10, 'rss', '%s is not in the format (botname,channel)' % str(item))
                bot = fleet.byname(botname)
                if not bot:
                    continue
                if self.markup.get(jsonstring([name, channel]), 'reverse-order'):
                    res2 = res2[::-1]
                if self.markup.get(jsonstring([name, channel]), 'all-lines'):
                    for i in res2:
                        response = self.makeresponse(name, [i, ], channel)
                        bot.say(channel, "\002%s\002: %s" % (rssitem.name, response), fromm=rssitem.name)
                else:
                    sep =  self.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, "\002%s\002: %s" % (rssitem.name, response), fromm=rssitem.name)
        except Exception, ex:
            handle_exception(txt=name)

    @locked
    def stopwatch(self, name):
        """ stop watcher thread """
        for i, z in self.data.iteritems():
            if i == name:
                z.running = 0
                try:
                    del self.results[name]
                except KeyError:
                    pass
                self.data[i] = z
                self.save()
                try:
                    periodical.killjob(self.jobids[i])
                except KeyError:
                    pass
                return 1

    @locked
    def list(self):
        """ return of rss names """
        feeds = self.data.keys()
        return feeds

    @locked
    def runners(self):
        """ show names/channels of running watchers """
        result = []
        for j, z in self.data.iteritems():
            if z.running == 1 and not z.stoprunning:
                result.append((z.name, z.watchchannels))
        return result

    @locked
    def feeds(self, botname, channel):
        """ show names/channels of running watcher """
        result = []
        for j, z in self.data.iteritems():
            if jsonstring([botname, channel]) in z.watchchannels or [botname, channel] in z.watchchannels:
                result.append(z.name)
        return result

    @locked
    def url(self, name):
        """ return url of rssitem """
        for j, z in self.data.iteritems():
            if z.name == name:
                return z.url

    @locked
    def seturl(self, name, url):
        """ set url of rssitem """
        for j, z in self.data.iteritems():
            if z.name == name:
                z.url = url
                self.save()
                return True

    def scan(self, name):
        """ scan a rss url for used xml items """
        try:
            result = self.getdata(name)
        except RssException, ex:
            rlog(10, 'rss', '%s error: %s' % (name, str(ex)))
            return
        if not result:
            return
        keys = []
        for item in self.rawresults[name]:
             for key in item.keys():
                 keys.append(key)
        statdict = Statdict()
        for key in keys:
            statdict.upitem(key)
        return statdict.top()

    def search(self, name, item, search):
        res = []
        for result in self.rawresults[name]:
            try:
                title = result['title']
                txt = result[item]
            except KeyError:
                continue
            if search in title.lower():
                if txt:
                   res.append(txt)
        return res

    def searchall(self, item, search):
        res = []
        for name, results in self.rawresults.iteritems():
            for result in results:
                try:
                    title = result['title']
                    txt = result[item]
                except KeyError:
                    continue
                if search in title.lower():
                    if txt:
                        res.append("%s: %s" % (name, txt))
        return res

    def all(self, name, item):
        res = []
        for result in self.rawresults[name]:
            try:
                txt = result[item]
            except KeyError:
                continue
            if txt:
                res.append(txt)
        return res

defines2

watcher = Rsswatcher('rss')

3## init function

def init():
    """ called after plugin import """
    thr.start_new_thread(watcher.startwatchers, ())
    return 1

size function

def size():
    """ return number of watched rss entries """
    return watcher.size()

shutdown function

def shutdown():
    """ called before plugin import """
    watcher.stopwatchers()
    return 1

rss-add command

def handle_rssadd(bot, ievent):
    """ rss-add <name> <url> .. add a rss item """
    try:
        (name, url) = ievent.args
    except ValueError:
        ievent.missing('<name> <url>')
        return
    watcher.add(name, url)
    ievent.reply('rss item added')

cmnds.add('rss-add', handle_rssadd, 'OPER')
examples.add('rss-add', 'rss-add <name> <url> to the rsswatcher', 'rss-add \
gozerbot http://core.gozerbot.org/hg/dev/0.9/rss-log')
tests.add('rss-add dev http://core.gozerbot.org/hg/dev/0.9/rss-log')

rss-del command

def handle_rssdel(bot, ievent):
    """ rss-del <name> .. delete a rss item """
    try:
        name = ievent.args[0]
    except IndexError:
        ievent.missing('<name>')
        return
    if watcher.byname(name):
        watcher.stopwatch(name)
        watcher.delete(name)
        ievent.reply('rss item deleted')
    else:
        ievent.reply('there is no %s rss item' % name)

cmnds.add('rss-del', handle_rssdel, 'OPER')
examples.add('rss-del', 'rss-del <name> .. remove <name> from the \
rsswatcher', 'rss-del mekker')
tests.add('rss-del mekker')

rss-watch command

def handle_rsswatch(bot, ievent):
    """ rss-watch <name> .. start watcher thread """
    if not ievent.channel:
        ievent.reply('no channel provided')
    try:
        name, sleepsec = ievent.args
    except ValueError:
        try:
            name = ievent.args[0]
            sleepsec = 1800
        except IndexError:
            ievent.missing('<name> [secondstosleep]')
            return
    try:
        sleepsec = int(sleepsec)
    except ValueError:
        ievent.reply("time to sleep needs to be in seconds")
        return
    rssitem = watcher.byname(name)
    if rssitem == None:
        ievent.reply("we don't have a %s rss object" % name)
        return
    got = None
    if not rssitem.running or rssitem.stoprunning:
        if not rssitem.sleeptime:
            rssitem.sleeptime = sleepsec
        rssitem.running = 1
        rssitem.stoprunning = 0
        got = True
        watcher.save()
        try:
            watcher.watch(name)
        except Exception, ex:
            ievent.reply(str(ex))
            return
    if got:
        watcher.save()
        ievent.reply('watcher started')
    else:
        ievent.reply('already watching %s' % name)

cmnds.add('rss-watch', handle_rsswatch, 'OPER')
examples.add('rss-watch', 'rss-watch <name> [seconds to sleep] .. go \
watching <name>', '1) rss-watch gozerbot 2) rss-watch gozerbot 600')
tests.add('rss-watch')

rss-start command

def handle_rssstart(bot, ievent):
    """ rss-start <name> .. start a rss feed to a user """
    if ievent.rest == 'all':
        targets = watcher.list()
    elif not ievent.args:
       ievent.missing('<list of feeds>')
       return
    else:
       targets = ievent.args

    started = []

    for name in targets:
        rssitem = watcher.byname(name)
        if bot.jabber:
            if ievent.msg:
                target = ievent.userhost
            else:
                target = ievent.channel
        else:
            if users.allowed(ievent.userhost, ['OPER', ]) and not ievent.msg:
                target = ievent.channel
            else:
                target = ievent.nick
        if rssitem == None:
            ievent.reply("we don't have a %s rss object" % name)
            continue
        watcher.watch(name)
        if not rssitem.running:
            ievent.reply('%s watcher is not running' % name)
            continue
        if jsonstring([bot.name, target]) in rssitem.watchchannels or [bot.name, target] in rssitem.watchchannels:
            ievent.reply('we are already monitoring %s on (%s,%s)' % (name, bot.name, target))
            continue
        rssitem.watchchannels.append([bot.name, target])
        watcher.itemslists.adduniq(jsonstring([name, target]), 'title')
        watcher.itemslists.adduniq(jsonstring([name, target]), 'link')
        watcher.markup.set(jsonstring([name, target]), 'tinyurl', 1)
        started.append(name)
    watcher.itemslists.save()
    watcher.markup.save()
    watcher.save()
    ievent.reply('started: ', started)

cmnds.add('rss-start', handle_rssstart, ['RSS', 'USER'])
examples.add('rss-start', 'rss-start <name> .. start a rss feed \
(per user/channel) ', 'rss-start gozerbot')
tests.add('rss-start dev')

rss-stop command

def handle_rssstop(bot, ievent):
    """ rss-start <name> .. start a rss feed to a user """
    if not ievent.rest:
       ievent.missing('<feed name>')
       return
    name = ievent.rest
    rssitem = watcher.byname(name)
    if bot.jabber:
        target = ievent.userhost
    else:
        if users.allowed(ievent.userhost, ['OPER', ]) and not ievent.msg:
            target = ievent.channel
        else:
            target = ievent.nick
    if rssitem == None:
        ievent.reply("we don't have a %s rss feed" % name)
        return
    if not rssitem.running:
        ievent.reply('%s watcher is not running' % name)
        return
    try:
        rssitem.watchchannels.remove([bot.name, target])
    except ValueError:
        try:
            rssitem.watchchannels.remove([bot.name, target])
        except ValueError:
            ievent.reply('we are not monitoring %s on (%s,%s)' % (name, bot.name, target))
            return
    watcher.save()
    ievent.reply('%s stopped' % name)

cmnds.add('rss-stop', handle_rssstop, ['RSS', 'USER'])
examples.add('rss-stop', 'rss-stop <name> .. stop a rss feed (per user/channel) ', 'rss-stop gozerbot')
tests.add('rss-stop mekker')

rss-channels command

def handle_rsschannels(bot, ievent):
    """ rss-channels <name> .. show channels of rss feed """
    try:
        name = ievent.args[0]
    except IndexError:
        ievent.missing("<name>")
        return
    rssitem = watcher.byname(name)
    if rssitem == None:
        ievent.reply("we don't have a %s rss object" % name)
        return
    if not rssitem.watchchannels:
        ievent.reply('%s is not in watch mode' % name)
        return
    result = []
    for i in rssitem.watchchannels:
        result.append(str(i))
    ievent.reply("channels of %s: " % name, result, dot=True)

cmnds.add('rss-channels', handle_rsschannels, 'OPER')
examples.add('rss-channels', 'rss-channels <name> .. show channels', 'rss-channels gozerbot')
tests.add('rss-channels')

rss-addchannel command

def handle_rssaddchannel(bot, ievent):
    """ rss-addchannel <name> [<botname>] <channel> .. add a channel to \
        rss item """
    try:
        (name, botname, channel) = ievent.args
    except ValueError:
        try:
            (name, channel) = ievent.args
            botname = bot.name
        except ValueError:
            try:
                name = ievent.args[0]
                botname = bot.name
                channel = ievent.channel
            except IndexError:
                ievent.missing('<name> [<botname>] <channel>')
                return
    rssitem = watcher.byname(name)
    if rssitem == None:
        ievent.reply("we don't have a %s rss object" % name)
        return
    if not rssitem.running:
        ievent.reply('%s watcher is not running' % name)
        return
    if jsonstring([botname, channel]) in rssitem.watchchannels or [botname, channel] in rssitem.watchchannels:
        ievent.reply('we are already monitoring %s on (%s,%s)' % (name, botname, channel))
        return
    rssitem.watchchannels.append([botname, channel])
    watcher.save()
    ievent.reply('%s added to %s rss item' % (channel, name))

cmnds.add('rss-addchannel', handle_rssaddchannel, 'OPER')
examples.add('rss-addchannel', 'rss-addchannel <name> [<botname>] <channel>, add <channel> or <botname> <channel> to watchchannels of <name>', \
'1) rss-addchannel gozerbot #dunkbots 2) rss-addchannel gozerbot main #dunkbots')
tests.add('rss-addchannel dev exec')

rss-setitems command

def handle_rsssetitems(bot, ievent):
    try:
        (name, items) = ievent.args[0], ievent.args[1:]
    except ValueError:
        ievent.missing('<name> <items>')
        return
    if bot.jabber or users.allowed(ievent.userhost, ['OPER', ]):
        target = ievent.channel.lower()
    else:
        target = ievent.nick.lower()
    if not watcher.byname(name):
        ievent.reply("we don't have a %s feed" % name)
        return
    watcher.itemslists.data[jsonstring([name, target])] = items
    watcher.itemslists.save()
    ievent.reply('%s added to (%s,%s) itemslist' % (items, name, target))

cmnds.add('rss-setitems', handle_rsssetitems, ['RSS', 'USER'])
examples.add('rss-setitems', 'set tokens of the itemslist (per user/channel)', 'rss-setitems gozerbot author author link pubDate')
tests.add('rss-setitems dev link author')

rss-additem command

def handle_rssadditem(bot, ievent):
    try:
        (name, item) = ievent.args
    except ValueError:
        ievent.missing('<name> <item>')
        return
    if bot.jabber or users.allowed(ievent.userhost, ['OPER', ]):
        target = ievent.channel.lower()
    else:
        target = ievent.nick.lower()
    if not watcher.byname(name):
        ievent.reply("we don't have a %s feed" % name)
        return
    watcher.itemslists.adduniq(jsonstring([name, target]), item)
    watcher.itemslists.save()
    ievent.reply('%s added to (%s,%s) itemslist' % (item, name, target))

cmnds.add('rss-additem', handle_rssadditem, ['RSS', 'USER'])
examples.add('rss-additem', 'add a token to the itemslist (per user/channel)', 'rss-additem gozerbot link')
tests.add('rss-additem dev link')

rss-delitem command

def handle_rssdelitem(bot, ievent):
    try:
        (name, item) = ievent.args
    except ValueError:
        ievent.missing('<name> <item>')
        return
    if users.allowed(ievent.userhost, ['OPER', 'RSS']):
        target = ievent.channel.lower()
    else:
        target = ievent.nick.lower()
    if not watcher.byname(name):
        ievent.reply("we don't have a %s feed" % name)
        return
    try:
        watcher.itemslists.remove(jsonstring([name, target]), item)
        watcher.itemslists.save()
    except RssNoSuchItem:
        ievent.reply("we don't have a %s rss feed" % name)
        return
    ievent.reply('%s removed from (%s,%s) itemslist' % (item, name, target))

cmnds.add('rss-delitem', handle_rssdelitem, ['RSS', 'USER'])
examples.add('rss-delitem', 'remove a token from the itemslist (per user/channel)', 'rss-delitem gozerbot link')
tests.add('rss-delitem')

rss-markuplist command

def handle_rssmarkuplist(bot, ievent):
    ievent.reply('possible markups ==> ' , possiblemarkup, dot=True)

cmnds.add('rss-markuplist', handle_rssmarkuplist, 'USER')
examples.add('rss-markuplist', 'show possible markup entries', 'rss-markuplist')
tests.add('rss-markuplist')

rss-markup command

def handle_rssmarkup(bot, ievent):
    try:
        name = ievent.args[0]
    except IndexError:
        ievent.missing('<name>')
        return
    if users.allowed(ievent.userhost, ['OPER', ]):
        target = ievent.channel.lower()
    else:
        target = ievent.nick.lower()
    try:
        ievent.reply(str(watcher.markup[jsonstring([name, target])]))
    except KeyError:
        pass

cmnds.add('rss-markup', handle_rssmarkup, ['RSS', 'USER'])
examples.add('rss-markup', 'show markup list for a feed (per user/channel)', 'rss-markup gozerbot')
tests.add('rss-markup dev')

rss-addmarkup command

def handle_rssaddmarkup(bot, ievent):
    try:
        (name, item, value) = ievent.args
    except ValueError:
        ievent.missing('<name> <item> <value>')
        return
    if users.allowed(ievent.userhost, ['OPER', ]):
        target = ievent.channel.lower()
    else:
        target = ievent.nick.lower()
    try:
        value = int(value)
    except ValueError:
        pass
    try:
        watcher.markup.set(jsonstring([name, target]), item, value)
        watcher.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('rss-addmarkup', handle_rssaddmarkup, ['RSS', 'USER'])
examples.add('rss-addmarkup', 'add a markup option to the markuplist (per user/channel)', 'rss-addmarkup gozerbot all-lines 1')
tests.add('rss-addmarkup dev')

rss-delmarkup command

def handle_rssdelmarkup(bot, ievent):
    try:
        (name, item) = ievent.args
    except ValueError:
        ievent.missing('<name> <item>')
        return
    if users.allowed(ievent.userhost, ['OPER', 'RSS']):
        target = ievent.channel.lower()
    else:
        target = ievent.nick.lower()
    try:
        del watcher.markup[jsonstring([name, target])][item]
    except (KeyError, TypeError):
        ievent.reply("can't remove %s from %s feed's markup" %  (item, name))
        return
    watcher.markup.save()
    ievent.reply('%s removed from (%s,%s) markuplist' % (item, name, target))

cmnds.add('rss-delmarkup', handle_rssdelmarkup, ['RSS', 'USER'])
examples.add('rss-delmarkup', 'remove a markup option from the markuplist (per user/channel)', 'rss-delmarkup gozerbot all-lines')
tests.add('rss-delmarkup dev all-lines')

rss-delchannel command

def handle_rssdelchannel(bot, ievent):
    """ rss-delchannel <name> [<botname>] <channel> .. delete channel \
        from rss item """
    botname = None
    try:
        (name, botname, channel) = ievent.args
    except ValueError:
        try:
            (name, channel) = ievent.args
            botname = bot.name
        except ValueError:
            try:
                name = ievent.args[0]
                botname = bot.name
                channel = ievent.channel
            except IndexError:
                ievent.missing('<name> [<botname>] [<channel>]')
                return
    rssitem = watcher.byname(name)
    if rssitem == None:
        ievent.reply("we don't have a %s rss object" % name)
        return
    if jsonstring([botname, channel]) in rssitem.watchchannels:
        rssitem.watchchannels.remove(jsonstring([botname, channel]))
        ievent.reply('%s removed from %s rss item' % (channel, name))
    elif [botname, channel] in rssitem.watchchannels:
        rssitem.watchchannels.remove([botname, channel])
        ievent.reply('%s removed from %s rss item' % (channel, name))
    else:
        ievent.reply('we are not monitoring %s on (%s,%s)' % (name, botname, \
channel))
        return
    watcher.save()

cmnds.add('rss-delchannel', handle_rssdelchannel, 'OPER')
examples.add('rss-delchannel', 'rss-delchannel <name> [<botname>] [<channel>] .. delete <channel> or <botname> <channel> from watchchannels of \
<name>', '1) rss-delchannel gozerbot #dunkbots 2) rss-delchannel gozerbot main #dunkbots')
tests.add('rss-delchannel dev exec')

rss-stopwatch command

def handle_rssstopwatch(bot, ievent):
    """ rss-stopwatch <name> .. stop a watcher thread """
    try:
        name = ievent.args[0]
    except IndexError:
        ievent.missing('<name>')
        return
    rssitem = watcher.byname(name)
    if not rssitem:
        ievent.reply("there is no %s rssitem" % name)
        return
    if not watcher.stopwatch(name):
        ievent.reply("can't stop %s watcher" % name)
        return
    ievent.reply('stopped %s rss watch' % name)

cmnds.add('rss-stopwatch', handle_rssstopwatch, 'OPER')
examples.add('rss-stopwatch', 'rss-stopwatch <name> .. stop polling <name>', 'rss-stopwatch gozerbot')
tests.add('rss-stopwatch makker')

rss-sleepttime command

def handle_rsssleeptime(bot, ievent):
    """ rss-sleeptime <name> .. get sleeptime of rss item """
    try:
        name = ievent.args[0]
    except IndexError:
        ievent.missing('<name>')
        return
    rssitem = watcher.byname(name)
    if rssitem == None:
        ievent.reply("we don't have a %s rss item" % name)
        return
    try:
        ievent.reply('sleeptime for %s is %s seconds' % (name, \
str(rssitem.sleeptime)))
    except AttributeError:
        ievent.reply("can't get sleeptime for %s" % name)

cmnds.add('rss-sleeptime', handle_rsssleeptime, 'OPER')
examples.add('rss-sleeptime', 'rss-sleeptime <name> .. get sleeping time for <name>', 'rss-sleeptime gozerbot')
tests.add('rss-sleeptime dev')

rss-setsleeptime command

def handle_rsssetsleeptime(bot, ievent):
    """ rss-setsleeptime <name> <seconds> .. set sleeptime of rss item """
    try:
        (name, sec) = ievent.args
        sec = int(sec)
    except ValueError:
        ievent.missing('<name> <seconds>')
        return
    if sec < 60:
        ievent.reply('min is 60 seconds')
        return
    rssitem = watcher.byname(name)
    if rssitem == None:
        ievent.reply("we don't have a %s rss item" % name)
        return
    rssitem.sleeptime = sec
    if rssitem.running:
        try:
            watcher.changeinterval(name, sec)
        except KeyError, ex:
            ievent.reply("failed to set interval: %s" % str(ex))
            return
    watcher.save()
    ievent.reply('sleeptime set')

cmnds.add('rss-setsleeptime', handle_rsssetsleeptime, 'OPER')
examples.add('rss-setsleeptime', 'rss-setsleeptime <name> <seconds> .. set sleeping time for <name> .. min 60 sec', 'rss-setsleeptime gozerbot 600')
tests.add('rss-setsleeptime dev 60')

rss-get command

def handle_rssget(bot, ievent):
    """ rss-get  <name> .. fetch rss data """
    try:
        name = ievent.args[0]
    except IndexError:
        ievent.missing('<name>')
        return
    channel = ievent.channel
    rssitem = watcher.byname(name)
    if rssitem == None:
        ievent.reply("we don't have a %s rss item" % name)
        return
    try:
        result = watcher.getdata(name)
    except Exception, ex:
        ievent.reply('%s error: %s' % (name, str(ex)))
        return
    if watcher.markup.get(jsonstring([name, channel]), 'reverse-order'):
        result = result[::-1]
    response = None
    go = watcher.markup.get(jsonstring([name, channel]), 'all-lines')
    if go:
        for i in result:
            response = watcher.makeresponse(name, [i, ], channel)
            bot.say(channel, "\002%s\002: %s" % (rssitem.name, response), fromm=rssitem.name)
    else:
        response = watcher.makeresponse(name, result, ievent.channel)
        if response:
            ievent.reply("results of %s: %s" % (name, response))
        else:
            ievent.reply("can't match watcher data")

cmnds.add('rss-get', handle_rssget, ['RSS', 'USER'], threaded=True)
examples.add('rss-get', 'rss-get <name> .. get data from <name>', 'rss-get gozerbot')
tests.add('rss-get dev')

rss-runnig command

def handle_rssrunning(bot, ievent):
    """ rss-running .. show which watchers 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 rss watchers: ", resultlist, nr=1)
    else:
        ievent.reply('nothing running yet')

cmnds.add('rss-running', handle_rssrunning, ['RSS', 'USER'])
examples.add('rss-running', 'rss-running .. get running rsswatchers', 'rss-running')
tests.add('rss-running')

rss-list command

def handle_rsslist(bot, ievent):
    """ rss-list .. return list of rss items """
    result = watcher.list()
    result.sort()
    if result:
        ievent.reply("rss items: ", result, dot=True)
    else:
        ievent.reply('no rss items yet')

cmnds.add('rss-list', handle_rsslist, ['RSS', 'USER'])
examples.add('rss-list', 'get list of rss items', 'rss-list')
tests.add('rss-list')

rss-url command

def handle_rssurl(bot, ievent):
    """ rss-url <name> .. return url of rss item """
    try:
        name = ievent.args[0]
    except IndexError:
        ievent.missing('<name>')
        return
    result = watcher.url(name)
    if not result:
        ievent.reply("can't fetch url for %s" % name)
        return
    try:
        if ':' in result.split('@')[0]:
            if not ievent.msg:
                ievent.reply('run this command in a private message')
                return
            if not users.allowed(ievent.userhost, 'OPER'):
                ievent.reply('you need have OPER perms')
                return
    except (TypeError, ValueError):
        pass
    ievent.reply('url of %s: %s' % (name, result))

cmnds.add('rss-url', handle_rssurl, ['RSS', 'OPER'])
examples.add('rss-url', 'rss-url <name> .. get url from rssitem with <name>', 'rss-url gozerbot')
tests.add('rss-url dev')

rss-seturl command

def handle_rssseturl(bot, ievent):
    """ rss-seturl <name> <url> .. set url of rss item """
    try:
        name = ievent.args[0]
        url = ievent.args[1]
    except IndexError:
        ievent.missing('<name> <url>')
        return
    oldurl = watcher.url(name)
    if not oldurl:
        ievent.reply("no %s rss item found" % name)
        return
    if watcher.seturl(name, url):
        watcher.sync(name)
        ievent.reply('url of %s changed from %s to %s' % (name, oldurl, \
url))
    else:
        ievent.reply('failed to set url of %s to %s' % (name, url))

cmnds.add('rss-seturl', handle_rssseturl, ['RSS', 'OPER'])
examples.add('rss-seturl', 'rss-seturl <name> <url> .. change url of rssitem', 'rss-seturl gozerbot http://core.gozerbot.org/hg/dev/0.9/rss-log')
tests.add('rss-seturl dev http://gozerbot.googlecode.com/hg/')

rss-itemslist command

def handle_rssitemslist(bot, ievent):
    """ rss-itemslist <name> .. show itemslist of rss item """
    try:
        name = ievent.args[0]
    except IndexError:
        ievent.missing('<name>')
        return
    try:
        itemslist = watcher.itemslists[jsonstring([name, ievent.channel.lower()])]
    except KeyError:
        ievent.reply("no itemslist set for (%s, %s)" % (name, ievent.channel.lower()))
        return
    ievent.reply("itemslist of (%s, %s): " % (name, ievent.channel.lower()), itemslist, dot=True)

cmnds.add('rss-itemslist', handle_rssitemslist, ['RSS', 'USER'])
examples.add('rss-itemslist', 'rss-itemslist <name> .. get itemslist of <name> ', 'rss-itemslist gozerbot')
tests.add('rss-itemslist dev')

rss-scan command

def handle_rssscan(bot, ievent):
    """ rss-scan <name> .. scan rss item for used xml items """
    try:
        name = ievent.args[0]
    except IndexError:
        ievent.missing('<name>')
        return
    if not watcher.byname(name):
        ievent.reply('no %s feeds available' % name)
        return
    try:
        result = watcher.scan(name)
    except Exception, 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('rss-scan', handle_rssscan, 'OPER')
examples.add('rss-scan', 'rss-scan <name> .. get possible items of <name> ', 'rss-scan gozerbot')
tests.add('rss-scan dev')

rss-sync command

def handle_rsssync(bot, ievent):
    """ rss-sync <name> .. sync rss item data """
    try:
        name = ievent.args[0]
    except IndexError:
        ievent.missing('<name>')
        return
    try:
        result = watcher.sync(name)
        ievent.reply('%s synced' % name)
    except Exception, ex:
        ievent.reply("%s error: %s" % (name, str(ex)))

cmnds.add('rss-sync', handle_rsssync, 'OPER')
examples.add('rss-sync', 'rss-sync <name> .. sync data of <name>', 'rss-sync gozerbot')
tests.add('rss-sync dev')

rss-feeds command

def handle_rssfeeds(bot, ievent):
    """ rss-feeds <channel> .. show what feeds are running in a channel """
    try:
        channel = ievent.args[0]
    except IndexError:
        channel = ievent.printto
    try:
        result = watcher.feeds(bot.name, channel)
        if result:
            ievent.reply("feeds running in %s: " % channel, result, dot=True)
        else:
            ievent.reply('%s has no feeds running' % channel)
    except Exception, ex:
        ievent.reply("ERROR: %s" % str(ex))

cmnds.add('rss-feeds', handle_rssfeeds, ['USER', 'RSS'])
examples.add('rss-feeds', 'rss-feeds <name> .. show what feeds are running in a channel', '1) rss-feeds 2) rss-feeds #dunkbots')
tests.add('rss-feeds')

rss-descroption command

def handle_rssdescription(bot, ievent):
    try:
        feed, rest = ievent.rest.split(' ', 1)
    except ValueError:
        ievent.missing('<feed> <words to search>')
        return
    rest = rest.strip().lower()
    res = ""
    try:
        ievent.reply(watcher.search(feed, 'description', rest), dot=" \002||\002 ")
    except KeyError:
        ievent.reply('no %s feed data available' % feed)
        return

cmnds.add('rss-description', handle_rssdescription, ['RSS', 'USER'])
examples.add('rss-description', 'give description of item which title matches search key', 'rss-description gozerbot gozer')
tests.add('rss-description')

rss-all command

def handle_rssall(bot, ievent):
    try:
        feed = ievent.args[0]
    except IndexError:
        ievent.missing('<feed>')
        return
    try:
        ievent.reply(watcher.all(feed, 'title'), dot=" \002||\002 ")
    except KeyError:
        ievent.reply('no %s feed data available' % feed)
        return

cmnds.add('rss-all', handle_rssall, ['RSS', 'USER'])
examples.add('rss-all', "give titles of a feed", 'rss-all gozerbot')
tests.add('rss-all dev')

rss-search command

def handle_rsssearch(bot, ievent):
    try:
        txt = ievent.args[0]
    except IndexError:
        ievent.missing('<txt>')
        return
    try:
        ievent.reply(watcher.searchall('title', txt), dot=" \002||\002 ")
    except KeyError:
        ievent.reply('no %s feed data available' % feed)
        return

cmnds.add('rss-search', handle_rsssearch, ['RSS', 'USER'])
examples.add('rss-search', "search titles of all current feeds", 'rss-search goz')
tests.add('rss-search gozerbot')

rss-dump command

def handle_rssdump(bot, ievent):
    try:
        ievent.reply(str(watcher.rawresults[ievent.rest]))
    except Exception, ex:
        ievent.reply(str(ex))

cmnds.add('rss-dump', handle_rssdump, 'OPER')
examples.add('rss-dump', 'dump cached rss data', 'rss-dump')
tests.add('rss-dump dev')

rss-peek command

def handle_rsspeek(bot, ievent):
    if not ievent.rest:
        ievent.missing('<feedname>')
        return
    watcher.peek(ievent.rest)

cmnds.add('rss-peek', handle_rsspeek, 'OPER')
tests.add('rss-peek dev')