def _parse_direct_message(self, event_data):

        recipient_id = event_data['message_create']['target']['recipient_id']
        sender_id = event_data['message_create']['sender_id']
        sender_screen_name = self.get_user_name(sender_id)
        message_text = event_data['message_create']['message_data']['text']

        msg = {
            'created_utc': self._timestamp_utc_now(),
            'author': {
                'name': sender_screen_name
            },
            'recipient_id': sender_id,
            'type': 'direct_message'
        }
        msg['id'] = event_data['id'] + str(
            msg['created_utc'])[(30 - len(event_data['id'])):]

        text = event_data['message_create']['message_data']['text']
        msg['body'] = text.replace('@' + self.user, '').strip()
        lg.debug(msg)

        action = ctb_action.eval_message(ctb_misc.DotDict(msg), self.ctb)

        return action
Example #2
0
    def on_pubmsg(self, c, e):
        ch = e.target
        nick = e.source.nick
        text = ' '.join(e.arguments)

        lg.debug('IRCChatBot::on_pubmsg(): %s on %s: %s', nick, ch, text)

        # ignore my own message
        if nick == self.username:
            return None

        # commands must start with +
        if text[0] != '+':
            return None

        now = datetime.utcnow().replace(tzinfo=pytz.utc)
        msg = {
            'created_utc': calendar.timegm(now.utctimetuple()),
            'author': {
                'name': nick
            }
        }
        msg['id'] = str(msg['created_utc'])
        msg['body'] = text
        print(msg)

        action = ctb_action.eval_message(ctb_misc.DotDict(msg), self.ctb)
        if action:
            lg.info("IRCChatBot::on_pubmsg(): %s from %s", action.type,
                    action.u_from.name)
            lg.debug("IRCChatBot::on_pubmsg(): comment body: <%s>",
                     action.msg.body)
            action.do()
    def _parse_mention(self, data):
        # ignore retweets
        if 'retweeted_status' in data:
            return None

        author_name = data['user']['screen_name']
        if author_name == self.user or '@' + self.user not in data['text']:
            return None

        # we do allow the bot to issue commands
        msg = {
            'created_utc': self._timestamp_utc_now(),
            'author': {
                'name': author_name
            },
            'type': 'mention'
        }
        msg['id'] = data['id_str'] + str(
            msg['created_utc'])[(30 - len(data['id_str'])):]

        text = data['text']
        msg['body'] = text.replace('@' + self.user, '').strip()
        print(msg)

        action = ctb_action.eval_message(ctb_misc.DotDict(msg), self.ctb)
        return action
    def follow_followers(self):
        lg.debug('TwitterStreamer::follow_followers(): started')

        # only get the latest followers but this relies on Twitter returns the latest followers first
        followers = []
        for fid in self.conn.cursor(self.conn.get_followers_ids, count=5000):
            followers.append(fid)

        friends = []
        for fid in self.conn.cursor(self.conn.get_friends_ids, count=5000):
            friends.append(fid)

        pending = []
        for fid in self.conn.cursor(self.conn.get_outgoing_friendship_ids):
            pending.append(fid)

        lg.debug(
            'TwitterStreamer::follow_followers(): looking for new followers')
        to_follow = [
            f for f in followers[:100] if f not in friends and f not in pending
        ]
        lg.debug(
            'TwitterStreamer::follow_followers(): about to send follow request'
        )

        # only follow 10 at a time
        actions = []
        for user_id in to_follow[:10]:
            try:
                resp = self.conn.create_friendship(user_id=user_id)
                time.sleep(1)
            except TwythonError as e:
                # either really failed (e.g. sent request before) or already friends
                lg.warning(
                    "TwitterStreamer::follow_followers: failed to follow user %s: %s",
                    user_id, e.msg)
                continue
            else:
                lg.debug(
                    'TwitterStreamer::follow_followers(): just sent request to follow user %s',
                    user_id)

            msg = {
                'id': str(user_id),
                'created_utc': self._timestamp_utc_now(),
                'author': {
                    'name': resp['screen_name']
                },
                'body': '+register',
                'type': 'mention'
            }
            # make the msg id unique
            msg['id'] += ('@' + str(msg['created_utc']))

            action = ctb_action.eval_message(ctb_misc.DotDict(msg), self.ctb)
            actions.append(action)

        return actions
Example #5
0
    def _parse_follow(self, event_data):
        event = event_data['event']
        source_id = event['source']['id']
        source_name = event['source']['screen_name']

        msg = {'id': source_id,
               'created_utc': self._timestamp_utc_now(),
               'author': {'name': source_name},
               'body': '+register',
               'type': 'direct_message'}
        # make the msg id unique
        msg['id'] += ('@' + str(msg['created_utc']))

        lg.debug(msg)
        action = ctb_action.eval_message(ctb_misc.DotDict(msg), self.ctb)
        return action
Example #6
0
    def _parse_mention(self, event_data):

        event = event_data['event']
        author_name = event['user']['screen_name']

        # we do allow the bot to issue commands
        msg = {'created_utc': self._timestamp_utc_now(),
               'author': {'name': author_name},
               'type': 'mention'}
        msg['id'] = event['id_str'] + str(msg['created_utc'])[(30-len(event['id_str'])):]

        text = event['text']
        msg['body'] = text.replace('@' + self.username, '').strip()
        lg.debug(msg)

        action = ctb_action.eval_message(ctb_misc.DotDict(msg), self.ctb)
        return action
    def _parse_direct_msg(self, data):
        # ignore direct message from the bot itself
        author_name = data['sender']['screen_name']
        if author_name == self.username:
            return None

        msg = {
            'created_utc': self._timestamp_utc_now(),
            'author': {
                'name': author_name
            },
            'type': 'direct_message'
        }
        msg['id'] = data['id_str'] + str(
            msg['created_utc'])[(30 - len(data['id_str'])):]

        text = data['text']
        msg['body'] = text.replace('@' + self.username, '').strip()
        print(msg)

        action = ctb_action.eval_message(ctb_misc.DotDict(msg), self.ctb)
        return action
Example #8
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 #9
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 #10
0
    def check_inbox(self):
        """
		Evaluate new messages until checkpoint is reached
		"""
        lg.debug('> CointipBot::check_inbox()')
        last_read = None
        running = True

        while running:
            try:
                # fetch all the messages since last read
                lg.debug("querying all messages since %s", last_read)
                my_params = {'after': last_read}
                messages = list(
                    ctb_misc.praw_call(self.reddit.get_inbox,
                                       params=my_params))
                # Process messages
                for m in messages:
                    last_read = m.fullname
                    lg.debug("Checking %s", last_read)

                    #check for checkpoint
                    if self.check_id(thingid=last_read):
                        lg.debug("Hit checkpoint")
                        running = False
                        break

                    # 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"
                        )
                        self.mark_as_processed(thingid=m.fullname)
                        continue

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

                    # 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"
                        )
                        self.mark_as_processed(thingid=m.fullname)
                        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)
                            self.mark_as_processed(thingid=m.fullname)
                            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)

                    # load into database
                    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.save_pending(state="pending")
                    else:
                        lg.info(
                            "CointipBot::check_inbox(): no match ... message body: <%s>",
                            m.body)
                        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
                    self.mark_as_processed(thingid=m.fullname)

            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.error("CointipBot::check_inbox(): %s", e)
                raise

        lg.debug("< CointipBot::check_inbox() DONE")
        return True
Example #11
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