Source code for scratchattach.site.comment

"""Comment class"""
from __future__ import annotations

import html
from typing import Union, Optional, Any
from typing_extensions import assert_never  # importing from typing caused me errors
from enum import Enum, auto

from . import user, project, studio
from ._base import BaseSiteComponent
from scratchattach.utils import exceptions

[docs] class Comment(BaseSiteComponent): """ Represents a Scratch comment (on a profile, studio or project) """ id: Union[int, str] source: str source_id: Union[int, str] cached_replies: Optional[list[Comment]] parent_id: Optional[Union[int, str]] cached_parent_comment: Optional[Comment] commentee_id: Optional[int] content: Any def __str__(self): return str(self.content)
[docs] def __init__(self, **entries): # Set attributes every Comment object needs to have: self.id = None self._session = None self.source = None self.source_id = None self.cached_replies = None self.parent_id = None self.cached_parent_comment = None # Update attributes from entries dict: self.__dict__.update(entries) if "source" not in entries: self.source = "Unknown"
[docs] def update(self): print("Warning: Comment objects can't be updated") return False # Objects of this type cannot be updated
[docs] def _update_from_dict(self, data): try: self.id = data["id"] except Exception: pass try: self.parent_id = data["parent_id"] except Exception: pass try: self.commentee_id = data["commentee_id"] except Exception: pass try: self.content = data["content"] except Exception: pass try: self.datetime_created = data["datetime_created"] except Exception: pass try: self.author_name = data["author"]["username"] except Exception: pass try: self.author_id = data["author"]["id"] except Exception: pass try: self.written_by_scratchteam = data["author"]["scratchteam"] except Exception: pass try: self.reply_count = data["reply_count"] except Exception: pass try: self.source = data["source"] except Exception: pass try: self.source_id = data["source_id"] except Exception: pass return True
@property def text(self) -> str: if self.source == "profile": return self.content return str(html.unescape(self.content)) # Methods for getting related entities
[docs] def author(self) -> user.User: return self._make_linked_object("username", self.author_name, user.User, exceptions.UserNotFound)
[docs] def place(self) -> user.User | studio.Studio | project.Project: """ Returns the place (the project, profile or studio) where the comment was posted as Project, User, or Studio object. If the place can't be traced back, None is returned. """ if self.source == "profile": return self._make_linked_object("username", self.source_id, user.User, exceptions.UserNotFound) elif self.source == "studio": return self._make_linked_object("id", self.source_id, studio.Studio, exceptions.UserNotFound) elif self.source == "project": return self._make_linked_object("id", self.source_id, project.Project, exceptions.UserNotFound) else: raise ValueError("Unknown source.")
[docs] def parent_comment(self) -> Comment | None: if self.parent_id is None: return None if self.cached_parent_comment is not None: return self.cached_parent_comment if self.source == "profile": self.cached_parent_comment = user.User(username=self.source_id, _session=self._session).comment_by_id( self.parent_id) elif self.source == "project": p = project.Project(id=self.source_id, _session=self._session) p.update() self.cached_parent_comment = p.comment_by_id(self.parent_id) elif self.source == "studio": self.cached_parent_comment = studio.Studio(id=self.source_id, _session=self._session).comment_by_id( self.parent_id) return self.cached_parent_comment
[docs] def replies(self, *, use_cache: bool = True, limit=40, offset=0): """ Keyword Arguments: use_cache (bool): Returns the replies cached on the first reply fetch. This makes it SIGNIFICANTLY faster for profile comments. Warning: For profile comments, the replies are retrieved and cached on object creation. """ if (self.cached_replies is None) or (not use_cache): if self.source == "profile": _cached_replies = user.User(username=self.source_id, _session=self._session).comment_by_id( self.id).cached_replies if _cached_replies is not None: self.cached_replies = _cached_replies[offset:offset + limit] elif self.source == "project": p = project.Project(id=self.source_id, _session=self._session) p.update() self.cached_replies = p.comment_replies(comment_id=self.id, limit=limit, offset=offset) elif self.source == "studio": self.cached_replies = studio.Studio(id=self.source_id, _session=self._session).comment_replies( comment_id=self.id, limit=limit, offset=offset) return self.cached_replies
# Methods for dealing with the comment
[docs] def reply(self, content, *, commentee_id=None): """ Posts a reply comment to the comment. Warning: Scratch only shows comments replying to top-level comments, and all replies to replies are actually replies to top-level comments in the API. Therefore, if this comment is a reply, this method will not reply to the comment itself but to the corresponding top-level comment. Args: content (str): Comment content to post. Keyword args: commentee_id (None or str): If set to None (default), it will automatically fill out the commentee ID with the user ID of the parent comment author. Set it to "" to mention no user. Returns: scratchattach.Comment: The created comment. """ self._assert_auth() parent_id = str(self.id) if self.parent_id is not None: parent_id = str(self.parent_id) if commentee_id is None: if "author_id" in self.__dict__: commentee_id = self.author_id else: commentee_id = "" if self.source == "profile": return user.User(username=self.source_id, _session=self._session).reply_comment(content, parent_id=str(parent_id), commentee_id=commentee_id) if self.source == "project": p = project.Project(id=self.source_id, _session=self._session) p.update() return p.reply_comment(content, parent_id=str(parent_id), commentee_id=commentee_id) if self.source == "studio": return studio.Studio(id=self.source_id, _session=self._session).reply_comment(content, parent_id=str(parent_id), commentee_id=commentee_id)
[docs] def delete(self): """ Deletes the comment. """ self._assert_auth() if self.source == "profile": user.User(username=self.source_id, _session=self._session).delete_comment(comment_id=self.id) elif self.source == "project": p = project.Project(id=self.source_id, _session=self._session) p.update() p.delete_comment(comment_id=self.id) elif self.source == "studio": studio.Studio(id=self.source_id, _session=self._session).delete_comment(comment_id=self.id)
[docs] def report(self): """ Reports the comment to the Scratch team. """ self._assert_auth() if self.source == "profile": user.User(username=self.source_id, _session=self._session).report_comment(comment_id=self.id) elif self.source == "project": p = project.Project(id=self.source_id, _session=self._session) p.update() p.report_comment(comment_id=self.id) elif self.source == "studio": studio.Studio(id=self.source_id, _session=self._session).report_comment(comment_id=self.id)