Example #1
0
    def check_subreddits(self):
        """
        Evaluate new comments from configured subreddits
        """
        lg.debug("> CointipBot::check_subreddits()")

        try:
            # Process comments until old comment reached

            # Get last_processed_comment_time if necessary
            if not hasattr(self.conf.reddit, 'last_processed_comment_time') or self.conf.reddit.last_processed_comment_time <= 0:
                self.conf.reddit.last_processed_comment_time = ctb_misc.get_value(conn=self.db, param0='last_processed_comment_time')
            updated_last_processed_time = 0

            # Fetch comments from subreddits
            my_comments = ctb_misc.praw_call(self.conf.reddit.subreddits.get_comments, limit=self.conf.reddit.scan.batch_limit)

            # Match each comment against regex
            counter = 0
            for c in my_comments:
                # Stop processing if old comment reached
                #lg.debug("check_subreddits(): c.id %s from %s, %s <= %s", c.id, c.subreddit.display_name, c.created_utc, self.conf.reddit.last_processed_comment_time)
                if c.created_utc <= self.conf.reddit.last_processed_comment_time:
                    lg.debug("CointipBot::check_subreddits(): old comment reached")
                    break
                counter += 1
                if c.created_utc > updated_last_processed_time:
                    updated_last_processed_time = c.created_utc

                # Ignore duplicate comments (may happen when bot is restarted)
                if ctb_action.check_action(msg_id=c.id, ctb=self):
                    lg.warning("CointipBot::check_inbox(): duplicate action detected (comment.id %s), ignoring", c.id)
                    continue

                # Ignore comments from banned users
                if c.author and self.conf.reddit.banned_users:
                    lg.debug("CointipBot::check_subreddits(): checking whether user '%s' is banned..." % c.author)
                    u = ctb_user.CtbUser(name = c.author.name, redditobj = c.author, ctb = self)
                    if u.banned:
                        lg.info("CointipBot::check_subreddits(): ignoring banned user '%s'" % c.author)
                        continue

                # Attempt to evaluate comment
                action = ctb_action.eval_comment(c, self)

                # Perform action, if found
                if action:
                    lg.info("CointipBot::check_subreddits(): %s from %s (%s)", action.type, action.u_from.name, c.id)
                    lg.debug("CointipBot::check_subreddits(): comment body: <%s>", c.body)
                    action.do()
                else:
                    lg.info("CointipBot::check_subreddits(): no match")

            lg.debug("CointipBot::check_subreddits(): %s comments processed", counter)
            if counter >= self.conf.reddit.scan.batch_limit - 1:
                lg.warning("CointipBot::check_subreddits(): conf.reddit.scan.batch_limit (%s) was not large enough to process all comments", self.conf.reddit.scan.batch_limit)

        except (HTTPError, RateLimitExceeded, timeout) as e:
            lg.warning("CointipBot::check_subreddits(): Reddit is down (%s), sleeping", e)
            time.sleep(self.conf.misc.times.sleep_seconds)
            pass
        except Exception as e:
            lg.error("CointipBot::check_subreddits(): coudln't fetch comments: %s", e)
            raise

        # Save updated last_processed_time value
        if updated_last_processed_time > 0:
            self.conf.reddit.last_processed_comment_time = updated_last_processed_time
        ctb_misc.set_value(conn=self.db, param0='last_processed_comment_time', value0=self.conf.reddit.last_processed_comment_time)

        lg.debug("< CointipBot::check_subreddits() DONE")
        return True
