codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
class Queue_Manager(threading.Thread): def __init__(self, connection, delay=network['announce_delay']): threading.Thread.__init__(self) self.setDaemon(1) self.connection = connection self.delay = delay self.event = threading.Event() self.queue = [] def run(self): while 1: self.event.wait() while self.queue: (msg, target) = self.queue.pop(0) try: self.connection.privmsg(target, msg) except irclib.ServerNotConnectedError as error: print(error) time.sleep(self.delay) self.event.clear() def send(self, msg, target): self.queue.append((msg.strip(), target)) self.event.set() class ReconnectStrategy(object): min_interval = 60 max_interval = 300 def __init__(self, **attrs): vars(self).update(attrs) assert 0 <= self.min_interval <= self.max_interval self._check_scheduled = False self.attempt_count = itertools.count(1) def run(self, bot): self.bot = bot if self._check_scheduled: return # calculate interval in seconds based on connection attempts intvl = 2**next(self.attempt_count) - 1 # limit the max interval intvl = min(intvl, self.max_interval) # add jitter and truncate to integer seconds intvl = int(intvl * random.random()) # limit the min interval intvl = max(intvl, self.min_interval) self.bot.reactor.scheduler.execute_after(intvl, self.check) self._check_scheduled = True def check(self): self._check_scheduled = False if not self.bot.connection.is_connected(): self.run(self.bot) self.bot.jump_server() class _feedie(SimpleIRCClient): def __init__(self): irclib.SimpleIRCClient.__init__(self) self.start_time = time.time() self.queue = Queue_Manager(self.connection) self.reconnection_interval = 10 self.channels = utils.IrcDict() self.recon = ReconnectStrategy(min_interval=self.reconnection_interval) self.urlShorter = utils.URLShortener(feedie['shorten_service']) self.lastRequest = {} self.cachedFeeds = {} def on_welcome(self, serv, ev): if network['password']: serv.privmsg("nickserv", "IDENTIFY {}".format(network['password'])) serv.privmsg("chanserv", "SET irc_auto_rejoin ON") serv.privmsg("chanserv", "SET irc_join_delay 0") for name in feeds[0]: if not feeds[0][name]['enabled']: continue try: serv.join(feeds[0][name]['channel'], key=feeds[0][name]['channel_key']) except: serv.join(feeds[0][name]['channel']) try: self.history_manager() time.sleep(2) self.queue.start() self.initFeedRefreshTimers() except (OSError, IOError) as error: serv.disconnect() print(error) sys.exit(1) def on_rss_entry(self, chan=None, text=''): if chan: self.queue.send(text, chan) else: for name in feeds[0]: self.queue.send(text, feeds[0][name]['channel']) def mircColor(self, s, fg=None, bg=None): """Returns s with the appropriate mIRC color codes applied.""" if fg is None and bg is None: return s elif bg is None: fg = mircColors[str(fg)] return '\x03%s%s\x03' % (fg.zfill(2), s) elif fg is None: bg = mircColors[str(bg)] # According to the mirc color doc, a fg color MUST be specified if a # background color is specified. So, we'll specify 00 (white) if the # user doesn't specify one. return '\x0300,%s%s\x03' % (bg.zfill(2), s) else: fg = mircColors[str(fg)] bg = mircColors[str(bg)] # No need to zfill fg because the comma delimits. return '\x03%s,%s%s\x03' % (fg, bg.zfill(2), s) def _getConverter(self, feed): toText = utils.htmlToText if 'encoding' in feed: return lambda s: toText(s).strip().encode(feed['encoding'], 'replace') else: return lambda s: toText(s).strip() def getHeadlines(self, feed): headlines = [] conv = self._getConverter(feed) for d in feed['items']: if 'title' in d: title = conv(d['title']) link = d.get('link') if link: headlines.append((title, link)) else: headlines.append((title, None)) return headlines def getFeed(self, url): def error(s): return {'items': [{'title': s}]} try: #print('Downloading new feed from %u' % url) results = feedparser.parse(url) if 'bozo_exception' in results: raise results['bozo_exception'] except sgmllib.SGMLParseError: return error('Invalid (unparsable) RSS feed.') except socket.timeout: return error('Timeout downloading feed.') except Exception, e: # These seem mostly harmless. We'll need reports of a kind that isn't. print('Allowing bozo_exception "%r" through.' % e) if results.get('feed', {}): self.cachedFeeds[url] = results self.lastRequest[url] = time.time() else: print('Not caching results; feed is empty.') try: return self.cachedFeeds[url] except KeyError: # If there's a problem retrieving the feed, we should back off # for a little bit before retrying so that there is time for # the error to be resolved. self.lastRequest[url] = time.time() - .5 * 180 return error('Unable to download feed.') def initFeedRefreshTimers(self): for feed in feeds: for name in feed: if not feed[name]['enabled']: continue try: refresh_time = feed[name]['refresh_delay'] except KeyError: refresh_time = network['default_refresh_delay'] threading.Timer(refresh_time, self.feed_refresh, (feed,name,refresh_time,)).start() def feed_refresh(self, feed, name, refresh_time): url = feed[name]['url'] try: oldresults = self.cachedFeeds[url] oldheadlines = self.getHeadlines(oldresults) except KeyError: oldheadlines = [] if not network['startup_announces'] and not oldheadlines: newresults = self.getFeed(url) threading.Timer(refresh_time, self.feed_refresh, (feed,name,refresh_time,)).start() return else: newresults = self.getFeed(url) newheadlines = self.getHeadlines(newresults) if len(newheadlines) == 1: s = newheadlines[0][0] if s in ('Timeout downloading feed.', 'Unable to download feed.'): print('%s %u', s, url) threading.Timer(refresh_time, self.feed_refresh, (feed,name,refresh_time,)).start() return def canonize(headline): return (tuple(headline[0].lower().split()), headline[1]) oldheadlines = set(map(canonize, oldheadlines)) for (i, headline) in enumerate(newheadlines): if canonize(headline) in oldheadlines: newheadlines[i] = None newheadlines = filter(None, newheadlines) # Removes Nones. if newheadlines: for headline in newheadlines: if headline[1]: title = headline[0] short_url = self.urlShorter.shorten_url(headline[1]) if not short_url or short_url == 'Error': short_url = url feedName = self.mircColor(name, feed[name]['color']) feedTitle = self.mircColor(title, 'blue') try: chan = feed[name]['channel'] except KeyError: # send to all channels chan = None self.on_rss_entry(chan=chan, text='{0} {1} {2}'.format(feedName, feedTitle, self.underline(short_url))) threading.Timer(refresh_time, self.feed_refresh, (feed,name,refresh_time,)).start()
Private
[
?
]
Run code
Submit