2
2
from __future__ import annotations
3
3
4
4
import warnings
5
+ import html
6
+
7
+ from dataclasses import dataclass
8
+ from typing_extensions import assert_never
5
9
from typing import Union , Optional , Any
6
- from typing_extensions import assert_never # importing from typing caused me errors
7
10
from enum import Enum , auto
8
- import html
9
11
10
- from . import user , project , studio
12
+ from . import user , project , studio , session
11
13
from ._base import BaseSiteComponent
12
14
from scratchattach .utils import exceptions
13
15
14
16
class CommentSource (Enum ):
15
17
PROJECT = auto ()
16
18
USER_PROFILE = auto ()
17
19
STUDIO = auto ()
20
+ UNKNOWN = auto ()
18
21
22
+ @dataclass
19
23
class Comment (BaseSiteComponent ):
20
24
"""
21
25
Represents a Scratch comment (on a profile, studio or project)
22
26
"""
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
31
41
32
42
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
51
44
52
45
def update (self ):
53
46
warnings .warn ("Warning: Comment objects can't be updated" )
54
47
return False # Objects of this type cannot be updated
55
48
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 )
102
72
103
73
@property
104
74
def text (self ) -> str :
@@ -109,7 +79,7 @@ def text(self) -> str:
109
79
# user profile comments do not seem to be escaped
110
80
return self .content
111
81
112
- return html .unescape (self .content )
82
+ return str ( html .unescape (self .content ) )
113
83
114
84
# Methods for getting related entities
115
85
@@ -159,16 +129,16 @@ def replies(self, *, use_cache: bool = True, limit=40, offset=0):
159
129
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.
160
130
"""
161
131
if (self .cached_replies is None ) or (not use_cache ):
162
- if self .source == "profile" :
132
+ if self .source == CommentSource . USER_PROFILE :
163
133
self .cached_replies = user .User (username = self .source_id , _session = self ._session ).comment_by_id (
164
134
self .id ).cached_replies [offset :offset + limit ]
165
135
166
- elif self .source == "project" :
136
+ elif self .source == CommentSource . PROJECT :
167
137
p = project .Project (id = self .source_id , _session = self ._session )
168
138
p .update ()
169
139
self .cached_replies = p .comment_replies (comment_id = self .id , limit = limit , offset = offset )
170
140
171
- elif self .source == "studio" :
141
+ elif self .source == CommentSource . STUDIO :
172
142
self .cached_replies = studio .Studio (id = self .source_id , _session = self ._session ).comment_replies (
173
143
comment_id = self .id , limit = limit , offset = offset )
174
144
@@ -194,58 +164,63 @@ def reply(self, content, *, commentee_id=None):
194
164
195
165
Returns:
196
166
scratchattach.Comment: The created comment.
167
+ :param content: Content of the comment to send
168
+ :param commentee_id: ID of user to reply to
197
169
"""
198
170
199
171
self ._assert_auth ()
200
172
parent_id = str (self .id )
201
173
if self .parent_id is not None :
202
174
parent_id = str (self .parent_id )
203
175
if commentee_id is None :
204
- if "author_id" in self .__dict__ :
176
+ if self .author_id :
205
177
commentee_id = self .author_id
206
178
else :
207
179
commentee_id = ""
208
- if self .source == "profile" :
180
+
181
+ if self .source == CommentSource .USER_PROFILE :
209
182
return user .User (username = self .source_id , _session = self ._session ).reply_comment (content ,
210
183
parent_id = str (parent_id ),
211
184
commentee_id = commentee_id )
212
- if self .source == "project" :
185
+ if self .source == CommentSource . PROJECT :
213
186
p = project .Project (id = self .source_id , _session = self ._session )
214
187
p .update ()
215
188
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 :
217
191
return studio .Studio (id = self .source_id , _session = self ._session ).reply_comment (content ,
218
192
parent_id = str (parent_id ),
219
193
commentee_id = commentee_id )
194
+ raise ValueError (f"Unknown source: { self .source } " )
220
195
221
196
def delete (self ):
222
197
"""
223
198
Deletes the comment.
224
199
"""
225
200
self ._assert_auth ()
226
- if self .source == "profile" :
201
+ if self .source == CommentSource . USER_PROFILE :
227
202
user .User (username = self .source_id , _session = self ._session ).delete_comment (comment_id = self .id )
228
203
229
- elif self .source == "project" :
204
+ elif self .source == CommentSource . PROJECT :
230
205
p = project .Project (id = self .source_id , _session = self ._session )
231
206
p .update ()
232
207
p .delete_comment (comment_id = self .id )
233
208
234
- elif self .source == "studio" :
209
+ elif self .source == CommentSource . STUDIO :
235
210
studio .Studio (id = self .source_id , _session = self ._session ).delete_comment (comment_id = self .id )
236
211
237
212
def report (self ):
238
213
"""
239
214
Reports the comment to the Scratch team.
240
215
"""
241
216
self ._assert_auth ()
242
- if self .source == "profile" :
217
+ if self .source == CommentSource . USER_PROFILE :
243
218
user .User (username = self .source_id , _session = self ._session ).report_comment (comment_id = self .id )
244
219
245
- elif self .source == "project" :
220
+ elif self .source == CommentSource . PROJECT :
246
221
p = project .Project (id = self .source_id , _session = self ._session )
247
222
p .update ()
248
223
p .report_comment (comment_id = self .id )
249
224
250
- elif self .source == "studio" :
225
+ elif self .source == CommentSource . STUDIO :
251
226
studio .Studio (id = self .source_id , _session = self ._session ).report_comment (comment_id = self .id )
0 commit comments