100
155
""" get data of rss feed """
101
156
rssitem = self.byname(name)
102
157
if rssitem == None:
104
# fetch data from url
105
urlresult = fromenc(geturl2(rssitem.url, True), what=name)
109
result = rsslist(urlresult)
110
except xml.parsers.expat.ExpatError, ex:
111
rlog(10, 'rss', '%s: %s' % (name, str(ex)))
116
for z, zz in i.iteritems():
117
if z in rssitem.itemslist:
118
if type(zz) == types.DictType:
128
resultlist.append(temp)
158
raise RssNoSuchItem("no %s rss item found" % name)
160
modified = self.modified[name]
164
etag = self.etag[name]
167
result = feedparser.parse(rssitem.url, modified=modified, etag=etag, \
169
if result and result.has_key('bozo_exception'):
170
rlog(10, 'rss', '%s bozo_exception: %s' % (name, \
171
result['bozo_exception']))
172
#raise RssStatus(result['bozo_exception'])
174
status = result.status
175
except AttributeError:
177
if status != 200 and status != 301 and status != 302 and status != 304:
178
raise RssStatus(status)
180
self.modified[name] = result.modified
181
except AttributeError:
184
self.etag[name] = result.etag
185
except AttributeError:
188
return self.rawresults[name]
190
self.rawresults[name] = result.entries
191
return result.entries
131
193
class Rsswatcher(Rssdict):
135
197
def __init__(self, filename):
136
198
Rssdict.__init__(self, filename)
200
def sync(self, name):
201
result = self.getdata(name)
203
self.results[name] = result
140
205
def changeinterval(self, name, interval):
141
206
periodical.changeinterval(self.jobids[name], interval)
143
209
def startwatchers(self):
144
210
""" start watcher threads """
145
for i in self.data.values():
211
for j, i in self.data.iteritems():
149
except Exception, ex:
150
rlog(100, 'rss', '%s feed error: %s' % (i.name, str(ex)))
152
rlog(10, 'rss', 'started %s rss watch' % i.name)
213
thr.start_new_thread(self.watch, (i.name, ))
154
216
def stopwatchers(self):
155
217
""" stop all watcher threads """
156
for i in self.data.values():
218
for j, i in self.data.iteritems():
158
220
i.stoprunning = 1
159
221
periodical.killgroup('rss')
223
def dowatch(self, name, sleeptime=1800):
224
rssitem = self.byname(name)
226
rlog(10, 'rss', "no %s rss item available" % name)
231
except Exception, ex:
232
rlog(100, 'rss', '%s feed error: %s' % (name, str(ex)))
233
rlog(100, 'rss', '%s sleeping %s seconds for retry' % \
235
time.sleep(sleeptime)
236
if not rssitem.running:
241
def makeresult(self, name, target, data):
245
if not self.itemslists[(name, target)]:
247
for i in self.itemslists[(name, target)]:
249
tmp[i] = unicode(j[i])
161
255
def watch(self, name):
162
256
""" start a watcher thread """
164
result = self.getdata(name)
258
rlog(10, 'rss', 'trying %s rss feed watcher' % name)
260
result = self.getdata(name)
261
except RssException, ex:
262
rlog(10, 'rss', "%s error: %s" % (name, str(ex)))
264
rssitem = self.byname(name)
267
# poll every sleeptime seconds
165
268
self.results[name] = result
166
rssitem = self.byname(name)
167
# poll every sleeptime seconds
168
269
pid = periodical.addjob(rssitem.sleeptime, 0, self.peek, name, name)
169
270
self.jobids[name] = pid
171
def peek(self, name):
271
rlog(10, 'rss', 'started %s rss watch' % name)
273
def makeresponse(self, name, res, channel, sep="\002||\002"):
274
# loop over result to make a response
276
itemslist = self.itemslists[(name, channel)]
278
rssitem = self.byname(name)
280
return "no %s rss item" % name
282
self.itemslists.extend((name, channel), rssitem.itemslist)
283
self.itemslists.save()
286
for i in self.itemslists[(name, channel)]:
291
if item.startswith('http://'):
292
resultstr += "<%s> - " % item
294
resultstr += "%s - " % striphtml(item)
297
resultstr = resultstr[:-3]
299
result += "%s %s " % (resultstr, sep)
302
def peek(self, name, *args):
172
303
rssitem = self.byname(name)
173
304
if not rssitem or not rssitem.running or rssitem.stoprunning:
178
309
except socket.timeout:
179
310
rlog(10, 'rss', 'socket timeout of %s' % name)
312
except RssException, ex:
313
rlog(10, 'rss', '%s error: %s' % (name, str(ex)))
182
rlog(10, 'rss', "can't match %s data" % name)
183
# loop over result to see if we already seen item
187
if j not in self.results[name]:
188
self.results[name].append(j)
322
if j not in self.results[name]:
323
self.results[name].append(j)
326
if not checkfordate(self.results[name], d):
327
self.results[name].append(j)
331
for item in rssitem.watchchannels:
333
(botname, channel) = item
335
rlog(10, 'rss', '%s is not in the format \
336
(botname,channel)' % str(item))
337
bot = fleet.byname(botname)
193
for i in rssitem.itemslist:
195
if j[i].startswith('http://'):
196
resultstr += "<%s> - " % j[i]
198
resultstr += "%s - " % j[i]
201
resultstr = resultstr[:-3]
202
res2 += "%s \002||\002 " % resultstr
204
for item in rssitem.watchchannels:
206
(botname, channel) = item
207
bot = fleet.byname(botname)
209
rlog(10, 'rss', "can't find bot %s in fleet" \
212
bot.say(channel, "%s: %s" % (rssitem.name, res2[:-4]))
214
rlog(10, 'rss', '%s is not in the format \
215
(botname,channel)' % item)
340
if self.markup.get((name, channel), 'all-lines'):
342
response = self.makeresponse(name, [i, ], channel)
343
bot.say(channel, "\002%s\002: %s" % \
344
(rssitem.name, response), fromm=rssitem.name)
346
sep = self.markup.get((name, channel), 'seperator')
348
response = self.makeresponse(name, res2, channel, \
351
response = self.makeresponse(name, res2, channel)
352
bot.say(channel, "\002%s\002: %s" % (rssitem.name, \
353
response), fromm=rssitem.name)
216
354
except Exception, ex:
217
355
handle_exception(txt=name)
219
358
def stopwatch(self, name):
220
359
""" stop watcher thread """
221
360
for i, j in self.data.iteritems():
236
376
""" return of rss names """
237
return self.data.keys()
377
feeds = self.data.keys()
239
381
def runners(self):
240
382
""" show names/channels of running watchers """
242
for i in self.data.values():
384
for j, i in self.data.iteritems():
243
385
if i.running == 1 and not i.stoprunning:
244
386
result.append((i.name, i.watchchannels))
247
390
def feeds(self, botname, channel):
248
391
""" show names/channels of running watcher """
250
for i in self.data.values():
393
for j, i in self.data.iteritems():
251
394
if (botname, channel) in i.watchchannels:
252
395
result.append(i.name)
255
399
def url(self, name):
256
400
""" return url of rssitem """
257
for i in self.data.values():
401
for j, i in self.data.iteritems():
258
402
if i.name == name:
261
405
def scan(self, name):
262
406
""" scan a rss url for used xml items """
264
result = fromenc(geturl2(self.url(name), True))
265
except Exception, ex:
266
rlog(10, 'rss', str(ex))
268
reslist = rsslist(result)
408
result = self.getdata(name)
409
except RssException, ex:
410
rlog(10, 'rss', '%s error: %s' % (name, str(ex)))
415
for item in self.rawresults[name]:
416
for key in item.keys():
269
418
statdict = Statdict()
271
for j, z in i.iteritems():
274
return statdict.top(start=2)
421
return statdict.top()
423
def search(self, name, item, search):
425
for result in self.rawresults[name]:
427
title = result['title']
431
if search in title.lower():
436
def searchall(self, item, search):
438
for name, results in self.rawresults.iteritems():
439
for result in results:
441
title = result['title']
445
if search in title.lower():
447
res.append("%s: %s" % (name, txt))
450
def all(self, name, item):
452
for result in self.rawresults[name]:
276
461
watcher = Rsswatcher(datadir + os.sep + 'rss')
343
528
if rssitem == None:
344
529
ievent.reply("we don't have a %s rss object" % name)
346
if (bot.name, ievent.channel) not in rssitem.watchchannels:
347
rssitem.watchchannels.append((bot.name, ievent.channel))
532
if not rssitem.running:
348
533
rssitem.sleeptime = sleepsec
349
534
rssitem.running = 1
350
535
rssitem.stoprunning = 0
353
539
watcher.watch(name)
354
540
except Exception, ex:
355
541
ievent.reply(str(ex))
357
545
ievent.reply('watcher started')
359
547
ievent.reply('already watching %s' % name)
361
cmnds.add('rss-watch', handle_rsswatch, ['RSS', 'OPER'])
549
cmnds.add('rss-watch', handle_rsswatch, 'OPER')
362
550
examples.add('rss-watch', 'rss-watch <name> [seconds to sleep] .. go \
363
551
watching <name>', '1) rss-watch gozerbot 2) rss-watch gozerbot 600')
553
def handle_rssstart(bot, ievent):
554
""" rss-start <name> .. start a rss feed to a user """
556
ievent.missing('<feed name>')
559
rssitem = watcher.byname(name)
561
target = ievent.userhost
563
if users.allowed(ievent.userhost, ['OPER', ]) and not ievent.msg:
564
target = ievent.channel
568
ievent.reply("we don't have a %s rss object" % name)
570
if not rssitem.running:
571
ievent.reply('%s watcher is not running' % name)
573
if (bot.name, target) in rssitem.watchchannels:
574
ievent.reply('we are already monitoring %s on (%s,%s)' % \
575
(name, bot.name, target))
577
rssitem.watchchannels.append((bot.name, target))
578
for item in rssitem.itemslist:
579
watcher.itemslists.adduniq((name, target), item)
581
ievent.reply('%s started' % name)
583
cmnds.add('rss-start', handle_rssstart, ['RSS', 'USER'])
584
examples.add('rss-start', 'rss-start <name> .. start a rss feed \
585
(per user/channel) ', 'rss-start gozerbot')
587
def handle_rssstop(bot, ievent):
588
""" rss-start <name> .. start a rss feed to a user """
590
ievent.missing('<feed name>')
593
rssitem = watcher.byname(name)
595
target = ievent.userhost
597
if users.allowed(ievent.userhost, ['OPER', ]) and not ievent.msg:
598
target = ievent.channel
602
ievent.reply("we don't have a %s rss feed" % name)
604
if not rssitem.running:
605
ievent.reply('%s watcher is not running' % name)
607
if not (bot.name, target) in rssitem.watchchannels:
608
ievent.reply('we are not monitoring %s on (%s,%s)' % \
609
(name, bot.name, target))
611
rssitem.watchchannels.remove((bot.name, target))
613
ievent.reply('%s stopped' % name)
615
cmnds.add('rss-stop', handle_rssstop, ['RSS', 'USER'])
616
examples.add('rss-stop', 'rss-stop <name> .. stop a rss feed \
617
(per user/channel) ', 'rss-stop gozerbot')
365
619
def handle_rsschannels(bot, ievent):
366
620
""" rss-channels <name> .. show channels of rss feed """
418
672
ievent.reply('%s added to %s rss item' % (channel, name))
420
cmnds.add('rss-addchannel', handle_rssaddchannel, ['RSS', 'OPER'])
674
cmnds.add('rss-addchannel', handle_rssaddchannel, 'OPER')
421
675
examples.add('rss-addchannel', 'rss-addchannel <name> [<botname>] <channel> \
422
676
..add <channel> or <botname> <channel> to watchchannels of <name>', \
423
677
'1) rss-addchannel gozerbot #dunkbots 2) rss-addchannel gozerbot main \
426
def handle_rssstart(bot, ievent):
427
""" rss-start <name> .. start a rss feed to a user """
429
ievent.missing('<feed name>')
432
rssitem = watcher.byname(name)
434
target = ievent.userhost
438
ievent.reply("we don't have a %s rss object" % name)
440
if not rssitem.running:
441
ievent.reply('%s watcher is not running' % name)
443
if (bot.name, target) in rssitem.watchchannels:
444
ievent.reply('we are already monitoring %s on (%s,%s)' % \
445
(name, bot.name, target))
447
rssitem.watchchannels.append((bot.name, target))
449
ievent.reply('%s started' % name)
451
cmnds.add('rss-start', handle_rssstart, ['USER'])
452
examples.add('rss-start', 'rss-start <name> .. start a rss watcher ',\
453
'rss-start gozerbot')
455
def handle_rssstop(bot, ievent):
456
""" rss-start <name> .. start a rss feed to a user """
458
ievent.missing('<feed name>')
461
rssitem = watcher.byname(name)
463
target = ievent.userhost
680
def handle_rssadditem(bot, ievent):
682
(name, item) = ievent.args
684
ievent.missing('<name> <item>')
686
if bot.jabber or users.allowed(ievent.userhost, ['OPER', ]):
687
target = ievent.channel.lower()
689
target = ievent.nick.lower()
690
if not watcher.byname(name):
691
ievent.reply("we don't have a %s feed" % name)
693
watcher.itemslists.adduniq((name, target), item)
694
watcher.itemslists.save()
696
ievent.reply('%s added to (%s,%s) itemslist' % (item, name, target))
698
cmnds.add('rss-additem', handle_rssadditem, ['RSS', 'USER'])
699
examples.add('rss-additem', 'add a token to the itemslist (per user/channel)',\
700
'rss-additem gozerbot link')
702
def handle_rssdelitem(bot, ievent):
704
(name, item) = ievent.args
706
ievent.missing('<name> <item>')
708
if users.allowed(ievent.userhost, ['OPER', 'RSS']):
709
target = ievent.channel.lower()
711
target = ievent.nick.lower()
712
if not watcher.byname(name):
713
ievent.reply("we don't have a %s feed" % name)
716
watcher.itemslists.remove((name, target), item)
717
watcher.itemslists.save()
718
except RssNoSuchItem:
467
719
ievent.reply("we don't have a %s rss feed" % name)
469
if not rssitem.running:
470
ievent.reply('%s watcher is not running' % name)
472
if not (bot.name, channel) in rssitem.watchchannels:
473
ievent.reply('we are not monitoring %s on (%s,%s)' % \
474
(name, bot.name, channel))
476
rssitem.watchchannels.remove((bot.name, ievent.target))
478
ievent.reply('%s stopped' % name)
480
cmnds.add('rss-stop', handle_rssstop, ['USER'])
481
examples.add('rss-stop', 'rss-stop <name> .. stop a rss watcher ',\
721
ievent.reply('%s removed from (%s,%s) itemslist' % (item, name, target))
723
cmnds.add('rss-delitem', handle_rssdelitem, ['RSS', 'USER'])
724
examples.add('rss-delitem', 'remove a token from the itemslist \
725
(per user/channel)', 'rss-delitem gozerbot link')
727
def handle_rssmarkup(bot, ievent):
729
name = ievent.args[0]
731
ievent.missing('<name>')
733
if users.allowed(ievent.userhost, ['OPER', ]):
734
target = ievent.channel.lower()
736
target = ievent.nick.lower()
738
ievent.reply(str(watcher.markup[(name, target)]))
742
cmnds.add('rss-markup', handle_rssmarkup, ['RSS', 'USER'])
743
examples.add('rss-markup', 'show markup list for a feed (per user/channel)', \
744
'rss-markup gozerbot')
746
def handle_rssaddmarkup(bot, ievent):
748
(name, item, value) = ievent.args
750
ievent.missing('<name> <item> <value>')
752
if users.allowed(ievent.userhost, ['OPER', ]):
753
target = ievent.channel.lower()
755
target = ievent.nick.lower()
757
watcher.markup.set((name, target), item, value)
758
watcher.markup.save()
759
ievent.reply('%s added to (%s,%s) markuplist' % (item, name, target))
761
ievent.reply("no (%s,%s) feed available" % (name, target))
763
cmnds.add('rss-addmarkup', handle_rssaddmarkup, ['RSS', 'USER'])
764
examples.add('rss-addmarkup', 'add a markup option to the markuplist \
765
(per user/channel)', 'rss-addmarkup gozerbot noseperator 1')
767
def handle_rssdelmarkup(bot, ievent):
769
(name, item) = ievent.args
771
ievent.missing('<name> <item>')
773
if users.allowed(ievent.userhost, ['OPER', 'RSS']):
774
target = ievent.channel.lower()
776
target = ievent.nick.lower()
778
del watcher.markup[(name, target)][item]
779
except (KeyError, TypeError):
780
ievent.reply("can't remove %s from %s feed's markup" % (item, name))
782
watcher.markup.save()
783
ievent.reply('%s removed from (%s,%s) markuplist' % (item, name, target))
785
cmnds.add('rss-delmarkup', handle_rssdelmarkup, ['RSS', 'USER'])
786
examples.add('rss-delmarkup', 'remove a markup option from the markuplist \
787
(per user/channel)', 'rss-delmarkup gozerbot noseperator')
484
789
def handle_rssdelchannel(bot, ievent):
485
790
""" rss-delchannel <name> [<botname>] <channel> .. delete channel \
671
956
examples.add('rss-url', 'rss-url <name> .. get url from rssitem with \
672
957
<name>', 'rss-url gozerbot')
674
def handle_rssadditemslist(bot, ievent):
675
""" rss-additemslist <name> <item> .. add item to itemslist of rss item """
677
(name, item) = ievent.args
679
ievent.missing('<name> <item>')
681
rssitem = watcher.byname(name)
683
ievent.reply("we don't have a %s rss item" % name)
685
if item not in rssitem.itemslist:
686
rssitem.itemslist.append(item)
688
ievent.reply('%s is already in %s rsslist' % (item, name))
691
ievent.reply('%s added to itemslist' % item)
693
cmnds.add('rss-additemslist', handle_rssadditemslist, ['RSS', 'OPER'])
694
examples.add('rss-additemslist', 'rss-additemslist <name> <item> .. add to \
695
itemslist of <name> ', 'rss-additemslist gozerbot url')
697
def handle_rssdelitemslist(bot, ievent):
698
""" rss-delitemslist <name> <item> .. delete item from itemslist """
700
(name, item) = ievent.args
702
ievent.missing('<name> <item>')
704
rssitem = watcher.byname(name)
706
ievent.reply("we don't have a %s rss item" % name)
708
if item in rssitem.itemslist:
709
rssitem.itemslist.remove(item)
711
ievent.reply('%s deleted from itemslist' % item)
713
ievent.reply("%s doesn't have %s in itemslist" % (name, item))
715
cmnds.add('rss-delitemslist', handle_rssdelitemslist, ['RSS', 'OPER'])
716
examples.add('rss-delitemslist', 'rss-delitemslist <name> <item> .. \
717
delete from itemslist of <name> ', 'rss-delitemslist gozerbot url')
719
959
def handle_rssitemslist(bot, ievent):
720
960
""" rss-itemslist <name> .. show itemslist of rss item """
793
1035
except Exception, ex:
794
1036
ievent.reply("ERROR: %s" % str(ex))
796
cmnds.add('rss-feeds', handle_rssfeeds, ['RSS', 'OPER'])
1038
cmnds.add('rss-feeds', handle_rssfeeds, ['USER', 'RSS'])
797
1039
examples.add('rss-feeds', 'rss-feeds <name> .. show what feeds are running \
798
1040
in a channel', '1) rss-feeds 2) rss-feeds #dunkbots')
1042
def handle_rsslink(bot, ievent):
1044
feed, rest = ievent.rest.split(' ', 1)
1046
ievent.missing('<feed> <words to search>')
1048
rest = rest.strip().lower()
1050
res = watcher.search(feed, 'link', rest)
1052
res = watcher.search(feed, 'feedburner:origLink', rest)
1054
ievent.reply(res, dot=" \002||\002 ")
1056
ievent.reply('no %s feed data available' % feed)
1059
cmnds.add('rss-link', handle_rsslink, ['RSS', 'USER'])
1060
examples.add('rss-link', 'give link of item which title matches search key', \
1061
'rss-link gozerbot gozer')
1063
def handle_rssdescription(bot, ievent):
1065
feed, rest = ievent.rest.split(' ', 1)
1067
ievent.missing('<feed> <words to search>')
1069
rest = rest.strip().lower()
1072
ievent.reply(watcher.search(feed, 'description', rest), \
1075
ievent.reply('no %s feed data available' % feed)
1078
cmnds.add('rss-description', handle_rssdescription, ['RSS', 'USER'])
1079
examples.add('rss-description', 'give description of item which title \
1080
matches search key', 'rss-description gozerbot gozer')
1082
def handle_rssall(bot, ievent):
1084
feed = ievent.args[0]
1086
ievent.missing('<feed>')
1089
ievent.reply(watcher.all(feed, 'title'), dot=" \002||\002 ")
1091
ievent.reply('no %s feed data available' % feed)
1094
cmnds.add('rss-all', handle_rssall, ['RSS', 'USER'])
1095
examples.add('rss-all', "give titles of a feed", 'rss-all gozerbot')
1097
def handle_rsssearch(bot, ievent):
1099
txt = ievent.args[0]
1101
ievent.missing('<txt>')
1104
ievent.reply(watcher.searchall('title', txt), dot=" \002||\002 ")
1106
ievent.reply('no %s feed data available' % feed)
1109
cmnds.add('rss-search', handle_rsssearch, ['RSS', 'USER'])
1110
examples.add('rss-search', "search titles of all current feeds", \
1113
def handle_rssdump(bot, ievent):
1115
ievent.reply(str(watcher.rawresults[ievent.rest]))
1116
except Exception, ex:
1117
ievent.reply(str(ex))
1119
cmnds.add('rss-dump', handle_rssdump, 'OPER')
1120
examples.add('rss-dump', 'dump cached rss data', 'rss-dump')