예제 #1
0
파일: modmail.py 프로젝트: zeantsoi/reddit
    def POST_unmute_participant(self, conversation):

        if conversation.is_internal or conversation.is_auto:
            return self.send_error(400, errors.CANT_RESTRICT_MODERATOR)

        sr = Subreddit._by_fullname(conversation.owner_fullname)

        try:
            participant = conversation.get_participant_account()
        except NotFound:
            abort(404, errors.USER_DOESNT_EXIST)

        if not c.user_is_admin:
            if not sr.is_moderator_with_perms(c.user, 'access', 'mail'):
                return self.send_error(403, errors.INVALID_MOD_PERMISSIONS)

        removed = sr.remove_muted(participant)
        if not removed:
            return simplejson.dumps(
                self._convo_to_serializable(conversation, all_messages=True))

        MutedAccountsBySubreddit.unmute(sr, participant)
        ModAction.create(sr, c.user, 'unmuteuser', target=participant)
        conversation.add_action(c.user, 'unmuted', commit=True)

        result = self._get_updated_convo(conversation.id, c.user)
        result['user'] = self._get_modmail_userinfo(conversation, sr=sr)

        return simplejson.dumps(result)
예제 #2
0
파일: modmail.py 프로젝트: zeantsoi/reddit
    def POST_unarchive(self, conversation):
        self._validate_vmodconversation()
        sr = Subreddit._by_fullname(conversation.owner_fullname)
        self._feature_enabled_check(sr)

        if sr.is_moderator_with_perms(c.user, 'mail'):
            if conversation.state != ModmailConversation.STATE['archived']:
                response.status_code = 204
                return

            if conversation.is_internal:
                return self.send_error(
                    422,
                    errors.CONVERSATION_NOT_ARCHIVABLE,
                )

            conversation.add_action(c.user, 'unarchived')
            conversation.set_state('inprogress')
            updated_convo = self._get_updated_convo(conversation.id, c.user)

            g.events.new_modmail_event(
                'ss.modmail_mark_thread',
                conversation,
                mark_type='unarchive',
                request=request,
                context=c,
            )

            return simplejson.dumps(updated_convo)
        else:
            return self.send_error(403, errors.INVALID_MOD_PERMISSIONS)
예제 #3
0
def set_downs():
    sr_counts = count.get_sr_counts()
    names = [k for k, v in sr_counts.iteritems() if v != 0]
    srs = Subreddit._by_fullname(names)
    for name in names:
        sr, c = srs[name], sr_counts[name]
        if c != sr._downs and c > 0:
            sr._downs = max(c, 0)
            sr._commit()
예제 #4
0
파일: sr_pops.py 프로젝트: 1900/reddit
def set_downs():
    sr_counts = count.get_sr_counts()
    names = [k for k, v in sr_counts.iteritems() if v != 0]
    srs = Subreddit._by_fullname(names)
    for name in names:
        sr,c = srs[name], sr_counts[name]
        if c != sr._downs and c > 0:
            sr._downs = max(c, 0)
            sr._commit()
예제 #5
0
파일: modmail.py 프로젝트: zeantsoi/reddit
    def POST_mute_participant(self, conversation):

        if conversation.is_internal or conversation.is_auto:
            return self.send_error(400, errors.CANT_RESTRICT_MODERATOR)

        sr = Subreddit._by_fullname(conversation.owner_fullname)

        try:
            participant = conversation.get_participant_account()
        except NotFound:
            return self.send_error(404, errors.USER_DOESNT_EXIST)

        if not sr.can_mute(c.user, participant):
            return self.send_error(400, errors.CANT_RESTRICT_MODERATOR)

        if not c.user_is_admin:
            if not sr.is_moderator_with_perms(c.user, 'access', 'mail'):
                return self.send_error(403, errors.INVALID_MOD_PERMISSIONS)

            if sr.use_quotas:
                sr_ratelimit = SimpleRateLimit(
                    name="sr_muted_%s" % sr._id36,
                    seconds=g.sr_quota_time,
                    limit=g.sr_muted_quota,
                )
                if not sr_ratelimit.record_and_check():
                    return self.send_error(403, errors.SUBREDDIT_RATELIMIT)

        # Add the mute record but only if successful create the
        # appropriate notifications, this prevents duplicate
        # notifications from being sent
        added = sr.add_muted(participant)

        if not added:
            return simplejson.dumps(
                self._convo_to_serializable(conversation, all_messages=True))

        MutedAccountsBySubreddit.mute(sr, participant, c.user)
        permalink = conversation.make_permalink()

        # Create the appropriate objects to be displayed on the
        # mute moderation log, use the permalink to the new modmail
        # system
        ModAction.create(sr,
                         c.user,
                         'muteuser',
                         target=participant,
                         description=permalink)
        sr.add_rel_note('muted', participant, permalink)

        # Add the muted mod action to the conversation
        conversation.add_action(c.user, 'muted', commit=True)

        result = self._get_updated_convo(conversation.id, c.user)
        result['user'] = self._get_modmail_userinfo(conversation, sr=sr)

        return simplejson.dumps(result)
