Beispiel #1
0
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)
Beispiel #2
0
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)
Beispiel #3
0
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)
Beispiel #4
0
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)
Beispiel #5
0
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)
Beispiel #6
0
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)
Beispiel #7
0
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)
Beispiel #8
0
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)