diff options
Diffstat (limited to 'news/newsbot.py')
-rw-r--r-- | news/newsbot.py | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/news/newsbot.py b/news/newsbot.py new file mode 100644 index 00000000..5850e4e9 --- /dev/null +++ b/news/newsbot.py @@ -0,0 +1,239 @@ +from ircasy import asybot +import threading +from asyncore import loop +import logging +import os +import subprocess + +import feedparser +import math +import re +import subprocess +from datetime import datetime +from time import sleep +#testbot = NewsBot('ire', 6667, 'crabman23', ['#retiolum'], loglevel=logging.DEBUG) + + + +## Newsbot Controller Class +class NewsBot(asybot): + def __init__(self, name, channels=['#test'], server='ire', port=6667, timeout=60, loglevel=logging.ERROR, url_shortener='http://wall'): + asybot.__init__(self, server, port, name, channels, loglevel=loglevel) + self.to = timeout + self.url_shortener = url_shortener + self.ctrl_chan = channels[0] + + def send_msg(self, target, msg): + for line in msg.split('\n'): + self.PRIVMSG(target, line) + + def on_privmsg(self, prefix, command, params, rest): + args_array = rest.split() + if params[0] == self.nickname: + answer = self.read_message(args_array) + self.send_msg(prefix.split('!')[0], answer) + elif args_array[0].strip(':') == self.nickname: + answer = self.read_message(args_array[1:]) + self.send_msg([params[0]], answer) + + def on_invite(self, prefix, command, params, rest): + for chan in rest.split(): + self.push('JOIN ' + chan) + + def read_message(self, args): + try: + if args[0] in [x for x in commands.__dict__.keys() if x.find('_')]: + func = getattr(commands, args[0]) + return func(self, args) + else: + return 'command not found' + except Exception as e: + return 'mimimi: ' + str(e) + +#Commands of NewsBot +class commands(): + def add(self, args): + if args[1] not in bots and args[1] != self.nickname: + try: + bot = RssBot(args[2], args[1], [self.ctrl_chan], url_shortener=self.url_shortener) + except Exception as e: + return 'add_mimi: ' + str(e) + sleep + bots[args[1]] = bot + bot.start_rss() + return "bot " + args[1] + " added" + else: + return args[1] + ' does already exist' + + def delete(self, args): + bots[args[1]].stop() + del bots[args[1]] + return "bot " + args[1] + " deleted" + + def rename(self, args): + if args[1] in bots: + if args[2] in bots: + return args[2] + ' already taken' + else: + bots[args[1]].connection.nick(args[2]) + bots[args[1]].name = args[2] + bots[args[2]] = bots[args[1]] + del bots[args[1]] + return 'renamed ' + args[1] + ' in ' + args[2] + else: + return args[1] + ' does not exist' + + def save(self, args): + output_buffer = '' + for bot in bots: + if bots[bot].loop: + output_buffer += bot + '|' + bots[bot].url + '|' + ' '.join(bots[bot].channels) + '\n' + + F = open(feedfile, "w") + F.writelines(output_buffer) + F.close() + + return "bots saved to " + feedfile + + def caps(self, args): + return ' '.join([x for x in commands.__dict__.keys() if x.find('_')]) + + def list(self, args): + output_buffer = '' + for bot in bots: + output_buffer += bot + ' url: ' + bots[bot].url + '\n' + return output_buffer + + def info(self, args): + if args[1] in bots: + output_buffer = '' + for data in ['title', 'link', 'updated']: + if data in bots[args[1]].feed.feed: + output_buffer += data + ': ' + bots[args[1]].feed.feed[data] + '\n' + output_buffer += 'lastnew: ' + bots[args[1]].lastnew.isoformat() + '\n' + output_buffer += 'rssurl: ' + bots[args[1]].url + return output_buffer + else: + return 'bot not found' + + def search(self, args): + output = subprocess.check_output(['./GfindFeeds4bot', args[1]]).decode() + return output + + def uptime(self, args): + output = subprocess.check_output(['uptime']).decode() + return output + + +##RssBot Class +class RssBot(asybot): + def __init__(self, rss, name, chans=['#news'], url_shortener="http://localhost", server='ire', port=6667, timeout=60): + try: + asybot.__init__(self, server, port, name, chans) + except Exception as e: + print(e) + self.url = rss + self.to = timeout + self.oldnews = [] + self.loop = True + self.lastnew = datetime.now() + self.url_shortener = url_shortener + + def start_rss(self): + self.upd_loop = threading.Thread(target=self.updateloop) + self.upd_loop.start() + + def stop(self): + self.disconnect() + self.loop = False + + def updateloop(self): + failcount=0 + while True: + try: + self.feed = feedparser.parse(self.url) + for entry in self.feed.entries: + self.oldnews.append(entry.link) + break + except: + print(self.nickname + ': rss timeout occured') + failcount+=1 + if failcount>20: + print(self.nickname + ' is broken, going to die') + self.stop() + return + while self.loop: + try: + self.feed = feedparser.parse(self.url) + for entry in self.feed.entries: + if not entry.link in self.oldnews: + #try: + # self.send_msg(entry.title + " " + entry.link + " com: " + entry.comments) + #except AttributeError: + shorturl = self.shortenurl(entry.link) + self.sendall(entry.title + ' ' + shorturl) + self.oldnews.append(entry.link) + self.lastnew = datetime.now() + except: + print(self.nickname + ': rss timeout occured') + sleep(self.to) + + def shortenurl(self, url): + while True: + try: + shorturl = subprocess.check_output(["curl", "-sS", "-F", "uri=" + url, self.url_shortener]).decode().strip('\n').strip('\r') + '#' + url.partition('://')[2].partition('/')[0] + return shorturl + except: + print('url shortener error') + sleep(1) + + def last(self, target, num): + for feed in [x for x in self.feed.entries][:num]: + self.send_msg(target, feed.title + ' ' + self.shortenurl(feed.link)) + + def sendall(self, string): + self.send_msg(self.channels, string) + + def send_msg(self, target, string): + if self.connected: + for line in string.split('\n'): + if len(line) < 450: + self.PRIVMSG(target, line) + else: + space = 0 + for x in range(math.ceil(len(line)/400)): + oldspace = space + space = line.find(" ", (x+1)*400, (x+1)*400+50) + self.PRIVMSG(target, line[oldspace:space]) + else: + self.reconnect() + while not self.connected: + sleep(3) + print('waiting for reconnect') + self.send_msg(string) + + def on_invite(self, prefix, command, params, rest): + for chan in rest.split(): + self.push('JOIN ' + chan) + +feedfile = 'new_feeds' +url_shortener = 'http://wall' +init_channels = ['#news'] + +bots = {} +knews = NewsBot('knews') + +#config file reading +F = open(feedfile, "r") +lines = F.readlines() +F.close() + +for line in lines: + line = line.strip('\n') + linear = line.split('|') + bot = RssBot(linear[1], linear[0], init_channels + linear[2].split(), url_shortener=url_shortener) + bot.start_rss() + bots[linear[0]] = bot + +th = threading.Thread(target=loop) +th.start() |