예제 #6
0
파일: modmail.py 프로젝트: zeantsoi/reddit
    def _try_get_subreddit_access(self, conversation, admin_override=False):
        sr = Subreddit._by_fullname(conversation.owner_fullname)
        self._feature_enabled_check(sr)

        if (not sr.is_moderator_with_perms(c.user, 'mail')
                and not (admin_override and c.user_is_admin)):
            return self.send_error(
                403,
                errors.SUBREDDIT_NO_ACCESS,
            )

        return sr
예제 #7
0
파일: modmail.py 프로젝트: zeantsoi/reddit
    def _get_modmail_userinfo(self, conversation, sr=None):
        if conversation.is_internal:
            raise ValueError('Cannot get userinfo for internal conversations')

        if not sr:
            sr = Subreddit._by_fullname(conversation.owner_fullname)

        # Retrieve the participant associated with the conversation
        try:
            account = conversation.get_participant_account()

            if not account:
                raise ValueError('No account associated with convo')

            permatimeout = (account.in_timeout
                            and account.days_remaining_in_timeout == 0)

            if account._deleted or permatimeout:
                raise ValueError('User info is inaccessible')
        except NotFound:
            raise NotFound('Unable to retrieve conversation participant')

        # Fetch the mute and ban status of the participant as it relates
        # to the subreddit associated with the conversation.
        mute_status = sr.is_muted(account)
        ban_status = sr.is_banned(account)

        # Parse the ban status and retrieve the length of the ban,
        # then output the data into a serialiazable dict
        ban_result = {
            'isBanned': bool(ban_status),
            'reason': '',
            'endDate': None,
            'isPermanent': False
        }

        if ban_status:
            ban_result['reason'] = getattr(ban_status, 'note', '')

            ban_duration = sr.get_tempbans('banned', account.name)
            ban_duration = ban_duration.get(account.name)

            if ban_duration:
                ban_result['endDate'] = ban_duration.isoformat()
            else:
                ban_result['isPermanent'] = True
                ban_result['endDate'] = None

        # Parse the mute status and retrieve the length of the ban,
        # then output the data into the serialiazable dict
        mute_result = {
            'isMuted': bool(mute_status),
            'endDate': None,
            'reason': ''
        }

        if mute_status:
            mute_result['reason'] = getattr(mute_status, 'note', '')

            muted_items = sr.get_muted_items(account.name)
            mute_duration = muted_items.get(account.name)
            if mute_duration:
                mute_result['endDate'] = mute_duration.isoformat()

        # Retrieve the participants post and comment fullnames from cache
        post_fullnames = []
        comment_fullnames = []
        if not account._spam:
            post_fullnames = list(queries.get_submitted(account, 'new',
                                                        'all'))[:100]

            comment_fullnames = list(
                queries.get_comments(account, 'new', 'all'))[:100]

        # Retrieve the associated link objects for posts and comments
        # using the retrieve fullnames, afer the link objects are retrieved
        # create a serializable dict with the the necessary information from
        # the endpoint.
        lookup_fullnames = list(set(post_fullnames) | set(comment_fullnames))
        posts = Thing._by_fullname(lookup_fullnames)

        serializable_posts = {}
        for fullname in post_fullnames:
            if len(serializable_posts) == 3:
                break

            post = posts[fullname]
            if post.sr_id == sr._id and not post._deleted:
                serializable_posts[fullname] = {
                    'title': post.title,
                    'permalink': post.make_permalink(sr, force_domain=True),
                    'date': post._date.isoformat(),
                }

        # Extract the users most recent comments associated with the
        # subreddit
        sr_comments = []
        for fullname in comment_fullnames:
            if len(sr_comments) == 3:
                break

            comment = posts[fullname]
            if comment.sr_id == sr._id and not comment._deleted:
                sr_comments.append(comment)

        # Retrieve all associated link objects (combines lookup)
        comment_links = Link._byID(
            [sr_comment.link_id for sr_comment in sr_comments])

        # Serialize all of the user's sr comments
        serializable_comments = {}
        for sr_comment in sr_comments:
            comment_link = comment_links[sr_comment.link_id]
            comment_body = sr_comment.body
            if len(comment_body) > 140:
                comment_body = '{:.140}...'.format(comment_body)

            serializable_comments[sr_comment._fullname] = {
                'title':
                comment_link.title,
                'comment':
                comment_body,
                'permalink':
                sr_comment.make_permalink(comment_link, sr, force_domain=True),
                'date':
                sr_comment._date.isoformat(),
            }

        return {
            'id': account._fullname,
            'name': account.name,
            'created': account._date.isoformat(),
            'banStatus': ban_result,
            'isShadowBanned': account._spam,
            'muteStatus': mute_result,
            'recentComments': serializable_comments,
            'recentPosts': serializable_posts,
        }
