def __info(self, author, subject, text):
     try:
         limit = 10
         #first find a limit if it exists
         match = self.limit_match.search(subject)
         if match:
             limit = int(match.group(1))
         #we must figure out the case
         if self.list_command.search(subject):
             return self.__info_list(author, subject, text)
         elif self.channel_command.search(subject):
             return self.__info_channels(author, subject, text, limit)
         elif self.user_command.search(subject):
             return self.__info_user(author, subject, text, limit)
         else:
             return Actions.send_message(self.praw,
                                         author,
                                         u'Message text not recognized',
                                         u'Message w/ \n'
                                         u'subject: {}\n'.format(subject) +
                                         u'and body: {}\n'.format(text) +
                                         u'not recognized, please consult documentation or help.')
     except Exception as e:
         logging.exception(e)
         Actions.send_message(self.praw,
                              author, u'Re: {}'.format(subject),
                              u'An error occured processing the following text, please file a bug report with'
                              u' /u/arghdos:  \n{}'.format(text))
 def update_mods(self, author=None):
     """
     Update the internal mod-list (who can execute queries)
     :param author: if specified, the bot will respond to this user to let them know success/failure
     :return: None
     """
     try:
         mlist = [mod.name for mod in Actions.get_mods(self.praw, self.sub)]
         if mlist is None or not len(mlist):
             return False
         # only update if it's valid
         self.mod_list = mlist
         self.last_mod_update = datetime.datetime.now()
         if author is not None:
             Actions.send_message(self.praw, author, u"RE: Modlist update", u"Success!")
         return True
     except Exception, e:
         if author is not None:
             Actions.send_message(self.praw, author, u"RE: Modlist update",
                                 u"Error encountered, please try again later.")
         logging.error(u"Could not update moderator list!")
         self.log_error()
         if __debug__:
             logging.exception(e)
         return False
    def __info_user(self, author, subject, text, limit):
        # check that we have text
        lines = [l.strip() for l in self.line_splitter.split(text) if l is not None and len(l.strip())]
        if not len(lines):
            Actions.send_message(self.praw, author, u"RE: info user",
                                 u"No users specified in text:  \n{}".format(text))
            return False

        invalid_users = []
        valid_users = []
        #now go through the lines and make sure they're all usernames
        for line in lines:
            match = self.user_name_match.search(line)
            if not match:
                invalid_users.append(line)
            else:
                valid_users.append(match.group(1))

        if not len(valid_users):
            if len(invalid_users):
                message = u'The following were not recognized as usernames:  \n{}'.format(u', '.join(invalid_users))
            else:
                message = u"No users specified in text: ".format(text)
            Actions.send_message(self.praw, author, u"RE: info user", message)
            return False

        valid_users = list(set(valid_users))
        return_string = self.__create_table((u'Date',
                                             u'Link', u'Submitter', u'Channel', u'Domain', u'Deleted', u'Exception'))
        #with our list of usernames, query DB for submissions
        with DataBaseWrapper(self.owner.database_file, False) as db:
            for user in valid_users:
                #val is (short_url, channel_id, domain, date_added, processed, exception
                val = db.get_reddit(submitter=user, return_channel_id=True, return_domain=True, return_processed=True,
                                    return_exception=True, sort_by_new=True, limit=limit, return_dateadded=True)
                if val is not None and len(val):
                    for submission in val:
                        return_string += self.__table_entry((
                            str(submission[3]),
                            u'http://redd.it/{}'.format(submission[0][submission[0].index('t3_')+ 3:]),
                            user,
                            submission[1], submission[2],
                            u'True' if submission[4] == 1 else u'False',
                            u'True' if submission[5] == 0 and submission[4] == 1 else u'False'))
                else:
                   return_string += self.__table_entry((u'Not Found', user, u'N/A', u'N/A', u'N/A', u'N/A'))
        if invalid_users:
            return_string += u'\n\n'
            return_string += u"The following were not recognized as users:\n"
            return_string += u'\n'.join(invalid_users)

        return_string += u'\n\n'
        return_string += u'Note: Deletions and Exceptions are processed every {:.1} day(s),'.format(
                         self.policy.Historial_Scan_Period / (24.0 * 60.0 * 60.0)) + \
                         u' and thus may not be updated within that time window.'

        return Actions.send_message(self.praw, author, u'Re: User Info query', return_string)
