def default_mask(trigger): welcome = formatting.color('Welcome to:', formatting.colors.PURPLE) chan = formatting.color(trigger.sender, formatting.colors.TEAL) topic_ = formatting.bold('Topic:') topic_ = formatting.color('| ' + topic_, formatting.colors.PURPLE) arg = formatting.color('{}', formatting.colors.GREEN) return '{} {} {} {}'.format(welcome, chan, topic_, arg)
def rpost_info(bot, trigger, match=None): r = praw.Reddit(user_agent=USER_AGENT) match = match or trigger if len(match.group(1)) < 10: post_url = "https://www.reddit.com/comments/{}/".format(match.group(1)) else: post_url = match.group(1) s = r.get_submission(url=post_url) message = ('[reddit] {title} {link}{nsfw} | {points} points ({percent}) | ' '{comments} comments | Posted by {author} {post_time}') if s.is_self: link = '(self.{})'.format(s.subreddit.display_name) else: link = '({}) to r/{}'.format(s.url, s.subreddit.display_name) if s.over_18: nsfw = bold(color(' [NSFW]', colors.RED)) # TODO implement per-channel settings db, and make this able to kick else: nsfw = '' if s.author: author = s.author.name else: author = '[deleted]' if s.created: post_time = arrow.get(s.created_utc, tzinfo="utc").humanize() else: post_time = '' if s.score > 0: point_color = colors.GREEN else: point_color = colors.RED percent = color(str(int(s.upvote_ratio * 100)) + '%', point_color) message = message.format(title=s.title, link=link, nsfw=nsfw, points=s.score, percent=percent, comments=s.num_comments, author=author, post_time=post_time) bot.say(message)
def rpost_info(bot, trigger, match=None): r = praw.Reddit(user_agent=USER_AGENT) match = match or trigger if len(match.group(1)) < 10: post_url = "https://www.reddit.com/comments/{}/".format(match.group(1)) else: post_url = match.group(1) s = r.get_submission(url=post_url) message = ('[reddit] {title} {link}{nsfw} | {points} points ({percent}) | ' '{comments} comments | Posted by {author} {post_time}') if s.is_self: link = '(self.{})'.format(s.subreddit.display_name) else: link = '({}) to r/{}'.format(s.url, s.subreddit.display_name) if s.over_18: nsfw = bold(color(' [NSFW]', colors.RED)) # TODO implement per-channel settings db, and make this able to kick else: nsfw = '' if s.author: author = s.author.name else: author = '[deleted]' if s.created: post_time = arrow.get(s.created_utc, tzinfo="utc").humanize() else: post_time = '' if s.score > 0: point_color = colors.GREEN else: point_color = colors.RED percent = color(str(int(s.upvote_ratio * 100)) + '%', point_color) message = message.format( title=s.title, link=link, nsfw=nsfw, points=s.score, percent=percent, comments=s.num_comments, author=author, post_time=post_time) bot.say(message)
def rpost_info(bot, trigger, match=None): r = praw.Reddit(user_agent=USER_AGENT) match = match or trigger s = r.get_submission(url=match.group(1)) message = ('[reddit] {title} {link}{nsfw} | {points} points ({percent}) | ' '{comments} comments | Posted by {author}') if s.is_self: link = '(self.{})'.format(s.subreddit.display_name) else: link = '({}) to r/{}'.format(s.url, s.subreddit.display_name) if s.over_18: nsfw = bold(color(' [NSFW]', colors.RED)) # TODO implement per-channel settings db, and make this able to kick else: nsfw = '' if s.author: author = s.author.name else: author = '[deleted]' # TODO add creation time with s.created if s.score > 0: point_color = colors.GREEN else: point_color = colors.RED percent = color(unicode(int(s.upvote_ratio * 100)) + '%', point_color) message = message.format( title=s.title, link=link, nsfw=nsfw, points=s.score, percent=percent, comments=s.num_comments, author=author) bot.say(message)
def read_feeds(bot, force=False): if not bot.memory['rss_manager'].running and not force: return feeds = bot.db._execute('SELECT * FROM rss_feeds').fetchall() if not feeds: return for feed_row in feeds: feed = RSSFeed(feed_row) if not feed.enabled: continue try: fp = feedparser.parse(feed.url, etag=feed.etag, modified=feed.modified) except IOError as e: LOGGER.exception("Can't parse feed on %s, disabling.", feed.name) _disable_feed(feed) continue # fp.status will only exist if pulling from an online feed # fp.version sometimes runs into AttributeError fp.status = getattr(fp, 'status', 'unknown') fp.version = getattr(fp, 'version', 'unknown') LOGGER.debug("%s: status = %s, version = '%s', items = %s", feed.name, fp.status, fp.version, len(fp.entries)) # check HTTP status if fp.status == 301: # MOVED_PERMANENTLY bot.warning( "Got HTTP 301 (Moved Permanently) on %s, updating URI to %s", feed.name, fp.href ) bot.db._execute(''' UPDATE rss_feeds SET feed_url = ? WHERE channel = ? AND feed_name = ? ''', (fp.href, feed.channel, feed.name)) elif fp.status == 410: # GONE LOGGER.warning("Got HTTP 410 (Gone) on {0}, disabling", feed.name) _disable_feed(feed) if not fp.entries: continue feed_etag = getattr(fp, 'etag', None) feed_modified = getattr(fp, 'modified', None) entry = fp.entries[0] # parse published and updated times into datetime objects (or None) entry_dt = (datetime.fromtimestamp(time.mktime(entry.published_parsed)) if hasattr(entry, 'published_parsed') else None) entry_update_dt = (datetime.fromtimestamp(time.mktime(entry.updated_parsed)) if hasattr(entry, 'updated_parsed') else None) # check if article is new, and skip otherwise if (feed.title == entry.title and feed.link == entry.link and feed.etag == feed_etag and feed.modified == feed_modified): LOGGER.info(u"Skipping previously read entry: [%s] %s", feed.name, entry.title) continue # save article title, url, and modified date bot.db._execute(''' UPDATE rss_feeds SET article_title = ?, article_url = ?, published = ?, etag = ?, modified = ? WHERE channel = ? AND feed_name = ? ''', (entry.title, entry.link, entry_dt, feed_etag, feed_modified, feed.channel, feed.name)) if feed.published and entry_dt: published_dt = datetime.strptime(feed.published, "%Y-%m-%d %H:%M:%S") if published_dt >= entry_dt: # This will make more sense once iterating over the feed is # implemented. Once that happens, deleting or modifying the # latest item would result in the whole feed getting re-msg'd. # This will prevent that from happening. LOGGER.info( "Skipping older entry: [%s] %s, because %s >= %s", feed.name, entry.title, published_dt, entry_dt) continue # Don't use long reddit urls, use short version entry_link = entry.link if "www.reddit.com/r/" in entry.link: short_url = "https://redd.it/{}" reddit_re= "https://www\.reddit\.com\/r\/.*comments/(.*?)\/" try: entry_link = short_url.format(re.search(reddit_re, entry_link).group(1)) except: LOGGER.debug("Matching reddit url {} failed".format(entry_link)) # create message for new entry message = u"[{0}] {1} - {2}".format( bold(color(feed.name, feed.fg, feed.bg)), bold(entry.title), entry_link) # append update time if it exists, or published time if it doesn't # timestamp = entry_update_dt or entry_dt # if timestamp: # # attempt to get time format from preferences # tformat = bot.db.get_channel_value(feed.channel, 'time_format') # if not tformat and bot.config.has_option('clock', 'time_format'): # tformat = bot.config.clock.time_format # # message += " - {0}".format(timestamp.strftime(tformat or '%F - %T%Z')) # print message bot.msg(feed.channel, message)
def findandreplace(bot, trigger): # Don't bother in PM if trigger.is_privmsg: return # Correcting other person vs self. rnick = Identifier(trigger.group(1) or trigger.nick) search_dict = bot.memory['find_lines'] # only do something if there is conversation to work with if trigger.sender not in search_dict: return if Identifier(rnick) not in search_dict[trigger.sender]: return #TODO rest[0] is find, rest[1] is replace. These should be made variables of #their own at some point. rest = [trigger.group(2), trigger.group(3)] rest[0] = rest[0].replace(r'\/', '/') rest[1] = rest[1].replace(r'\/', '/') me = False # /me command flags = (trigger.group(4) or '') # If g flag is given, replace all. Otherwise, replace once. if 'g' in flags: count = -1 else: count = 1 # repl is a lambda function which performs the substitution. i flag turns # off case sensitivity. re.U turns on unicode replacement. if 'i' in flags: regex = re.compile(re.escape(rest[0]), re.U | re.I) repl = lambda s: re.sub(regex, rest[1], s, count == 1) else: repl = lambda s: s.replace(rest[0], rest[1], count) # Look back through the user's lines in the channel until you find a line # where the replacement works for line in reversed(search_dict[trigger.sender][rnick]): if line.startswith("\x01ACTION"): me = True # /me command line = line[8:] else: me = False new_phrase = repl(line) if new_phrase != line: # we are done break if not new_phrase or new_phrase == line: return # Didn't find anything # Save the new "edited" message. action = (me and '\x01ACTION ') or '' # If /me message, prepend \x01ACTION templist = search_dict[trigger.sender][rnick] templist.append(action + new_phrase) search_dict[trigger.sender][rnick] = templist bot.memory['find_lines'] = search_dict # output if not me: new_phrase = '%s to say: %s' % (bold('meant'), new_phrase) if trigger.group(1): phrase = '%s thinks %s %s' % (trigger.nick, rnick, new_phrase) else: phrase = '%s %s' % (trigger.nick, new_phrase) bot.say(phrase)