Example #2
0
    def check_inbox(self):
        """
        Evaluate new messages in inbox
        """
        lg.debug('> CointipBot::check_inbox()')

        try:

            # Try to fetch some messages
            messages = list(ctb_misc.praw_call(self.reddit.get_unread, limit=self.conf.reddit.scan.batch_limit))
            messages.reverse()

            # Process messages
            for m in messages:
                # Sometimes messages don't have an author (such as 'you are banned from' message)
                if not m.author:
                    lg.info("CointipBot::check_inbox(): ignoring msg with no author")
                    ctb_misc.praw_call(m.mark_as_read)
                    continue

                lg.info("CointipBot::check_inbox(): %s from %s", "comment" if m.was_comment else "message", m.author.name)

                # Ignore duplicate messages (sometimes Reddit fails to mark messages as read)
                if ctb_action.check_action(msg_id=m.id, ctb=self):
                    lg.warning("CointipBot::check_inbox(): duplicate action detected (msg.id %s), ignoring", m.id)
                    ctb_misc.praw_call(m.mark_as_read)
                    continue

                # Ignore self messages
                if m.author and m.author.name.lower() == self.conf.reddit.auth.user.lower():
                    lg.debug("CointipBot::check_inbox(): ignoring message from self")
                    ctb_misc.praw_call(m.mark_as_read)
                    continue

                # Ignore messages from banned users
                if m.author and self.conf.reddit.banned_users:
                    lg.debug("CointipBot::check_inbox(): checking whether user '%s' is banned..." % m.author)
                    u = ctb_user.CtbUser(name = m.author.name, redditobj = m.author, ctb = self)
                    if u.banned:
                        lg.info("CointipBot::check_inbox(): ignoring banned user '%s'" % m.author)
                        ctb_misc.praw_call(m.mark_as_read)
                        continue

                action = None
                if m.was_comment:
                    # Attempt to evaluate as comment / mention
                    action = ctb_action.eval_comment(m, self)
                else:
                    # Attempt to evaluate as inbox message
                    action = ctb_action.eval_message(m, self)

                # Perform action, if found
                if action:
                    lg.info("CointipBot::check_inbox(): %s from %s (m.id %s)", action.type, action.u_from.name, m.id)
                    lg.debug("CointipBot::check_inbox(): message body: <%s>", m.body)
                    action.do()
                else:
                    lg.info("CointipBot::check_inbox(): no match")
                    if self.conf.reddit.messages.sorry and not m.subject in ['post reply', 'comment reply']:
                        user = ctb_user.CtbUser(name=m.author.name, redditobj=m.author, ctb=self)
                        tpl = self.jenv.get_template('didnt-understand.tpl')
                        msg = tpl.render(user_from=user.name, what='comment' if m.was_comment else 'message', source_link=m.permalink if hasattr(m, 'permalink') else None, ctb=self)
                        lg.debug("CointipBot::check_inbox(): %s", msg)
                        user.tell(subj='What?', msg=msg, msgobj=m if not m.was_comment else None)

                # Mark message as read
                ctb_misc.praw_call(m.mark_as_read)

        except (HTTPError, ConnectionError, Timeout, timeout) as e:
            lg.warning("CointipBot::check_inbox(): Reddit is down (%s), sleeping", e)
            time.sleep(self.conf.misc.times.sleep_seconds)
            pass
        except RateLimitExceeded as e:
             lg.warning("CointipBot::check_inbox(): rate limit exceeded, sleeping for %s seconds", e.sleep_time) 
             time.sleep(e.sleep_time)
             time.sleep(1)
             pass
        except Exception as e:
            lg.error("CointipBot::check_inbox(): %s", e)
            raise

        lg.debug("< CointipBot::check_inbox() DONE")
        return True
Example #3
0
    def check_subreddits(self):
        """
        Evaluate new comments from configured subreddits
        """
        lg.debug("> CointipBot::check_subreddits()")

        try:
            # Process comments until old comment reached

            # Get last_processed_comment_time if necessary
            if (not hasattr(self.conf.reddit, "last_processed_comment_time")
                    or self.conf.reddit.last_processed_comment_time <= 0):
                self.conf.reddit.last_processed_comment_time = ctb_misc.get_value(
                    conn=self.db, param0="last_processed_comment_time")
            updated_last_processed_time = 0

            # Fetch comments from subreddits
            my_comments = ctb_misc.praw_call(
                self.conf.reddit.subreddits.get_comments,
                limit=self.conf.reddit.scan.batch_limit,
            )

            # Match each comment against regex
            counter = 0
            for c in my_comments:
                # Stop processing if old comment reached
                # lg.debug("check_subreddits(): c.id %s from %s, %s <= %s", c.id, c.subreddit.display_name, c.created_utc, self.conf.reddit.last_processed_comment_time)
                if c.created_utc <= self.conf.reddit.last_processed_comment_time:
                    lg.debug(
                        "CointipBot::check_subreddits(): old comment reached")
                    break
                counter += 1
                if c.created_utc > updated_last_processed_time:
                    updated_last_processed_time = c.created_utc

                # Ignore duplicate comments (may happen when bot is restarted)
                if ctb_action.check_action(msg_id=c.id, ctb=self):
                    lg.warning(
                        "CointipBot::check_inbox(): duplicate action detected (comment.id %s), ignoring",
                        c.id,
                    )
                    continue

                # Ignore comments from banned users
                if c.author and self.conf.reddit.banned_users:
                    lg.debug(
                        "CointipBot::check_subreddits(): checking whether user '%s' is banned..."
                        % c.author)
                    u = ctb_user.CtbUser(name=c.author.name,
                                         redditobj=c.author,
                                         ctb=self)
                    if u.banned:
                        lg.info(
                            "CointipBot::check_subreddits(): ignoring banned user '%s'"
                            % c.author)
                        continue

                # Attempt to evaluate comment
                action = ctb_action.eval_comment(c, self)

                # Perform action, if found
                if action:
                    lg.info(
                        "CointipBot::check_subreddits(): %s from %s (%s)",
                        action.type,
                        action.u_from.name,
                        c.id,
                    )
                    lg.debug(
                        "CointipBot::check_subreddits(): comment body: <%s>",
                        c.body)
                    action.do()
                else:
                    lg.info("CointipBot::check_subreddits(): no match")

            lg.debug("CointipBot::check_subreddits(): %s comments processed",
                     counter)
            if counter >= self.conf.reddit.scan.batch_limit - 1:
                lg.warning(
                    "CointipBot::check_subreddits(): conf.reddit.scan.batch_limit (%s) was not large enough to process all comments",
                    self.conf.reddit.scan.batch_limit,
                )

        except (HTTPError, RateLimitExceeded, timeout) as e:
            lg.warning(
                "CointipBot::check_subreddits(): Reddit is down (%s), sleeping",
                e)
            time.sleep(self.conf.misc.times.sleep_seconds)
            pass
        except Exception as e:
            lg.error(
                "CointipBot::check_subreddits(): coudln't fetch comments: %s",
                e)
            raise

        # Save updated last_processed_time value
        if updated_last_processed_time > 0:
            self.conf.reddit.last_processed_comment_time = updated_last_processed_time
        ctb_misc.set_value(
            conn=self.db,
            param0="last_processed_comment_time",
            value0=self.conf.reddit.last_processed_comment_time,
        )

        lg.debug("< CointipBot::check_subreddits() DONE")
        return True
