Skip to content

Commit 10ed59c

Browse files
committed
feat: comment dataclass & fix: consistently use CommentSource
1 parent 605eaa9 commit 10ed59c

File tree

1 file changed

+64
-89
lines changed

1 file changed

+64
-89
lines changed

scratchattach/site/comment.py

Lines changed: 64 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -2,103 +2,73 @@
22
from __future__ import annotations
33

44
import warnings
5+
import html
6+
7+
from dataclasses import dataclass
8+
from typing_extensions import assert_never
59
from typing import Union, Optional, Any
6-
from typing_extensions import assert_never # importing from typing caused me errors
710
from enum import Enum, auto
8-
import html
911

10-
from . import user, project, studio
12+
from . import user, project, studio, session
1113
from ._base import BaseSiteComponent
1214
from scratchattach.utils import exceptions
1315

1416
class CommentSource(Enum):
1517
PROJECT = auto()
1618
USER_PROFILE = auto()
1719
STUDIO = auto()
20+
UNKNOWN = auto()
1821

22+
@dataclass
1923
class Comment(BaseSiteComponent):
2024
"""
2125
Represents a Scratch comment (on a profile, studio or project)
2226
"""
23-
id: Union[int, str]
24-
source: CommentSource
25-
source_id: Union[int, str]
26-
cached_replies: Optional[list[Comment]]
27-
parent_id: Optional[Union[int, str]]
28-
cached_parent_comment: Optional[Comment]
29-
commentee_id: Optional[int]
30-
content: Any
27+
id: Optional[int | str] = None
28+
source: CommentSource = CommentSource.UNKNOWN
29+
source_id: Optional[int | str] = None
30+
cached_replies: Optional[list[Comment]] = None
31+
parent_id: Optional[int | str] = None
32+
cached_parent_comment: Optional[Comment] = None
33+
commentee_id: Optional[int] = None
34+
content: Optional[str] = None
35+
reply_count: Optional[int] = None
36+
written_by_scratchteam: Optional[bool] = None
37+
author_id: Optional[int] = None
38+
author_name: Optional[str] = None
39+
40+
_session: Optional[session.Session] = None
3141

3242
def __str__(self):
33-
return str(self.content)
34-
35-
def __init__(self, **entries):
36-
37-
# Set attributes every Comment object needs to have:
38-
self.id = None
39-
self._session = None
40-
self.source = None
41-
self.source_id = None
42-
self.cached_replies = None
43-
self.parent_id = None
44-
self.cached_parent_comment = None
45-
46-
# Update attributes from entries dict:
47-
self.__dict__.update(entries)
48-
49-
if "source" not in entries:
50-
self.source = "Unknown"
43+
return self.text
5144

5245
def update(self):
5346
warnings.warn("Warning: Comment objects can't be updated")
5447
return False # Objects of this type cannot be updated
5548

56-
def _update_from_dict(self, data):
57-
try:
58-
self.id = data["id"]
59-
except Exception:
60-
pass
61-
try:
62-
self.parent_id = data["parent_id"]
63-
except Exception:
64-
pass
65-
try:
66-
self.commentee_id = data["commentee_id"]
67-
except Exception:
68-
pass
69-
try:
70-
self.content = data["content"]
71-
except Exception:
72-
pass
73-
try:
74-
self.datetime_created = data["datetime_created"]
75-
except Exception:
76-
pass
77-
try:
78-
self.author_name = data["author"]["username"]
79-
except Exception:
80-
pass
81-
try:
82-
self.author_id = data["author"]["id"]
83-
except Exception:
84-
pass
85-
try:
86-
self.written_by_scratchteam = data["author"]["scratchteam"]
87-
except Exception:
88-
pass
89-
try:
90-
self.reply_count = data["reply_count"]
91-
except Exception:
92-
pass
93-
try:
94-
self.source = data["source"]
95-
except Exception:
96-
pass
97-
try:
98-
self.source_id = data["source_id"]
99-
except Exception:
100-
pass
101-
return True
49+
def _update_from_dict(self, data: dict[str, str | dict | Any]):
50+
self.id = data["id"]
51+
self.parent_id = data.get("parent_id")
52+
self.commentee_id = data.get("commentee_id")
53+
self.content = str(data["content"])
54+
self.datetime_created = data["datetime_created"]
55+
56+
author = data.get("author", {})
57+
self.author_name = author.get("username", self.author_name)
58+
self.author_id = author.get("id", self.author_id)
59+
self.written_by_scratchteam = author.get("scratchteam", self.written_by_scratchteam)
60+
self.reply_count = data.get("reply_count", self.reply_count)
61+
62+
source: str = data.get("source")
63+
if self.source is CommentSource.UNKNOWN:
64+
self.source = {
65+
"project": CommentSource.PROJECT,
66+
"studio": CommentSource.STUDIO,
67+
"profile": CommentSource.USER_PROFILE,
68+
None: CommentSource.UNKNOWN,
69+
}[source]
70+
71+
self.source_id = data.get("source_id", self.source_id)
10272