Пример #4
0
def test_send_message(reddit, credentials):
    if a.send_message(reddit, credentials['ALTUSER'], "test", "testmessage"):
        print "Test Message Send: Passed"
        return True
    else:
        print "Test Message Send: Failed"
        return False
    def process_message(self, message):
        """
        Handles the processing of unread messages
        :param message: the message to process
        """
        result = None
        # valid author check
        if message.author and any(name == message.author.name for name in self.mod_list) and not self.is_cached(message.id):
            subject = message.subject
            text = message.body
            # check that it matches one of the basic commands
            matches = [bc for bc in self.base_commands if bc.search(subject)]
            if len(matches) == 1:
                # take care of add /removes
                if matches[0] == self.add_command:
                    self.__add_remove(message.author.name, subject, text, True)
                elif matches[0] == self.remove_command:
                    self.__add_remove(message.author.name, subject, text, False)
                # update mods
                elif matches[0] == self.update_command:
                    self.update_mods(message.author.name)
                # print query
                elif matches[0] == self.info_command:
                    result = self.__info(message.author.name, subject, text)
                # help query
                elif matches[0] == self.help_command:
                    Actions.send_message(self.praw, message.author.name, u"RE:{}".format(message.subject),
                                         self.doc_string)

            if len(matches) != 1:
                Actions.send_message(self.praw, message.author.name, u"RE:{}".format(message.subject),
                                     u"Sorry, I did not recognize your query.  \n".format(text) + self.short_doc_string)

        self.message_cache.append(message.id)
        # don't need to see this again
        message.mark_read()
        return result
    def __add_remove(self, author, subject, text, add):
        """
        add/remove a list of entries from the black/whitelist

        :param author: the mod who initiated this query
        :param subject: the subject line of the message
        :param text: the text of the message
        :param add: a boolean indicating whether this is an addition or removal
        """

        # get black/whitelist
        blacklist = None
        result = self.blist_command.search(subject)
        if result:
            blacklist = True
        result = self.wlist_command.search(subject)
        if result:
            blacklist = False
        if blacklist is None:
            Actions.send_message(self.praw, author, u"RE: Black/whitelist add/removal", \
                                 u"Could not determine blacklist/whitelist from subject line  \n" \
                                 u"Subject: {}".format(subject))
            return False

        force_flag = self.force.search(subject) is not None

        lines = [l.strip() for l in self.line_splitter.split(text) if l and len(l.strip())]
        matches = [self.quote_match.match(l) for l in lines]
        matches = [m for m in matches if m]
        if len(matches) and len(matches) == len(lines) - 1:
            url_list = False
        elif not len(matches) and any(self.url_regex.match(l) for l in lines):
            url_list = True
        else:
            Actions.send_message(self.praw, author, u"RE: {}list {}".format(u"black" if blacklist else u"white", \
                                                                            u"addition" if add else u"removal"), \
                                 u"Could not determine format of request.  For an id list, the first line must " \
                                 u"be a domain and all subsequent lines must be followed by comma separated ids in" \
                                 u" quotes.  For a url list, there must be no comma separated ids.")
            return False

        if add and not url_list:
            Actions.send_message(self.praw, author, u"RE: {}list {}".format(u"black" if blacklist else u"white", \
                                                                            u"addition" if add else u"removal"), \
                                 u"Addition of {}list entries by id is no longer supported.  Please add by URL instead"
                                .format(u"black" if blacklist else u"white"))
            return False

        blist = None
        if not url_list:
            # test the first line to get appropriate blacklist
            for b in self.blacklists:
                if b.check_domain(lines[0]):
                    # store b
                    blist = b
                    break

        # now check that we have a blacklist and url_list defined
        if blist is None and not url_list:
            Actions.send_message(self.praw, author, u"RE: {}list {}".format(u"black" if blacklist else u"white", \
                                                                            u"addition" if add else u"removal"),
                                 u"Could not determine valid domain from:  \n{}".format(lines[0]))
            return False

        # check that if we do not have a url list, we indeed have a domain and other entries to add
        if not url_list and len(lines) == 1:
            Actions.send_message(self.praw, author, u"RE: {}list {}".format(u"black" if blacklist else u"white", \
                                                                            u"addition" if add else u"removal"), u"Invalid format detected, must have at least one channel id to {}\
                from {}list for domain {}".format(u"add" if add else u"remove", u"black" if blacklist else u"white", \
                                                  self.lines[0]))
            return False

        entries = lines if url_list else lines[1:]
        invalid_ids = []
        invalid_urls = []
        valid_ids = []
        if not url_list:
            real_entries = []
            # if we have an id list, we have to see if they're comma separated
            for entry in entries:
                val = self.quote_splitter(entry, force=force_flag)
                if isinstance(val, tuple):
                    if force_flag:
                        val = val[0]
                    else:
                        body = u"Warning: potential error(s) in ID list detected, **No action has been taken**.  \n" \
                               u"Unescaped quotes or slashes (or simply malformed input) " \
                               u"has been found in the following entries:    \n\n"
                        body += u"  \n".join(val[1])
                        body += u"  \n  \nIf these entries have been correctly parsed " \
                                u"(note: any escaped characters have not been processed), " \
                                u"please resubmit your last query with the --force flag in the subject line."
                        body += u"  \n  \n**Parsed entries**:  \n"
                        body += u"  \n".join(val[0])
                        Actions.send_message(self.praw, author, u"RE: {}list {}".format(
                            u"black" if blacklist else u"white", u"addition" if add else u"removal"), body)
                        return False
                if val:
                    real_entries.extend([self.__unescape(v) for v in val])
                else:
                    Actions.send_message(self.praw, author, u"RE: {}list {}".format(u"black" if blacklist else u"white" \
                        ), u"Cannot parse quoted identifiers:  \n{}".format(entry))
            # copy back
            entries = real_entries[:]
        else:
            real_entries = []
            for entry in entries:
                if self.url_regex.match(entry):# and Actions.resolve_url(entry):
                    real_entries.append(entry)
                else:
                    invalid_urls.append(entry)
            entries = real_entries[:]

        if url_list:
            found = [False for u in entries]
            for blist in self.blacklists:
                this_list = []
                for i, url in enumerate(entries):
                    if blist.check_domain(url):
                        found[i] = True
                        this_list.append(url)

                if not len(this_list):
                    continue
                if blacklist:
                    if add:
                        bad_urls, bad_ids, good_ids = blist.add_blacklist_urls(this_list, author)
                    else:
                        bad_urls, bad_ids, good_ids = blist.remove_blacklist_urls(this_list, author)
                else:
                    if add:
                        bad_urls, bad_ids, good_ids = blist.add_whitelist_urls(this_list, author)
                    else:
                        bad_urls, bad_ids, good_ids = blist.remove_whitelist_urls(this_list, author)
                invalid_urls += bad_urls
                invalid_ids += [(b, blist.domains[0]) for b in bad_ids]
                valid_ids += [(g, blist.domains[0]) for g in good_ids]
            invalid_urls += [url for i, url in enumerate(entries) if not found[i]]
        else:
            if blacklist:
                if add:
                    #no longer accepted
                    invalid_ids += entries
                    #invalid += blist.add_blacklist(entries)
                else:
                    invalid_ids += blist.add_blacklist(entries)
            else:
                if add:
                    invalid_ids += blist.add_whitelist(entries)
                else:
                    invalid_ids += blist.add_whitelist(entries)
            valid_ids = [(v, lines[0]) for v in entries if not v in invalid_ids]

        invalid_str = u""
        if invalid_ids is not None and len(invalid_ids):
            if url_list:
                invalid_str += u"Failed to add the following ids:  \n"
                invalid_str += u"  \n".join([u"id = {},domain={}".format(inv[0],  inv[1]) for inv in invalid_ids])
            else:
                invalid_str += u"Failed to add the following ids:  \n"
                invalid_str += u"  \n".join([u"id = {}, domain={}".format(inv[0],  lines[0]) for inv in invalid_ids])

        if invalid_urls is not None and len(invalid_urls):
            invalid_str += u"Invalid urls detected:  \n"
            invalid_str += u"  \n".join(invalid_urls)

        retstr = u""
        if valid_ids is not None and len(valid_ids):
            retstr = u"The following channels were successfully {} the {}list  \n" \
                        u"{}".format(u"added to" if add else u"removed from the", u"black" \
                        if blacklist else u"white", u"  \n".join([u"id = {}, domain={}".format(v[0], v[1])
                                                                  for v in valid_ids]))
        if len(invalid_str):
            if len(retstr):
                retstr += u"  \n"
            retstr += invalid_str
        return Actions.send_message(self.praw, author, u"RE: {}list {}".format(u"black" if blacklist else u"white", \
                                                                               u"addition" if add else u"removal"),
                                    retstr)
    def __info_channels(self, author, subject, text, limit):

        #we want to find
        #a table of:
        #   submission, user, channel, domain, strike

        #check that we have text
        lines = [l.strip() for l in self.line_splitter.split(text) if l is not None and len(l.strip())]
        if not len(lines):
            Actions.send_message(self.praw, author, u"RE: info list",
                                 u"No valid channels specified in text:  \n{}".format(text))
            return False

        found_channels = []
        valid_urls = []
        invalid_urls = []
        return_string = u""
        for blacklist in self.blacklists:
            my_lines = [line for line in lines if blacklist.check_domain(line)]
            overlap = [x for x in my_lines if x in valid_urls]
            #if it's already matched, it's bad
            if overlap:
                invalid_urls.extend(overlap)
                valid_urls = [v for v in valid_urls if v not in overlap]
                my_lines = [line for line in my_lines if not line in overlap]
            if not len(my_lines):
                continue
            #if we have data, get the channel ids
            my_channel_info = [blacklist.data.channel_id(url=url) for url in my_lines]
            my_channel_ids = []
            for i, info in enumerate(my_channel_info):
                if info is not None:
                    if not (info[0], blacklist.domains[0]) in found_channels:
                        found_channels.append((info[0], blacklist.domains[0]))
                        my_channel_ids.append(info[0])
                else:
                    valid_urls.remove(my_lines[i])
                    invalid_urls.append(my_lines[i])
            return_string += self.__create_table((u'Date', u'Link'
                                                 , u'Submitter',u'Channel', u'Domain', u'Deleted', u'Exception'))
            #with our list of channel ids, query DB for submissions
            if my_channel_ids:
                with DataBaseWrapper(self.owner.database_file, False) as db:
                    for id in my_channel_ids:
                        #val is (short_url, date, processed, submitter, exception
                        val = db.get_reddit(channel_id=id, domain=blacklist.domains[0],
                                            return_domain=False, return_channel_id=False,
                                            return_processed=True, return_submitter=True,
                                            return_exception=True, sort_by_new=True,
                                            limit=limit, return_dateadded=True)
                        if val is not None and len(val):
                            for submission in val:
                                return_string += self.__table_entry((
                                    str(submission[1]),
                                    u'http://redd.it/{}'.format(submission[0][submission[0].index('t3_')+ 3:]),
                                    submission[3],
                                    id, blacklist.domains[0],
                                    u'True' if submission[2] == 1 else u'False',
                                    u'True' if submission[4] == 0 and submission[2] == 1 else u'False'))
                        else:
                            return_string += self.__table_entry((u'Not Found', u'Not Found', id, blacklist.domains[0],
                                                                u'N/A', u'N/A'))
        invalid_urls.extend([x for x in my_lines if x not in valid_urls])
        if invalid_urls:
            return_string += u'\n\n'
            return_string += u"Channel data for the following urls could not be obtained:\n"
            return_string += u'\n'.join(invalid_urls)

        return_string += u'\n\n'
        return_string += u'Note: Deletions and Exceptions are processed every {:.1} day(s),'.format(
                         self.policy.Historial_Scan_Period / (24.0 * 60.0 * 60.0)) + \
                         u' and thus may not be updated within that time window.'

        return Actions.send_message(self.praw, author, u'Re: Channel Info query', return_string)
    def __info_list(self, author, subject, text):
        # check that we have text
        lines = [l.strip() for l in self.line_splitter.split(text) if l is not None and len(l.strip())]
        if not len(lines):
            Actions.send_message(self.praw, author, u"RE: info list",
                                 u"No channel info specified in text:  \n{}".format(text))
            return False

        blist = []
        myfilter = []
        return_subject = u'Re: Info list'
        return_domains = []
        return_filters = []
        urls = []
        for line in lines:
            domain_match = re.search(r'^domain:\s*([^\n]+)$', line)
            if domain_match:
                potential_domain = domain_match.group(1).strip()
                # get domain
                found = False
                for b in self.blacklists:
                    if b.check_domain(potential_domain):
                        return_domains.append(potential_domain)
                        blist.append(b)
                        found = True
                        break
                if not found:
                    Actions.send_message(self.praw, author, u"RE: info list", u"{} not a valid domain."\
                                         .format(potential_domain))
                    return False
                continue
            filter_match = re.search(r'^filter:\s*([^\n]+)$', line)
            if filter_match:
                the_filter = filter_match.group(1).strip()
                myfilter.append(the_filter)
                return_filters.append(the_filter)
                continue
            Actions.send_message(self.praw, author, u"RE: info list", u"Text not recognized:  \n{}."\
                                         .format(line))
            return False

        if return_domains:
            return_subject += u' w/ domains: {}'.format(u', '.join(return_domains))
        if return_filters:
            return_subject += u' w/ filters: {}'.format(u', '.join(return_filters))

        #if no domain, check all
        if not blist:
            blist = self.blacklists

        results = []
        for blacklist in blist:
            if myfilter:
                for filter in myfilter:
                    b_chann = blacklist.get_blacklisted_channels(filter)
                    w_chann = blacklist.get_whitelisted_channels(filter)

                    if b_chann or w_chann:
                        results.append(u'Channel results for domain {} w/ filter {}:'\
                                       .format(blacklist.domains[0], filter))
                    if b_chann:
                        results.append(u'Blacklisted channels:')
                        results.extend([channel[0] for channel in b_chann])

                    if w_chann:
                        results.append(u'Whitelisted channels:')
                        results.extend([channel[0] for channel in w_chann])

            else:
                b_chann = blacklist.get_blacklisted_channels('')
                w_chann = blacklist.get_whitelisted_channels('')

                if b_chann or w_chann:
                    results.append(u'Channel results for domain {}:'\
                                   .format(blacklist.domains[0]))
                if b_chann:
                    results.append(u'Blacklisted channels:')
                    results.extend([channel[0] for channel in b_chann])

                if w_chann:
                    results.append(u'Whitelisted channels:')
                    results.extend([channel[0] for channel in w_chann])

        if len(results):
            out_str = u"  \n".join(results)
        else:
            out_str = u"No matches found!"
        Actions.send_message(self.praw, author, return_subject, out_str)
        return True