Example #4
0
    def check_inbox(self):
        """
        Evaluate new messages in inbox
        """
        lg.debug("> CointipBot::check_inbox()")

        try:

            # Try to fetch some messages
            messages = list(
                ctb_misc.praw_call(self.reddit.get_unread,
                                   limit=self.conf.reddit.scan.batch_limit))
            messages.reverse()

            # Process messages
            for m in messages:
                # Sometimes messages don't have an author (such as 'you are banned from' message)
                if not m.author:
                    lg.info(
                        "CointipBot::check_inbox(): ignoring msg with no author"
                    )
                    ctb_misc.praw_call(m.mark_as_read)
                    continue

                lg.info(
                    "CointipBot::check_inbox(): %s from %s",
                    "comment" if m.was_comment else "message",
                    m.author.name,
                )

                # Ignore duplicate messages (sometimes Reddit fails to mark messages as read)
                if ctb_action.check_action(msg_id=m.id, ctb=self):
                    lg.warning(
                        "CointipBot::check_inbox(): duplicate action detected (msg.id %s), ignoring",
                        m.id,
                    )
                    ctb_misc.praw_call(m.mark_as_read)
                    continue

                # Ignore self messages
                if (m.author and m.author.name.lower()
                        == self.conf.reddit.auth.user.lower()):
                    lg.debug(
                        "CointipBot::check_inbox(): ignoring message from self"
                    )
                    ctb_misc.praw_call(m.mark_as_read)
                    continue

                # Ignore messages from banned users
                if m.author and self.conf.reddit.banned_users:
                    lg.debug(
                        "CointipBot::check_inbox(): checking whether user '%s' is banned..."
                        % m.author)
                    u = ctb_user.CtbUser(name=m.author.name,
                                         redditobj=m.author,
                                         ctb=self)
                    if u.banned:
                        lg.info(
                            "CointipBot::check_inbox(): ignoring banned user '%s'"
                            % m.author)
                        ctb_misc.praw_call(m.mark_as_read)
                        continue

                action = None
                if m.was_comment:
                    # Attempt to evaluate as comment / mention
                    action = ctb_action.eval_comment(m, self)
                else:
                    # Attempt to evaluate as inbox message
                    action = ctb_action.eval_message(m, self)

                # Perform action, if found
                if action:
                    lg.info(
                        "CointipBot::check_inbox(): %s from %s (m.id %s)",
                        action.type,
                        action.u_from.name,
                        m.id,
                    )
                    lg.debug("CointipBot::check_inbox(): message body: <%s>",
                             m.body)
                    action.do()
                else:
                    lg.info("CointipBot::check_inbox(): no match")
                    if self.conf.reddit.messages.sorry and m.subject not in [
                            "post reply",
                            "comment reply",
                    ]:
                        user = ctb_user.CtbUser(name=m.author.name,
                                                redditobj=m.author,
                                                ctb=self)
                        tpl = self.jenv.get_template("didnt-understand.tpl")
                        msg = tpl.render(
                            user_from=user.name,
                            what="comment" if m.was_comment else "message",
                            source_link=ctb_misc.permalink(m),
                            ctb=self,
                        )
                        lg.debug("CointipBot::check_inbox(): %s", msg)
                        user.tell(
                            subj="What?",
                            msg=msg,
                            msgobj=m if not m.was_comment else None,
                        )

                # Mark message as read
                ctb_misc.praw_call(m.mark_as_read)

        except (HTTPError, ConnectionError, Timeout, RateLimitExceeded,
                timeout) as e:
            lg.warning(
                "CointipBot::check_inbox(): Reddit is down (%s), sleeping", e)
            time.sleep(self.conf.misc.times.sleep_seconds)
            pass
        except Exception as e:
            lg.exception("CointipBot::check_inbox(): %s", e)
            # raise
        # ^ what do we say to death?
        # 	    lg.error("^not today (^skipped raise)")
        #            raise #not sure if right number of spaces; try to quit on error
        # for now, quitting on error because of dealing with on-going issues; switch
        # back when stable

        lg.debug("< CointipBot::check_inbox() DONE")
        return True