10373
@property
10474
def text(self) -> str:
@@ -109,7 +79,7 @@ def text(self) -> str:
10979
# user profile comments do not seem to be escaped
11080
return self.content
11181

112-
return html.unescape(self.content)
82+
return str(html.unescape(self.content))
11383

11484
# Methods for getting related entities
11585

@@ -159,16 +129,16 @@ def replies(self, *, use_cache: bool = True, limit=40, offset=0):
159129
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.
160130
"""
161131
if (self.cached_replies is None) or (not use_cache):
162-
if self.source == "profile":
132+
if self.source == CommentSource.USER_PROFILE:
163133
self.cached_replies = user.User(username=self.source_id, _session=self._session).comment_by_id(
164134
self.id).cached_replies[offset:offset + limit]
165135

166-
elif self.source == "project":
136+
elif self.source == CommentSource.PROJECT:
167137
p = project.Project(id=self.source_id, _session=self._session)
168138
p.update()
169139
self.cached_replies = p.comment_replies(comment_id=self.id, limit=limit, offset=offset)
170140

171-
elif self.source == "studio":
141+
elif self.source == CommentSource.STUDIO:
172142
self.cached_replies = studio.Studio(id=self.source_id, _session=self._session).comment_replies(
173143
comment_id=self.id, limit=limit, offset=offset)
174144

@@ -194,58 +164,63 @@ def reply(self, content, *, commentee_id=None):
194164
195165
Returns:
196166
scratchattach.Comment: The created comment.
167+
:param content: Content of the comment to send
168+
:param commentee_id: ID of user to reply to
197169
"""
198170

199171
self._assert_auth()
200172
parent_id = str(self.id)
201173
if self.parent_id is not None:
202174
parent_id = str(self.parent_id)
203175
if commentee_id is None:
204-
if "author_id" in self.__dict__:
176+
if self.author_id:
205177
commentee_id = self.author_id
206178
else:
207179
commentee_id = ""
208-
if self.source == "profile":
180+
181+
if self.source == CommentSource.USER_PROFILE:
209182
return user.User(username=self.source_id, _session=self._session).reply_comment(content,
210183
parent_id=str(parent_id),
211184
commentee_id=commentee_id)
212-
if self.source == "project":
185+
if self.source == CommentSource.PROJECT:
213186
p = project.Project(id=self.source_id, _session=self._session)
214187
p.update()
215188
return p.reply_comment(content, parent_id=str(parent_id), commentee_id=commentee_id)
216-
if self.source == "studio":
189+
190+
if self.source == CommentSource.STUDIO:
217191
return studio.Studio(id=self.source_id, _session=self._session).reply_comment(content,
218192
parent_id=str(parent_id),
219193
commentee_id=commentee_id)
194+
raise ValueError(f"Unknown source: {self.source}")
220195

221196
def delete(self):
222197
"""
223198
Deletes the comment.
224199
"""
225200
self._assert_auth()
226-
if self.source == "profile":
201+
if self.source == CommentSource.USER_PROFILE:
227202
user.User(username=self.source_id, _session=self._session).delete_comment(comment_id=self.id)
228203

229-
elif self.source == "project":
204+
elif self.source == CommentSource.PROJECT:
230205
p = project.Project(id=self.source_id, _session=self._session)
231206
p.update()
232207
p.delete_comment(comment_id=self.id)
233208

234-
elif self.source == "studio":
209+
elif self.source == CommentSource.STUDIO:
235210
studio.Studio(id=self.source_id, _session=self._session).delete_comment(comment_id=self.id)
236211

237212
def report(self):
238213
"""
239214
Reports the comment to the Scratch team.
240215
"""
241216
self._assert_auth()
242-
if self.source == "profile":
217+
if self.source == CommentSource.USER_PROFILE:
243218
user.User(username=self.source_id, _session=self._session).report_comment(comment_id=self.id)
244219

245-
elif self.source == "project":
220+
elif self.source == CommentSource.PROJECT:
246221
p = project.Project(id=self.source_id, _session=self._session)
247222
p.update()
248223
p.report_comment(comment_id=self.id)
249224

250-
elif self.source == "studio":
225+
elif self.source == CommentSource.STUDIO:
251226
studio.Studio(id=self.source_id, _session=self._session).report_comment(comment_id=self.id)

0 commit comments

Comments
 (0)