<filename>Part-03-Understanding-Software-Crafting-Your-Own-Tools/models/edx-platform/openedx/core/djangoapps/django_comment_common/comment_client/comment.py<gh_stars>1-10
# pylint: disable=missing-docstring,protected-access


from openedx.core.djangoapps.django_comment_common.comment_client import models, settings

from .thread import Thread, _url_for_flag_abuse_thread, _url_for_unflag_abuse_thread
from .utils import CommentClientRequestError, perform_request


class Comment(models.Model):

    accessible_fields = [
        'id', 'body', 'anonymous', 'anonymous_to_peers', 'course_id',
        'endorsed', 'parent_id', 'thread_id', 'username', 'votes', 'user_id',
        'closed', 'created_at', 'updated_at', 'depth', 'at_position_list',
        'type', 'commentable_id', 'abuse_flaggers', 'endorsement',
        'child_count',
    ]

    updatable_fields = [
        'body', 'anonymous', 'anonymous_to_peers', 'course_id', 'closed',
        'user_id', 'endorsed', 'endorsement_user_id',
    ]

    initializable_fields = updatable_fields

    metrics_tag_fields = ['course_id', 'endorsed', 'closed']

    base_url = f"{settings.PREFIX}/comments"
    type = 'comment'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._cached_thread = None

    @property
    def thread(self):
        if not self._cached_thread:
            self._cached_thread = Thread(id=self.thread_id, type='thread')
        return self._cached_thread

    @property
    def context(self):
        """Return the context of the thread which this comment belongs to."""
        return self.thread.context

    @classmethod
    def url_for_comments(cls, params=None):
        if params and params.get('parent_id'):
            return _url_for_comment(params['parent_id'])
        else:
            return _url_for_thread_comments(params['thread_id'])

    @classmethod
    def url(cls, action, params=None):
        if params is None:
            params = {}
        if action in ['post']:
            return cls.url_for_comments(params)
        else:
            return super().url(action, params)

    def flagAbuse(self, user, voteable):
        if voteable.type == 'thread':
            url = _url_for_flag_abuse_thread(voteable.id)
        elif voteable.type == 'comment':
            url = _url_for_flag_abuse_comment(voteable.id)
        else:
            raise CommentClientRequestError("Can only flag/unflag threads or comments")
        params = {'user_id': user.id}
        response = perform_request(
            'put',
            url,
            params,
            metric_tags=self._metric_tags,
            metric_action='comment.abuse.flagged'
        )
        voteable._update_from_response(response)

    def unFlagAbuse(self, user, voteable, removeAll):
        if voteable.type == 'thread':
            url = _url_for_unflag_abuse_thread(voteable.id)
        elif voteable.type == 'comment':
            url = _url_for_unflag_abuse_comment(voteable.id)
        else:
            raise CommentClientRequestError("Can flag/unflag for threads or comments")
        params = {'user_id': user.id}

        if removeAll:
            params['all'] = True

        response = perform_request(
            'put',
            url,
            params,
            metric_tags=self._metric_tags,
            metric_action='comment.abuse.unflagged'
        )
        voteable._update_from_response(response)


def _url_for_thread_comments(thread_id):
    return f"{settings.PREFIX}/threads/{thread_id}/comments"


def _url_for_comment(comment_id):
    return f"{settings.PREFIX}/comments/{comment_id}"


def _url_for_flag_abuse_comment(comment_id):
    return f"{settings.PREFIX}/comments/{comment_id}/abuse_flag"


def _url_for_unflag_abuse_comment(comment_id):
    return f"{settings.PREFIX}/comments/{comment_id}/abuse_unflag"