Example #5
0
    def check_inbox(self):
        """
        Evaluate new messages in inbox
        """
        lg.debug('> CointipBot::check_inbox()')

        try:

            # Try to fetch some messages
            messages = list(
                ctb_misc.praw_call(self.reddit.get_unread,
                                   limit=self.conf.reddit.scan.batch_limit))
            messages.reverse()

            # Process messages
            for m in messages:
                # Sometimes messages don't have an author (such as 'you are banned from' message)
                if not m.author:
                    lg.info(
                        "CointipBot::check_inbox(): ignoring msg with no author"
                    )
                    ctb_misc.praw_call(m.mark_as_read)
                    continue

                lg.info("CointipBot::check_inbox(): %s from %s",
                        "comment" if m.was_comment else "message",
                        m.author.name)

                # Ignore duplicate messages (sometimes Reddit fails to mark messages as read)
                if ctb_action.check_action(msg_id=m.id, ctb=self):
                    lg.warning(
                        "CointipBot::check_inbox(): duplicate action detected (msg.id %s), ignoring",
                        m.id)
                    ctb_misc.praw_call(m.mark_as_read)
                    continue

                # Ignore self messages
                if m.author and m.author.name.lower(
                ) == self.conf.reddit.auth.user.lower():
                    lg.debug(
                        "CointipBot::check_inbox(): ignoring message from self"
                    )
                    ctb_misc.praw_call(m.mark_as_read)
                    continue

                # Ignore messages from banned users
                if m.author and self.conf.reddit.banned_users:
                    lg.debug(
                        "CointipBot::check_inbox(): checking whether user '%s' is banned..."
                        % m.author)
                    u = ctb_user.CtbUser(name=m.author.name,
                                         redditobj=m.author,
                                         ctb=self)
                    if u.banned:
                        lg.info(
                            "CointipBot::check_inbox(): ignoring banned user '%s'"
                            % m.author)
                        ctb_misc.praw_call(m.mark_as_read)
                        continue

                action = None
                if m.was_comment:
                    # Attempt to evaluate as comment / mention
                    action = ctb_action.eval_comment(m, self)
                else:
                    # Attempt to evaluate as inbox message
                    action = ctb_action.eval_message(m, self)

                # Perform action, if found
                if action:
                    lg.info("CointipBot::check_inbox(): %s from %s (m.id %s)",
                            action.type, action.u_from.name, m.id)
                    lg.debug("CointipBot::check_inbox(): message body: <%s>",
                             m.body)
                    action.do()
                else:
                    lg.info("CointipBot::check_inbox(): no match")
                    if self.conf.reddit.messages.sorry and not m.subject in [
                            'post reply', 'comment reply'
                    ]:
                        user = ctb_user.CtbUser(name=m.author.name,
                                                redditobj=m.author,
                                                ctb=self)
                        tpl = self.jenv.get_template('didnt-understand.tpl')
                        msg = tpl.render(
                            user_from=user.name,
                            what='comment' if m.was_comment else 'message',
                            source_link=m.permalink
                            if hasattr(m, 'permalink') else None,
                            ctb=self)
                        lg.debug("CointipBot::check_inbox(): %s", msg)
                        user.tell(subj='What?',
                                  msg=msg,
                                  msgobj=m if not m.was_comment else None)

                # Mark message as read
                ctb_misc.praw_call(m.mark_as_read)

        except (HTTPError, ConnectionError, Timeout, timeout) as e:
            lg.warning(
                "CointipBot::check_inbox(): Reddit is down (%s), sleeping", e)
            time.sleep(self.conf.misc.times.sleep_seconds)
            pass
        except RateLimitExceeded as e:
            lg.warning(
                "CointipBot::check_inbox(): rate limit exceeded, sleeping for %s seconds",
                e.sleep_time)
            time.sleep(e.sleep_time)
            time.sleep(1)
            pass
        except Exception as e:
            lg.error("CointipBot::check_inbox(): %s", e)
            raise

        lg.debug("< CointipBot::check_inbox() DONE")
        return True
