o
    2g\1                     @  s   d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	m
Z
 ddlmZ dd	lmZ d
dlmZ d
dlmZmZmZmZ d
dlmZ erHddlZG dd deeeeZG dd deZdS )zProvide the Comment class.    )annotations)TYPE_CHECKINGAny   )API_PATH)ClientException
InvalidURL)cachedproperty   )CommentForest   )
RedditBase)FullnameMixinInboxableMixinThingModerationMixinUserContentMixin)RedditorNc                      s   e Zd ZdZdZdZed1ddZed2d
dZ	e
dd Ze
d3ddZe
d4ddZe
d5ddZejd6ddZ			d7d8 fdd Zd9 fd$d%Zd&d' Z fd(d)Zd*d+ Zd:d-d.Zd;d/d0Z  ZS )<Commenta  A class that represents a Reddit comment.

    .. include:: ../../typical_attributes.rst

    ================= =================================================================
    Attribute         Description
    ================= =================================================================
    ``author``        Provides an instance of :class:`.Redditor`.
    ``body``          The body of the comment, as Markdown.
    ``body_html``     The body of the comment, as HTML.
    ``created_utc``   Time the comment was created, represented in `Unix Time`_.
    ``distinguished`` Whether or not the comment is distinguished.
    ``edited``        Whether or not the comment has been edited.
    ``id``            The ID of the comment.
    ``is_submitter``  Whether or not the comment author is also the author of the
                      submission.
    ``link_id``       The submission ID that the comment belongs to.
    ``parent_id``     The ID of the parent comment (prefixed with ``t1_``). If it is a
                      top-level comment, this returns the submission ID instead
                      (prefixed with ``t3_``).
    ``permalink``     A permalink for the comment. :class:`.Comment` objects from the
                      inbox have a ``context`` attribute instead.
    ``replies``       Provides an instance of :class:`.CommentForest`.
    ``saved``         Whether or not the comment is saved.
    ``score``         The number of upvotes for the comment.
    ``stickied``      Whether or not the comment is stickied.
    ``submission``    Provides an instance of :class:`.Submission`. The submission that
                      the comment belongs to.
    ``subreddit``     Provides an instance of :class:`.Subreddit`. The subreddit that
                      the comment belongs to.
    ``subreddit_id``  The subreddit ID that the comment belongs to.
    ================= =================================================================

    .. _unix time: https://en.wikipedia.org/wiki/Unix_time

    z6This comment does not appear to be in the comment treeidurlstrreturnc                 C  sR   t | }z|d}W n ty   t| dw t|d |kr%t| |d S )z*Get the ID of a comment from the full URL.commentsN   )r   
_url_partsindex
ValueErrorr   len)r   partscomment_index r!   R/home/garg/my-data/venv/lib/python3.10/site-packages/praw/models/reddit/comment.pyid_from_urlA   s   

zComment.id_from_url,praw.models.reddit.comment.CommentModerationc                 C  s   t | S )zProvide an instance of :class:`.CommentModeration`.

        Example usage:

        .. code-block:: python

            comment = reddit.comment("dkk4qjd")
            comment.mod.approve()

        )CommentModerationselfr!   r!   r"   modN   s   zComment.modc                 C  s   | j jjd S )zReturn the class's kind.comment)_redditconfigkindsr&   r!   r!   r"   _kind\   s   zComment._kindboolc                 C  s$   | j ddd }|| jjjd kS )z8Return ``True`` when the comment is a top-level comment._r   r   
submission)	parent_idsplitr*   r+   r,   )r'   parent_typer!   r!   r"   is_roota   s   zComment.is_rootr   c                 C  s"   t | jtrt| j| j| _| jS )a  Provide an instance of :class:`.CommentForest`.

        This property may return an empty list if the comment has not been refreshed
        with :meth:`.refresh`

        Sort order and reply limit can be set with the ``reply_sort`` and
        ``reply_limit`` attributes before replies are fetched, including any call to
        :meth:`.refresh`:

        .. code-block:: python

            comment.reply_sort = "new"
            comment.refresh()
            replies = comment.replies

        .. note::

            The appropriate values for ``reply_sort`` include ``"confidence"``,
            ``"controversial"``, ``"new"``, ``"old"``, ``"q&a"``, and ``"top"``.

        )
isinstance_replieslistr   r0   r&   r!   r!   r"   repliesg   s   zComment.repliespraw.models.Submissionc                 C  s   | j s| j|  | _ | j S )z?Return the :class:`.Submission` object this comment belongs to.)_submissionr*   r0   _extract_submission_idr&   r!   r!   r"   r0      s   zComment.submissionr0   c                 C  s.   | |j | j< || _t| dg D ]}||_qdS )zFUpdate the :class:`.Submission` associated with the :class:`.Comment`.r8   N)_comments_by_idfullnamer:   getattrr0   )r'   r0   replyr!   r!   r"   r0      s
   Nredditpraw.Reddit
str | None_datadict[str, Any] | Nonec                   sh   |||f ddkrd}t|d}g | _d| _|r|| _n|r'| || _nd}t j|||d dS )z(Initialize a :class:`.Comment` instance.Nr
   z8Exactly one of 'id', 'url', or '_data' must be provided.FT)rC   _fetched)count	TypeErrorr6   r:   r   r#   super__init__)r'   r@   r   r   rC   msgfetched	__class__r!   r"   rI      s   zComment.__init__	attributevalue6str | Redditor | CommentForest | praw.models.Subredditc                   sj   |dkrt | j|}n |dkr"|dkrg }n| jj|j}d}n
