22from __future__ import annotations
33
44import warnings
5+ import html
6+
7+ from dataclasses import dataclass
8+ from typing_extensions import assert_never
59from typing import Union , Optional , Any
6- from typing_extensions import assert_never # importing from typing caused me errors
710from enum import Enum , auto
8- import html
911
10- from . import user , project , studio
12+ from . import user , project , studio , session
1113from ._base import BaseSiteComponent
1214from scratchattach .utils import exceptions
1315
1416class CommentSource (Enum ):
1517 PROJECT = auto ()
1618 USER_PROFILE = auto ()
1719 STUDIO = auto ()
20+ UNKNOWN = auto ()
1821
22+ @dataclass
1923class 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