Example #6
0
    def check_mentions(self, ctb):
        """
        Evaluate new comments from self.configured subreddits
        """
        if not (self.conf.scan.my_subreddits
                or hasattr(self.conf.scan, 'these_subreddits')):
            lg.debug(
                "> RedditNetwork::check_mentions(): nothing to check. return now."
            )
            return True

        lg.debug("> RedditNetwork::check_mentions()")
        updated_last_processed_time = 0

        try:
            # Process comments until old comment reached
            # Get last_processed_comment_time if necessary
            if not hasattr(self.conf, 'last_processed_comment_time'
                           ) or self.conf.last_processed_comment_time <= 0:
                self.conf.last_processed_comment_time = ctb_misc.get_value(
                    conn=self.db, param0='last_processed_comment_time')

            # Fetch comments from subreddits
            my_comments = self.praw_call(self.conf.subreddits.comments,
                                         limit=self.conf.scan.batch_limit)

            # Match each comment against regex
            counter = 0
            for c in my_comments:
                # Stop processing if old comment reached
                #lg.debug("check_mentions(): c.id %s from %s, %s <= %s", c.id, c.subreddit.display_name, c.created_utc, self.conf.last_processed_comment_time)
                if c.created_utc <= self.conf.last_processed_comment_time:
                    lg.debug(
                        "RedditNetwork::check_mentions(): old comment reached")
                    break
                counter += 1
                if c.created_utc > updated_last_processed_time:
                    updated_last_processed_time = c.created_utc

                # Ignore duplicate comments (may happen when bot is restarted)
                if ctb_action.check_action(msg_id=c.id, ctb=ctb):
                    lg.warning(
                        "RedditNetwork::check_inbox(): duplicate action detected (comment.id %s), ignoring",
                        c.id)
                    continue

                # Ignore comments from banned users
                if c.author and self.conf.banned_users:
                    lg.debug(
                        "RedditNetwork::check_mentions(): checking whether user '%s' is banned..."
                        % c.author)
                    if self.is_user_banned(c.author.name):
                        lg.info(
                            "RedditNetwork::check_mentions(): ignoring banned user '%s'"
                            % c.author)
                        continue

                # Attempt to evaluate comment
                action = ctb_action.eval_reddit_comment(c, ctb)

                # Perform action, if found
                if action:
                    lg.info("RedditNetwork::check_mentions(): %s from %s (%s)",
                            action.type, action.u_from.name, c.id)
                    lg.debug(
                        "RedditNetwork::check_mentions(): comment body: <%s>",
                        c.body)
                    action.do()
                else:
                    lg.info("RedditNetwork::check_mentions(): no match")

            lg.debug("RedditNetwork::check_mentions(): %s comments processed",
                     counter)
            if counter >= self.conf.scan.batch_limit - 1:
                lg.warning(
                    "RedditNetwork::check_mentions(): conf.network.scan.batch_limit (%s) was not "
                    + "large enough to process all comments",
                    self.conf.scan.batch_limit)

        except (HTTPError, ClientException, socket.timeout) as e:
            lg.warning(
                "RedditNetwork::check_mentions(): Reddit is down (%s), sleeping",
                e)
            time.sleep(self.ctb.conf.misc.times.sleep_seconds)
            pass
        except Exception as e:
            lg.error(
                "RedditNetwork::check_mentions(): coudln't fetch comments: %s",
                e)
            raise

        # Save updated last_processed_time value
        if updated_last_processed_time > 0:
            self.conf.last_processed_comment_time = updated_last_processed_time
        ctb_misc.set_value(conn=self.db,
                           param0='last_processed_comment_time',
                           value0=self.conf.last_processed_comment_time)

        lg.debug("< RedditNetwork::check_mentions() DONE")
        return True