|dkr,| j|}t || dS )z)Objectify author, replies, and subreddit.authorr8    r6   	subredditN)	r   	from_datar*   	_objector	objectifychildrenrS   rH   __setattr__)r'   rN   rO   rL   r!   r"   rX      s   zComment.__setattr__c                 C  s.   d| j v r| jddd S | jddd S )Ncontext/r   r   r/   )__dict__rY   rsplitlink_idr2   r&   r!   r!   r"   r;      s   
zComment._extract_submission_idc                   sj   |   }|d }|d sd| j }t||d d d }t| | j|d}| j|j t   d S )NdatarW   zNo data returned for comment r   )rC   )	_fetch_datar=   r   typer*   r[   updaterH   _fetch)r'   r^   rJ   comment_dataotherrL   r!   r"   rb      s   zComment._fetchc                 C  s   di d| j ifS )Ninfor   )r=   r&   r!   r!   r"   _fetch_info   s   zComment._fetch_info Comment | praw.models.Submissionc                 C  sV   | j | jjkr
| jS | j | jjv r| jj| j  S t| j| j ddd }| j|_|S )a  Return the parent of the comment.

        The returned parent will be an instance of either :class:`.Comment`, or
        :class:`.Submission`.

        If this comment was obtained through a :class:`.Submission`, then its entire
        ancestry should be immediately available, requiring no extra network requests.
        However, if this comment was obtained through other means, e.g.,
        ``reddit.comment("COMMENT_ID")``, or ``reddit.inbox.comment_replies``, then the
        returned parent may be a lazy instance of either :class:`.Comment`, or
        :class:`.Submission`.

        Lazy comment example:

        .. code-block:: python

            comment = reddit.comment("cklhv0f")
            parent = comment.parent()
            # 'replies' is empty until the comment is refreshed
            print(parent.replies)  # Output: []
            parent.refresh()
            print(parent.replies)  # Output is at least: [Comment(id="cklhv0f")]

        .. warning::

            Successive calls to :meth:`.parent` may result in a network request per call
            when the comment is not obtained through a :class:`.Submission`. See below
            for an example of how to minimize requests.

        If you have a deeply nested comment and wish to most efficiently discover its
        top-most :class:`.Comment` ancestor you can chain successive calls to
        :meth:`.parent` with calls to :meth:`.refresh` at every 9 levels. For example:

        .. code-block:: python

            comment = reddit.comment("dkk4qjd")
            ancestor = comment
            refresh_counter = 0
            while not ancestor.is_root:
                ancestor = ancestor.parent()
                if refresh_counter % 9 == 0:
                    ancestor.refresh()
                refresh_counter += 1
            print(f"Top-most Ancestor: {ancestor}")

        The above code should result in 5 network requests to Reddit. Without the calls
        to :meth:`.refresh` it would make at least 31 network requests.

        r/   r   )r1   r0   r=   r<   r   r*   r2   r:   )r'   parentr!   r!   r"   rh      s   4zComment.parentc                 C  s@  d| j v r| jddd }ntd j| jjd}| d| j }ddi}d	| j v r/| j|d
< d| j v r9| j|d< | j	j
||dd j}|sKt| jd}|dd }|rz|du s_|j| jkrz| }t|trn||j |rz|du s_|j| jks_|j| jkrt| j| jdur|j d= | j |j  |D ]}| j|_q| S )a)  Refresh the comment's attributes.

        If using :meth:`.Reddit.comment` this method must be called in order to obtain
        the comment's replies.

        Example usage:

        .. code-block:: python

            comment = reddit.comment("dkk4qjd")
            comment.refresh()

        rY   ?r   r   r0   )r   z_/d   reply_limitlimit
reply_sortsort)paramsNr:   )r[   rY   r2   r   formatr0   r   rk   rm   r*   getrW   r   MISSING_COMMENT_MESSAGEpopr5   r   extendr6   r:   ra   )r'   comment_pathpathro   comment_listr)   queuer?   r!   r!   r"   refresh  s6   









zComment.refresh)r   r   r   r   )r   r$   )r   r.   )r   r   )r   r9   )r0   r9   )NNN)r@   rA   r   rB   r   rB   rC   rD   )rN   r   rO   rP   )r   rg   )r   r   )__name__
__module____qualname____doc__rr   	STR_FIELDstaticmethodr#   r	   r(   propertyr-   r4   r8   r0   setterrI   rX   r;   rb   rf   rh   ry   __classcell__r!   r!   rL   r"   r      s8    %


?r   c                   @  s&   e Zd ZdZdZd
ddZdd Zd	S )r%   zProvide a set of functions pertaining to :class:`.Comment` moderation.

    Example usage:

    .. code-block:: python

        comment = reddit.comment("dkk4qjd")
        comment.mod.approve()

    removal_comment_messager)   praw.models.Commentc                 C  s
   || _ dS )znInitialize a :class:`.CommentModeration` instance.

        :param comment: The comment to moderate.

        N)thing)r'   r)   r!   r!   r"   rI   M  s   
zCommentModeration.__init__c                 C  s&   t d }| jjj|d| jjid dS )zUncollapse a :class:`.Comment` that has been collapsed by Crowd Control.

        Example usage:

        .. code-block:: python

            # Uncollapse a comment:
            comment = reddit.comment("dkk4qjd")
            comment.mod.show()

        show_commentr   )r^   N)r   r   r*   postr=   )r'   r   r!   r!   r"   showU  s   zCommentModeration.showN)r)   r   )rz   r{   r|   r}   REMOVAL_MESSAGE_APIrI   r   r!   r!   r!   r"   r%   ?  s
    
r%   )r}   
__future__r   typingr   r   constr   
exceptionsr   r   
util.cacher	   comment_forestr   baser   mixinsr   r   r   r   redditorr   praw.modelsprawr   r%   r!   r!   r!   r"   <module>   s       )