예제 #8
0
파일: modmail.py 프로젝트: zeantsoi/reddit
    def POST_mod_messages(self, conversation, msg_body, is_author_hidden,
                          is_internal):
        """Creates a new message for a particular ModmailConversation

        URL Params:
        conversation_id -- id of the conversation to post a new message to

        POST Params:
        body            -- this is the message body
        isAuthorHidden  -- boolean on whether to hide author, i.e. respond as
                           the subreddit
        isInternal      -- boolean to signify a moderator only message
        """
        self._validate_vmodconversation()

        sr = Subreddit._by_fullname(conversation.owner_fullname)
        self._feature_enabled_check(sr)

        # make sure the user is not muted before posting a message
        if sr.is_muted(c.user):
            return self.send_error(400, errors.USER_MUTED)

        if conversation.is_internal and not is_internal:
            is_internal = True

        is_mod = sr.is_moderator(c.user)
        if not is_mod and is_author_hidden:
            return self.send_error(
                403,
                errors.MOD_REQUIRED,
                fields='isAuthorHidden',
            )
        elif not is_mod and is_internal:
            return self.send_error(
                403,
                errors.MOD_REQUIRED,
                fields='isInternal',
            )

        try:
            if not conversation.is_internal and not conversation.is_auto:
                participant = conversation.get_participant_account()

                if participant and sr.is_muted(participant):
                    return self.send_error(
                        400,
                        errors.MUTED_FROM_SUBREDDIT,
                    )
        except NotFound:
            pass

        try:
            new_message = conversation.add_message(
                c.user,
                msg_body,
                is_author_hidden=is_author_hidden,
                is_internal=is_internal,
            )
        except:
            return self.send_error(500, errors.MODMAIL_MESSAGE_NOT_SAVED)

        # Add the message to the legacy messaging system as well (unless it's
        # an internal message on a non-internal conversation, since we have no
        # way to hide specific messages from the external participant)
        legacy_incompatible = is_internal and not conversation.is_internal
        if (conversation.legacy_first_message_id and not legacy_incompatible):
            first_message = Message._byID(conversation.legacy_first_message_id)
            subject = conversation.subject
            if not subject.startswith('re: '):
                subject = 're: ' + subject

            # Retrieve the participant to decide whether to send the message
            # to the sr or to the participant. If the currently logged in user
            # is the same as the participant then address the message to the
            # sr.
            recipient = sr
            if not is_internal:
                try:
                    participant = (
                        ModmailConversationParticipant.get_participant(
                            conversation.id))

                    is_participant = (
                        (c.user._id == participant.account_id)
                        and not sr.is_moderator_with_perms(c.user, 'mail'))

                    if not is_participant:
                        recipient = Account._byID(participant.account_id)
                except NotFound:
                    pass

            message, inbox_rel = Message._new(
                c.user,
                recipient,
                subject,
                msg_body,
                request.ip,
                parent=first_message,
                from_sr=is_author_hidden,
                create_modmail=False,
            )
            queries.new_message(message, inbox_rel)

        serializable_convo = conversation.to_serializable(
            entity=sr,
            all_messages=True,
            current_user=c.user,
        )
        messages = serializable_convo.pop('messages')

        g.events.new_modmail_event(
            'ss.send_modmail_message',
            conversation,
            message=new_message,
            msg_author=c.user,
            sr=sr,
            request=request,
            context=c,
        )

        response.status_code = 201
        return simplejson.dumps({
            'conversation': serializable_convo,
            'messages': messages,
        })