Ejemplo n.º 1
0
    def get(self, request, Format=None):
        logger.info('-' * 100)
        logger.info('Client information request =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)

        subreddits = []
        if reddit.read_only:
            redditor_data = RedditorsUtils.get_dummy_redditor_data()
            redditor_id = redditor_data['id']
        else:
            # Get the current authenticated reddit user data
            api_redditor = reddit.user.me()
            redditor_id = api_redditor.id
            redditor_data = RedditorsUtils.get_redditor_data(api_redditor)
            for sub in reddit.user.subreddits():
                subreddits.append(
                    SubredditsUtils.get_subreddit_data_simple(sub))

        # Create or update redditor object for this client
        redditor = Redditor.objects.get_or_none(id=redditor_id)
        serializer = RedditorSerializer(instance=redditor, data=redditor_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        redditor_data = serializer.data

        redditor_data.update(subscriptions=subreddits)
        return Response(data=redditor_data, status=status.HTTP_200_OK)
Ejemplo n.º 2
0
    def delete(self, request, name, Format=None):
        logger.info('-' * 100)
        logger.info(f'Subreddit "{name}" disconnect =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, client_org = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        subreddit = SubredditsUtils.get_sub_if_available(name, reddit)
        if subreddit is None:
            raise exceptions.NotFound(
                detail={
                    'detail': f'No subreddit exists with the name: {name}.'
                })

        subreddit_obj = Subreddit.objects.get_or_none(id=subreddit.id)
        if subreddit_obj is None:
            raise exceptions.NotFound(
                detail={
                    'detail':
                    'No subreddit found with the name provided to make the disconnection.'
                })
        # Remove the client connection from both sides
        subreddit_obj.clients.remove(client_org)
        client_org.subreddit_set.remove(subreddit_obj)

        return Response(
            data={'detail': 'Client disconnected subreddit succesfully.'},
            status=status.HTTP_200_OK,
        )
Ejemplo n.º 3
0
    def delete(self, request, id, Format=None):
        logger.info('-' * 100)
        logger.info(f'Submission "{id}" delete =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, client_org = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        submission = SubmissionsUtils.get_sub_if_exists(id, reddit)
        if not submission:
            raise exceptions.NotFound(
                detail={'detail': f'No submission exists with the id: {id}.'}
            )

        status_code = status.HTTP_200_OK
        if not reddit.read_only:
            # Only can delete the submission if author is the same as the reddit instance
            # So check for submission redditor and reddit redditor
            submission_redditor = submission.author
            if submission_redditor:
                redditor_id, redditor_name = ClientsUtils.get_redditor_id_name(
                    client_org
                )
                if submission_redditor.id == redditor_id:
                    # Try to delete the submission now
                    try:
                        submission.delete()
                        msg = f'Submission \'{id}\' successfully deleted.'
                        logger.info(msg)
                    except Exception as ex:
                        msg = (
                            f'Error deleting submission. Exception raised: {repr(ex)}.'
                        )
                        status_code = status.HTTP_503_SERVICE_UNAVAILABLE
                        logger.error(msg)
                else:
                    msg = (
                        f'Cannot delete the submission with id: {id}. '
                        f'The authenticated reddit user u/{redditor_name} '
                        f'needs to be the same as the submission\'s author u/{submission_redditor.name}'
                    )
                    status_code = status.HTTP_403_FORBIDDEN
                    logger.info(msg)
            else:
                msg = (
                    f'Cannot delete the submission with id: {id}. '
                    'The submission was already deleted or there is no '
                    'way to verify the author at this moment.'
                )
                status_code = status.HTTP_404_NOT_FOUND
                logger.info(msg)
        else:
            msg = (
                f'Reddit instance is read only. Cannot delete submission with id: {id}.'
            )
            status_code = status.HTTP_405_METHOD_NOT_ALLOWED
            logger.warn(msg)

        return Response({'detail': msg}, status=status_code)
Ejemplo n.º 4
0
    def patch(self, request, id, Format=None):
        logger.info('-' * 100)
        logger.info(f'Comment "{id}" patch =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, client_org = Utils.new_client_request(request.user)
        comment = CommentsUtils.get_comment_if_exists(id, reddit)
        if comment is None:
            raise exceptions.NotFound(
                detail={'detail': f'No comment exists with the id: {id}.'})

        # Get the markdown content from json body attribute
        markdown_body = Utils.validate_body_value(request.data.get('body'))

        status_code = status.HTTP_200_OK
        updated_comment_data = None
        if not reddit.read_only:
            # Only can modify the comment if author is the same as the client redditor
            # So check for comment redditor and client data
            comment_redditor = comment.author
            redditor_id, redditor_name = ClientsUtils.get_redditor_id_name(
                client_org)

            if comment_redditor.id == redditor_id:
                # Try to delete the comment now
                try:
                    updated_comment = comment.edit(markdown_body)
                    # Here I need to call refresh() to get the actual replies count
                    updated_comment.refresh()
                    updated_comment_data = CommentsUtils.get_comment_data(
                        updated_comment)
                    msg = f'Comment \'{updated_comment.id}\' successfully edited.'
                    logger.info(msg)
                except Exception as ex:
                    msg = f'Error edit comment. Exception raised: {repr(ex)}.'
                    status_code = status.HTTP_503_SERVICE_UNAVAILABLE
                    logger.error(msg)
            else:
                msg = (
                    f'Cannot edit the comment with id: {id}. '
                    f'The authenticated reddit user u/{redditor_name} '
                    f'needs to be the same as the comment\'s author u/{comment_redditor.name}'
                )
                status_code = status.HTTP_403_FORBIDDEN
                logger.info(msg)
        else:
            msg = f'Reddit instance is read only. Cannot edit comment with id: {id}.'
            status_code = status.HTTP_405_METHOD_NOT_ALLOWED
            logger.warn(msg)

        return Response({
            'detail': msg,
            'comment': updated_comment_data
        },
                        status=status_code)
Ejemplo n.º 5
0
    def post(self, request, id, Format=None):
        logger.info('-' * 100)
        logger.info(f'Submission "{id}" reply =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, client_org = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        submission = SubmissionsUtils.get_sub_if_exists(id, reddit)
        if not submission:
            raise exceptions.NotFound(
                detail={'detail': f'No submission exists with the id: {id}.'}
            )

        # Get the markdown content from json body attribute
        markdown_body = Utils.validate_body_value(request.data.get('body'))

        comment_data = None
        status_code = status.HTTP_201_CREATED
        if not reddit.read_only:
            # Try to post the comment to the submission
            try:
                comment = submission.reply(markdown_body)
                comment_data = CommentsUtils.get_comment_data(comment)
                _, redditor_name = ClientsUtils.get_redditor_id_name(client_org)
                msg = (
                    f'New comment posted by u/{redditor_name} with id \'{comment.id}\' '
                    f'to submission with id: {id}'
                )
                logger.info(msg)
            except Exception as ex:
                if isinstance(ex, Forbidden):
                    msg = (
                        f'Cannot create a comment in submission with id: {id}. '
                        f'Forbidden exception: {repr(ex)}'
                    )
                    status_code = status.HTTP_403_FORBIDDEN
                else:
                    msg = (
                        f'Error creating comment in submission with id: {id}. '
                        f'Exception raised: {repr(ex)}.'
                    )
                    status_code = status.HTTP_503_SERVICE_UNAVAILABLE
                logger.error(msg)
        else:
            msg = f'Reddit instance is read only. Cannot create comment in submission with id: {id}.'
            status_code = status.HTTP_405_METHOD_NOT_ALLOWED
            logger.warn(msg)

        return Response({'detail': msg, 'comment': comment_data}, status=status_code)
Ejemplo n.º 6
0
    def get(self, request, name, Format=None):
        logger.info('-' * 100)
        logger.info(f'Subreddit "{name}" rules =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        subreddit = SubredditsUtils.get_sub_if_available(name, reddit)
        if subreddit is None:
            raise exceptions.NotFound(
                detail={
                    'detail': f'No subreddit exists with the name: {name}.'
                })

        return Response(subreddit.rules(), status=status.HTTP_200_OK)
Ejemplo n.º 7
0
    def get(self, request, id, Format=None):
        logger.info('-' * 100)
        logger.info(f'Submission "{id}" comments =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)
        # Get submission instance with the id provided
        submission = SubmissionsUtils.get_sub_if_exists(id, reddit)
        if not submission:
            raise exceptions.NotFound(
                detail={'detail': f'No submission exists with the id: {id}.'}
            )

        sort = request.query_params.get('sort', 'best')
        flat = request.query_params.get('flat', False)
        limit = request.query_params.get('limit', 10)
        offset = request.query_params.get('offset', 0)

        sort, limit, offset = self._validate_query_params(sort, flat, limit, offset)
        logger.info(f'Sort type: {sort}')
        logger.info(f'Limit: {limit}')
        logger.info(f'Offset: {offset}')
        logger.info(f'Flat: {flat}')

        # Get submissions generator according to query_params and with the limit + offset?
        comments_generator = self._get_comments(submission, sort, limit + offset, flat)

        comments = []
        for index, comment in enumerate(comments_generator, start=1):
            if index > offset:
                comments.append(CommentsUtils.get_comment_data_simple(comment))
                # For some reason the comment_limit attr in the submission instance does not work
                # as suggested in docs, so breaking here when it reaches limit comments
                if len(comments) > limit - 1:
                    break

        logger.info(f'Total comments retrieved: {len(comments)}')

        return Response(
            {
                'comments': comments,
                'sort_type': sort,
                'limit_request': limit,
                'offset': offset,
                'flat': flat,
            },
            status=status.HTTP_200_OK,
        )
Ejemplo n.º 8
0
    def get(self, request, id, Format=None):
        logger.info('-' * 100)
        logger.info(f'Submission "{id}" info request =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        submission = SubmissionsUtils.get_sub_if_exists(id, reddit)
        if not submission:
            raise exceptions.NotFound(
                detail={'detail': f'No submission exists with the id: {id}.'}
            )

        # Get data I need from submission instance
        submission_data = SubmissionsUtils.get_submission_data(submission)
        return Response(submission_data, status=status.HTTP_200_OK)
Ejemplo n.º 9
0
    def post(self, request, id, Format=None):
        logger.info('-' * 100)
        logger.info(f'Comment "{id}" vote =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)
        comment = CommentsUtils.get_comment_if_exists(id, reddit)
        if comment is None:
            raise exceptions.NotFound(
                detail={'detail': f'No comment exists with the id: {id}.'})

        # Get vote value from data json and check if valid
        vote_value = self._validate_vote_value(request.data.get('vote_value'))

        comment_data = None
        status_code = status.HTTP_200_OK
        if reddit.read_only:
            msg = f'Vote action \'dummy\' successful for comment with id: {id}.'
        else:
            try:
                if vote_value == -1:
                    vote_action = 'Downvote'
                    comment.downvote()
                elif vote_value == 0:
                    vote_action = 'Clear Vote'
                    comment.clear_vote()
                else:
                    vote_action = 'Upvote'
                    comment.upvote()
                # Need to force refresh to get replies count
                comment.refresh()
                comment_data = CommentsUtils.get_comment_data_simple(comment)
                msg = f'Vote action \'{vote_action}\' successful for comment with id: {id}.'
                logger.info(msg)
            except Exception as ex:
                status_code = status.HTTP_503_SERVICE_UNAVAILABLE
                msg = (f'Error posting vote to comment with id: {id}. '
                       f'Exception raised: {repr(ex)}.')
                logger.error(msg)

        return Response(
            {
                'detail': msg,
                'comment': comment_data,
            },
            status=status_code,
        )
Ejemplo n.º 10
0
    def get(self, request, id, Format=None):
        logger.info('-' * 100)
        logger.info(f'Comment "{id}" replies =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)
        # Get submission instance with the id provided
        comment = CommentsUtils.get_comment_if_exists(id, reddit)
        if comment is None:
            raise exceptions.NotFound(
                detail={'detail': f'No comment exists with the id: {id}.'})

        flat = request.query_params.get('flat', False)
        limit = request.query_params.get('limit', 10)
        offset = request.query_params.get('offset', 0)

        limit, offset = self._validate_query_params(flat, limit, offset)
        logger.info(f'Limit: {limit}')
        logger.info(f'Offset: {offset}')

        # Here I need to call refresh() for some reason to get the actual replies count
        comment.refresh()
        logger.info(f'Total top replies: {len(comment.replies)}')

        # Get replies generator from the comment instance
        replies_generator = self._get_replies(comment, flat)

        replies = []
        for index, reply in enumerate(replies_generator, start=1):
            if index > offset:
                replies.append(CommentsUtils.get_comment_data_simple(reply))
                # For some reason the comment_limit attr in the submission instance does not work
                # as suggested in docs, so breaking here when it reaches limit comments
                if len(replies) > limit - 1:
                    break

        logger.info(f'Total comments retrieved: {len(replies)}')

        return Response(
            {
                'replies': replies,
                'limit_request': limit,
                'offset': offset,
                'flat': flat,
            },
            status=status.HTTP_200_OK,
        )
Ejemplo n.º 11
0
    def post(self, request, id, Format=None):
        logger.info('-' * 100)
        logger.info(f'Submission "{id}" vote =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        submission = SubmissionsUtils.get_sub_if_exists(id, reddit)
        if not submission:
            raise exceptions.NotFound(
                detail={'detail': f'No submission exists with the id: {id}.'}
            )

        # Get vote value from data json and check if valid
        vote_value = self._validate_vote_value(request.data.get('vote_value'))

        submission_data = None
        status_code = status.HTTP_200_OK
        if reddit.read_only:
            msg = f'Vote action \'dummy\' successful for submission with id: {id}.'
        else:
            try:
                if vote_value == -1:
                    vote_action = 'Downvote'
                    submission.downvote()
                elif vote_value == 0:
                    vote_action = 'Clear Vote'
                    submission.clear_vote()
                else:
                    vote_action = 'Upvote'
                    submission.upvote()
                submission_data = SubmissionsUtils.get_submission_data_simple(
                    submission
                )
                msg = f'Vote action \'{vote_action}\' successful for submission with id: {id}.'
                logger.info(msg)
            except Exception as ex:
                status_code = status.HTTP_503_SERVICE_UNAVAILABLE
                msg = (
                    f'Error posting vote to submission with id: {id}. '
                    f'Exception raised: {repr(ex)}.'
                )
                logger.error(msg)

        return Response(
            {'detail': msg, 'submission': submission_data}, status=status_code,
        )
Ejemplo n.º 12
0
    def delete(self, request, Format=None):
        """
        Method to disconnect a Salesforce Org Client. Revokes access token from Reddit and
        deletes oauth token in database changing the Client Org to inactive status in the process
        """
        logger.info('-' * 100)
        logger.info('Client Reddit access token revoke =>')

        # If the request is authenticated correctly by the bearer token then I can get
        # the client_org from the request.user. Return tuple from TokenAuthentication:
        # (request.user, request.auth) = (client_org, bearer_token)

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, client_org = Utils.new_client_request(request.user)
        try:
            reddit._core._authorizer.revoke()
            logger.info('Reddit access token revoked succesfully.')
        except Exception as ex:
            logger.error(
                f'Error revoking access. Exception raised: {repr(ex)}.')

        # Now I need to delete the oauth_token from database and change the status to inactive
        _, salesforce_org_name = ClientsUtils.get_salesforce_org_id_name(
            client_org)
        logger.info(
            f'Deleting Reddit access token for org \'{salesforce_org_name}\' '
            'and changing status to inactive for client.')
        serializer = ClientOrgSerializer(
            instance=client_org,
            data={
                'disconnected_at': now(),
                'reddit_token': None,
                'is_active': False
            },
        )
        serializer.is_valid(raise_exception=True)
        client_org = serializer.save()

        bearer_token = request.auth
        logger.debug(repr(bearer_token))
        bearer_token.delete()

        return Response(
            data={'detail': 'Account disconnected succesfully.'},
            status=status.HTTP_200_OK,
        )
Ejemplo n.º 13
0
    def post(self, request, name, Format=None):
        """POST request that expects the subreddit name to connect the client to.
        Arguments:
                request {[type]} -- DRF Request object
                name {[string]} -- Subreddit name
        Keyword Arguments:
                Format {[string]} -- [description] (default: {None})
        """
        logger.info('-' * 100)
        logger.info(f'Subreddit "{name}" connect =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, client_org = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        subreddit = SubredditsUtils.get_sub_if_available(name, reddit)
        if subreddit is None:
            raise exceptions.NotFound(
                detail={
                    'detail': f'No subreddit exists with the name: {name}.'
                })

        logger.info(f'Connecting to Subreddit \'{subreddit.name}\'')
        if not reddit.read_only and not subreddit.user_is_subscriber:
            logger.info(
                'Client is not subscribed, so I need to subscribe him here...')
            status_code, msg = SubredditsUtils.subscribe_action(
                reddit, logger, name, client_org, subreddit)
            if status_code != status.HTTP_200_OK:
                return Response({'detail': msg}, status=status_code)

        # Get data I need from subreddit instance
        subreddit_data = SubredditsUtils.get_subreddit_data(subreddit)
        # TODO: Here for now I'll just save the subreddit_data in a Subreddit Model object
        # But I need to enqueue this into a redis queue, send the data to user as fast as possible
        subreddit_obj = SubredditsUtils.create_or_update(subreddit_data)
        # Add the client_org connection to the object
        subreddit_obj.clients.add(client_org)

        return Response(
            {
                'detail': 'Client connected subreddit succesfully.',
                'subreddit': subreddit_data,
            },
            status=status.HTTP_201_CREATED,
        )
Ejemplo n.º 14
0
    def get(self, request, Format=None):
        logger.info('-' * 100)
        logger.info(f'Subreddits subscriptions for client =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)

        if reddit.read_only:
            subreddits = []
        else:
            reddit_user = reddit.user
            subreddits = [
                SubredditsUtils.get_subreddit_data_simple(sub)
                for sub in reddit_user.subreddits()
            ]

        return Response({'subscriptions': subreddits},
                        status=status.HTTP_200_OK)
Ejemplo n.º 15
0
    def get(self, request, name, Format=None):
        logger.info('-' * 100)
        logger.info(f'Subreddit "{name}" submissions =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        subreddit = SubredditsUtils.get_sub_if_available(name, reddit)
        if subreddit is None:
            raise exceptions.NotFound(
                detail={
                    'detail': f'No subreddit exists with the name: {name}.'
                })

        sort = request.query_params.get('sort', 'hot')
        time_filter = request.query_params.get('time_filter', 'all')
        offset = request.query_params.get('offset', 0)

        offset = self._validate_query_params(sort, time_filter, offset)
        logger.info(f'Sort type: {sort}')
        logger.info(f'Time filter: {time_filter}')
        logger.info(f'offset: {offset}')

        # Get submissions generator according to query_params and with the limit + offset?
        submissions_generator = self._get_submissions(subreddit, sort,
                                                      time_filter, offset + 5)

        submissions = [
            SubmissionsUtils.get_submission_data_simple(sub)
            for index, sub in enumerate(submissions_generator, start=1)
            if index > offset
        ]
        logger.info(f'Total submissions: {len(submissions)}')

        return Response(
            {
                'submissions': submissions,
                'sort_type': sort,
                'time_filter': time_filter,
                'offset': offset,
            },
            status=status.HTTP_200_OK,
        )
Ejemplo n.º 16
0
    def get(self, request, name, Format=None):
        logger.info('-' * 100)
        logger.info(f'Redditor "{name}" info =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)
        # Get redditor instance with the name provided
        redditor = RedditorsUtils.get_redditor_if_exists(name, reddit)
        if redditor is None:
            raise exceptions.NotFound(
                detail={
                    'detail': f'No redditor exists with the name: {name}.'
                })

        # Get data I need from subreddit instance
        redditor_data = RedditorsUtils.get_redditor_data(redditor)
        # Enqueue this in a redis queue job later
        # RedditorsUtils.create_or_update(redditor_data)

        return Response(redditor_data, status=status.HTTP_200_OK)
Ejemplo n.º 17
0
    def get(self, request, name, Format=None):
        logger.info('-' * 100)
        logger.info(f'Subreddit "{name}" info request =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        subreddit = SubredditsUtils.get_sub_if_available(name, reddit)
        if subreddit is None:
            raise exceptions.NotFound(
                detail={
                    'detail': f'No subreddit exists with the name: {name}.'
                })

        # Get data I need from subreddit instance
        subreddit_data = SubredditsUtils.get_subreddit_data(subreddit)
        # TODO: Enqueue this in a redis queue job later
        SubredditsUtils.create_or_update(subreddit_data)

        return Response(subreddit_data, status=status.HTTP_200_OK)
Ejemplo n.º 18
0
    def get(self, request, id, Format=None):
        logger.info('-' * 100)
        logger.info(f'Comment "{id}" info request =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, _ = Utils.new_client_request(request.user)
        comment = CommentsUtils.get_comment_if_exists(id, reddit)
        if comment is None:
            raise exceptions.NotFound(
                detail={'detail': f'No comment exists with the id: {id}.'})

        try:
            # Here I need to call refresh() to get the actual replies count
            comment.refresh()
            logger.info(f'Total top replies: {len(comment.replies)}')
        except ClientException as ex:
            msg = (f'Error getting comment with id: {id}. '
                   f'Exception raised: {repr(ex)}.')
            logger.error(msg)
            raise exceptions.NotFound(detail={'detail': msg})

        comment_data = CommentsUtils.get_comment_data(comment)
        return Response(comment_data, status=status.HTTP_200_OK)
Ejemplo n.º 19
0
    def _subscribe_unsubscribe(self, request, subscribe=True):
        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, client_org = Utils.new_client_request(request.user)

        # Get the subreddit name from request data
        # subreddit_name = request.data.get('subreddit')
        subreddit = SubredditsUtils.check_and_get_sub(
            subreddit_name := request.data.get('subreddit'), reddit)

        # Get data I need from subreddit instance
        subreddit_data = SubredditsUtils.get_subreddit_data(subreddit)
        # TODO: Here for now I'll just save the subreddit_data in a Subreddit Model object
        # But I need to enqueue this into a redis queue, send the data to user as fast as possible
        SubredditsUtils.create_or_update(subreddit_data)

        status_code, msg = SubredditsUtils.subscribe_action(
            reddit, logger, subreddit_name, client_org, subreddit, subscribe)

        return Response({
            'detail': msg,
            'subreddit': subreddit_data
        },
                        status=status_code)
Ejemplo n.º 20
0
    def post(self, request, name, Format=None):
        logger.info('-' * 100)
        logger.info(f'Subreddit "{name}" post submission =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, client_org = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        subreddit = SubredditsUtils.get_sub_if_available(name, reddit)
        if subreddit is None:
            raise exceptions.NotFound(
                detail={
                    'detail': f'No subreddit exists with the name: {name}.'
                })

        # Get required data values
        title = request.data.get('title')
        if title is None:
            raise exceptions.ParseError(
                detail={
                    'detail': f'A title must be provided in the json data.'
                })
        selftext = request.data.get('selftext')
        url = request.data.get('url')

        if not selftext and not url:
            # Then it can be an image or video/gif post
            image_path = request.data.get('image_path')
            if not image_path:
                video_path = request.data.get('video_path')
                if video_path:
                    videogif = request.data.get('videogif', False)
                    thumbnail_path = request.data.get('thumbnail_path')
                else:
                    raise exceptions.ParseError(
                        detail={
                            'detail':
                            ('Either a selftext, url, image_path or video_path '
                             'must be provided in the json data.')
                        })

        # Now get optional data values
        flair_id = request.data.get('flair_id')
        flair_text = request.data.get('flair_text')
        resubmit = request.data.get('resubmit', True)
        send_replies = request.data.get('send_replies', True)
        nsfw = request.data.get('nsfw', False)
        spoiler = request.data.get('spoiler', False)
        collection_id = request.data.get('collection_id', False)

        status_code = status.HTTP_201_CREATED
        submission_data = None
        if not reddit.read_only:
            try:
                submission = None
                if selftext or url:
                    submission = subreddit.submit(
                        title,
                        selftext,
                        url,
                        flair_id,
                        flair_text,
                        resubmit,
                        send_replies,
                        nsfw,
                        spoiler,
                        collection_id,
                    )
                elif image_path:
                    # Not waiting the response here.. Not using websockets
                    subreddit.submit_image(
                        title,
                        image_path,
                        flair_id,
                        flair_text,
                        resubmit,
                        send_replies,
                        nsfw,
                        spoiler,
                        collection_id=collection_id,
                        without_websockets=True,
                    )
                else:
                    # Not waiting the response here.. Not using websockets
                    subreddit.submit_video(
                        title,
                        video_path,
                        videogif,
                        thumbnail_path,
                        flair_id,
                        flair_text,
                        resubmit,
                        send_replies,
                        nsfw,
                        spoiler,
                        collection_id=collection_id,
                        without_websockets=True,
                    )
                _, redditor_name = ClientsUtils.get_redditor_id_name(
                    client_org)
                if submission:
                    msg = f'New text/link submission created in r/{name} by u/{redditor_name} with id: {submission.id}.'
                    submission_data = SubmissionsUtils.get_submission_data(
                        submission)
                else:
                    msg = f'New image/video/gif submission created in r/{name} by u/{redditor_name}.'
                logger.info(msg)
            except Exception as ex:
                msg = f'Error creating submission. Exception raised: {repr(ex)}.'
                status_code = status.HTTP_503_SERVICE_UNAVAILABLE
                logger.error(msg)
        else:
            msg = f'Reddit instance is read only. Cannot submit a post creation in r/{name}.'
            status_code = status.HTTP_405_METHOD_NOT_ALLOWED
            logger.warn(msg)

        return Response({
            'detail': msg,
            'submission': submission_data
        },
                        status=status_code)
Ejemplo n.º 21
0
    def post(self, request, id, Format=None):
        logger.info('-' * 100)
        logger.info(f'Submission "{id}" crosspost =>')

        # Gets the reddit instance from the user in request (ClientOrg)
        reddit, client_org = Utils.new_client_request(request.user)
        # Get subreddit instance with the name provided
        submission = SubmissionsUtils.get_sub_if_exists(id, reddit)
        if not submission:
            raise exceptions.NotFound(
                detail={'detail': f'No submission exists with the id: {id}.'}
            )

        # Get required data values from json, in this case only the subreddit name
        # to crosspost the submission
        subreddit = SubredditsUtils.check_and_get_sub(
            subreddit_name := request.data.get('subreddit'), reddit
        )

        # Now get the optional data values
        title = request.data.get('title', None)
        flair_id = request.data.get('flair_id', None)
        flair_text = request.data.get('flair_text', None)
        send_replies = request.data.get('send_replies', True)
        nsfw = request.data.get('nsfw', False)
        spoiler = request.data.get('spoiler', False)

        status_code = status.HTTP_201_CREATED
        crosspost_data = None
        if not reddit.read_only:
            # Try to do the crosspost submission now
            try:
                crosspost = submission.crosspost(
                    subreddit, title, send_replies, flair_id, flair_text, nsfw, spoiler
                )
                crosspost_data = SubmissionsUtils.get_submission_data(crosspost)
                _, redditor_name = ClientsUtils.get_redditor_id_name(client_org)
                msg = (
                    f'New crosspost submission created in r/{subreddit_name} '
                    f'by u/{redditor_name} with id: {crosspost.id}.'
                )
                logger.info(msg)
            except Exception as ex:
                if isinstance(ex, Forbidden):
                    msg = (
                        f'Cannot create the crosspost submission with id: {id}. '
                        f'Forbidden exception: {repr(ex)}'
                    )
                    status_code = status.HTTP_403_FORBIDDEN
                else:
                    msg = (
                        f'Error creating crosspost submission with id: {id}. '
                        f'Exception raised: {repr(ex)}.'
                    )
                    status_code = status.HTTP_503_SERVICE_UNAVAILABLE
                logger.error(msg)
        else:
            msg = f'Reddit instance is read only. Cannot create crosspost submission with id: {id}.'
            status_code = status.HTTP_405_METHOD_NOT_ALLOWED
            logger.warn(msg)

        return Response(
            {'detail': msg, 'cross_submission': crosspost_data}, status=status_code
        )