66
77from dataclasses import dataclass
88from typing import Optional , Any
9+ from enum import Enum
910
1011from bs4 import Tag
1112
1213from . import user , project , studio , session , forum
1314from ._base import BaseSiteComponent
1415from scratchattach .utils import exceptions
1516
16- class ActvityTypes :
17- # not an enum to preserve backwards compatability. Can be changed though.
17+ class ActivityTypes (Enum ):
1818 loveproject = "loveproject"
1919 favoriteproject = "favoriteproject"
2020 becomecurator = "becomecurator"
@@ -74,7 +74,7 @@ class Activity(BaseSiteComponent):
7474
7575 datetime_created : Optional [str ] = None
7676 time : Any = None
77- type : Optional [str ] = None
77+ type : Optional [ActivityTypes ] = None
7878
7979 def __repr__ (self ):
8080 return f"Activity({ repr (self .raw )} )"
@@ -89,26 +89,26 @@ def parts(self):
8989 :return: A list of parts of the message. Join the parts to get a readable version, which is done with str(activity)
9090 """
9191 match self .type :
92- case " loveproject" :
92+ case ActivityTypes . loveproject :
9393 return [f"{ self .actor_username } " , "loved" , f"-P { self .title !r} ({ self .project_id } )" ]
94- case " favoriteproject" :
94+ case ActivityTypes . favoriteproject :
9595 return [f"{ self .actor_username } " , "favorited" , f"-P { self .project_title !r} ({ self .project_id } )" ]
96- case " becomecurator" :
96+ case ActivityTypes . becomecurator :
9797 return [f"{ self .actor_username } " , "now curating" , f"-S { self .title !r} ({ self .gallery_id } )" ]
98- case " followuser" :
98+ case ActivityTypes . followuser :
9999 return [f"{ self .actor_username } " , "followed" , f"-U { self .followed_username } " ]
100- case " followstudio" :
100+ case ActivityTypes . followstudio :
101101 return [f"{ self .actor_username } " , "followed" , f"-S { self .title !r} ({ self .gallery_id } )" ]
102- case " shareproject" :
102+ case ActivityTypes . shareproject :
103103 return [f"{ self .actor_username } " , "reshared" if self .is_reshare else "shared" ,
104104 f"-P { self .title !r} ({ self .project_id } )" ]
105- case " remixproject" :
105+ case ActivityTypes . remixproject :
106106 return [f"{ self .actor_username } " , "remixed" ,
107107 f"-P { self .parent_title !r} ({ self .parent_id } ) as -P { self .title !r} ({ self .project_id } )" ]
108- case " becomeownerstudio" :
108+ case ActivityTypes . becomeownerstudio :
109109 return [f"{ self .actor_username } " , "became owner of" , f"-S { self .gallery_title !r} ({ self .gallery_id } )" ]
110110
111- case " addcomment" :
111+ case ActivityTypes . addcomment :
112112 ret = [self .actor_username , "commented on" ]
113113
114114 match self .comment_type :
@@ -132,42 +132,42 @@ def parts(self):
132132
133133 return ret
134134
135- case " curatorinvite" :
135+ case ActivityTypes . curatorinvite :
136136 return [f"{ self .actor_username } " , "invited you to curate" , f"-S { self .title !r} ({ self .gallery_id } )" ]
137137
138- case " userjoin" :
138+ case ActivityTypes . userjoin :
139139 # This is also the first message you get - 'Welcome to Scratch'
140140 return [f"{ self .actor_username } " , "joined Scratch" ]
141141
142- case " studioactivity" :
142+ case ActivityTypes . studioactivity :
143143 # the actor username should be systemuser
144144 return [f"{ self .actor_username } " , 'Studio activity' , '' , f"-S { self .title !r} ({ self .gallery_id } )" ]
145145
146- case " forumpost" :
146+ case ActivityTypes . forumpost :
147147 return [f"{ self .actor_username } " , "posted in" , f"-F { self .topic_title } ({ self .topic_id } )" ]
148148
149- case " updatestudio" :
149+ case ActivityTypes . updatestudio :
150150 return [f"{ self .actor_username } " , "updated" , f"-S { self .gallery_title } ({ self .gallery_id } )" ]
151151
152- case " createstudio" :
152+ case ActivityTypes . createstudio :
153153 return [f"{ self .actor_username } " , "created" , f"-S { self .gallery_title } ({ self .gallery_id } )" ]
154154
155- case " promotetomanager" :
155+ case ActivityTypes . promotetomanager :
156156 return [f"{ self .actor_username } " , "promoted" , f"-U { self .recipient_username } " , "in" ,
157157 f"-S { self .gallery_title } ({ self .gallery_id } )" ]
158158
159- case " updateprofile" :
159+ case ActivityTypes . updateprofile :
160160 return [f"{ self .actor_username } " , "updated their profile." , f"Changed fields: { self .changed_fields } " ]
161161
162- case " removeprojectfromstudio" :
162+ case ActivityTypes . removeprojectfromstudio :
163163 return [f"{ self .actor_username } " , "removed" , f"-P { self .project_title } ({ self .project_id } )" , "from" ,
164164 f"-S { self .gallery_title } ({ self .gallery_id } )" ]
165165
166- case " addprojecttostudio" :
166+ case ActivityTypes . addprojecttostudio :
167167 return [f"{ self .actor_username } " , "added" , f"-P { self .project_title } ({ self .project_id } )" , "to" ,
168168 f"-S { self .gallery_title } ({ self .gallery_id } )" ]
169169
170- case " performaction" :
170+ case ActivityTypes . performaction :
171171 return [f"{ self .actor_username } " , "performed an action" ]
172172
173173 case _:
@@ -182,7 +182,45 @@ def update(self):
182182
183183 def _update_from_dict (self , data ):
184184 self .raw = data
185- self .__dict__ .update (data )
185+
186+ self ._session = data .get ("_session" , self ._session )
187+ self .raw = data .get ("raw" , self .raw )
188+
189+ self .id = data .get ("id" , self .id )
190+ self .actor_username = data .get ("actor_username" , self .actor_username )
191+
192+ self .project_id = data .get ("project_id" , self .project_id )
193+ self .gallery_id = data .get ("gallery_id" , self .gallery_id )
194+ self .username = data .get ("username" , self .username )
195+ self .followed_username = data .get ("followed_username" , self .followed_username )
196+ self .recipient_username = data .get ("recipient_username" , self .recipient_username )
197+ self .title = data .get ("title" , self .title )
198+ self .project_title = data .get ("project_title" , self .project_title )
199+ self .gallery_title = data .get ("gallery_title" , self .gallery_title )
200+ self .topic_title = data .get ("topic_title" , self .topic_title )
201+ self .topic_id = data .get ("topic_id" , self .topic_id )
202+ self .target_name = data .get ("target_name" , self .target_name )
203+ self .target_id = data .get ("target_id" , self .target_id )
204+
205+ self .parent_title = data .get ("parent_title" , self .parent_title )
206+ self .parent_id = data .get ("parent_id" , self .parent_id )
207+
208+ self .comment_type = data .get ("comment_type" , self .comment_type )
209+ self .comment_obj_id = data .get ("comment_obj_id" , self .comment_obj_id )
210+ self .comment_obj_title = data .get ("comment_obj_title" , self .comment_obj_title )
211+ self .comment_id = data .get ("comment_id" , self .comment_id )
212+ self .comment_fragment = data .get ("comment_fragment" , self .comment_fragment )
213+
214+ self .changed_fields = data .get ("changed_fields" , self .changed_fields )
215+ self .is_reshare = data .get ("is_reshare" , self .is_reshare )
216+
217+ self .datetime_created = data .get ("datetime_created" , self .datetime_created )
218+ self .time = data .get ("time" , self .time )
219+
220+ _type = data .get ("type" , self .type )
221+ if _type :
222+ self .type = ActivityTypes [_type ]
223+
186224 return True
187225
188226 def _update_from_json (self , data : dict ):
@@ -216,37 +254,37 @@ def _update_from_json(self, data: dict):
216254 self .raw = data
217255 self .datetime_created = _time
218256 if activity_type == 0 :
219- self .type = " followuser"
257+ self .type = ActivityTypes . followuser
220258 self .followed_username = data ["followed_username" ]
221259
222260 elif activity_type == 1 :
223- self .type = " followstudio"
261+ self .type = ActivityTypes . followstudio
224262 self .gallery_id = data ["gallery" ]
225263
226264 elif activity_type == 2 :
227- self .type = " loveproject"
265+ self .type = ActivityTypes . loveproject
228266 self .project_id = data ["project" ]
229267 self .recipient_username = recipient_username
230268
231269 elif activity_type == 3 :
232- self .type = " favoriteproject"
270+ self .type = ActivityTypes . favoriteproject
233271 self .project_id = data ["project" ]
234272 self .recipient_username = recipient_username
235273
236274 elif activity_type == 7 :
237- self .type = " addprojecttostudio"
275+ self .type = ActivityTypes . addprojecttostudio
238276 self .project_id = data ["project" ]
239277 self .gallery_id = data ["gallery" ]
240278 self .recipient_username = recipient_username
241279
242280 elif activity_type in (8 , 9 , 10 ):
243- self .type = " shareproject"
281+ self .type = ActivityTypes . shareproject
244282 self .is_reshare = data ["is_reshare" ]
245283 self .project_id = data ["project" ]
246284 self .recipient_username = recipient_username
247285
248286 elif activity_type == 11 :
249- self .type = " remixproject"
287+ self .type = ActivityTypes . remixproject
250288 self .parent_id = data ["parent" ]
251289 warnings .warn (f"This may be incorrectly implemented.\n "
252290 f"Raw data: { data } \n "
@@ -256,30 +294,30 @@ def _update_from_json(self, data: dict):
256294 # type 12 does not exist in the HTML. That's why it was removed, not merged with type 13.
257295
258296 elif activity_type == 13 :
259- self .type = " createstudio"
297+ self .type = ActivityTypes . createstudio
260298 self .gallery_id = data ["gallery" ]
261299
262300 elif activity_type == 15 :
263- self .type = " updatestudio"
301+ self .type = ActivityTypes . updatestudio
264302 self .gallery_id = data ["gallery" ]
265303
266304 elif activity_type in (16 , 17 , 18 , 19 ):
267- self .type = " removeprojectfromstudio"
305+ self .type = ActivityTypes . removeprojectfromstudio
268306 self .gallery_id = data ["gallery" ]
269307 self .project_id = data ["project" ]
270308
271309 elif activity_type in (20 , 21 , 22 ):
272- self .type = " promotetomanager"
310+ self .type = ActivityTypes . promotetomanager
273311 self .recipient_username = recipient_username
274312 self .gallery_id = data ["gallery" ]
275313
276314 elif activity_type in (23 , 24 , 25 ):
277- self .type = " updateprofile"
315+ self .type = ActivityTypes . updateprofile
278316 self .changed_fields = data .get ("changed_fields" , {})
279317
280318 elif activity_type in (26 , 27 ):
281319 # Comment in either project, user, or studio
282- self .type = " addcomment"
320+ self .type = ActivityTypes . addcomment
283321 self .comment_fragment = data ["comment_fragment" ]
284322 self .comment_type = data ["comment_type" ]
285323 self .comment_obj_id = data ["comment_obj_id" ]
@@ -288,7 +326,7 @@ def _update_from_json(self, data: dict):
288326
289327 else :
290328 # This is coded in the scratch HTML, haven't found an example of it though
291- self .type = " performaction"
329+ self .type = ActivityTypes . performaction
292330
293331
294332 def _update_from_html (self , data : Tag ):
@@ -306,26 +344,26 @@ def _update_from_html(self, data: Tag):
306344
307345 self .target_name = data .find ('div' ).find ('span' ).find_next ().text
308346 self .target_link = data .find ('div' ).find ('span' ).find_next ()["href" ]
309- self .target_id = data .find ('div' ).find ('span' ).find_next ()["href" ].split ("/" )[- 2 ]
347+ self .target_id = int ( data .find ('div' ).find ('span' ).find_next ()["href" ].split ("/" )[- 2 ])
310348
311- self . type = data .find ('div' ).find_all ('span' )[0 ].next_sibling .strip ()
312- if self . type == "loved" :
313- self .type = " loveproject"
349+ _type = data .find ('div' ).find_all ('span' )[0 ].next_sibling .strip ()
350+ if _type == "loved" :
351+ self .type = ActivityTypes . loveproject
314352
315- elif self . type == "favorited" :
316- self .type = " favoriteproject"
353+ elif _type == "favorited" :
354+ self .type = ActivityTypes . favoriteproject
317355
318- elif "curator" in self . type :
319- self .type = " becomecurator"
356+ elif "curator" in _type :
357+ self .type = ActivityTypes . becomecurator
320358
321- elif "shared" in self . type :
322- self .type = " shareproject"
359+ elif "shared" in _type :
360+ self .type = ActivityTypes . shareproject
323361
324- elif "is now following" in self . type :
362+ elif "is now following" in _type :
325363 if "users" in self .target_link :
326- self .type = " followuser"
364+ self .type = ActivityTypes . followuser
327365 else :
328- self .type = " followstudio"
366+ self .type = ActivityTypes . followstudio
329367
330368 return True
331369
@@ -340,14 +378,15 @@ def target(self):
340378 Returns the activity's target (depending on the activity, this is either a User, Project, Studio or Comment object).
341379 May also return None if the activity type is unknown.
342380 """
381+ _type = self .type .value
343382
344- if "project" in self . type : # target is a project
383+ if "project" in _type : # target is a project
345384 if self .target_id :
346385 return self ._make_linked_object ("id" , self .target_id , project .Project , exceptions .ProjectNotFound )
347386 if self .project_id :
348387 return self ._make_linked_object ("id" , self .project_id , project .Project , exceptions .ProjectNotFound )
349388
350- if self . type == "becomecurator" or self . type == "followstudio" : # target is a studio
389+ if _type == "becomecurator" or _type == "followstudio" : # target is a studio
351390 if self .target_id :
352391 return self ._make_linked_object ("id" , self .target_id , studio .Studio , exceptions .StudioNotFound )
353392 if self .gallery_id :
@@ -356,7 +395,7 @@ def target(self):
356395 if self .username :
357396 return self ._make_linked_object ("username" , self .username , user .User , exceptions .UserNotFound )
358397
359- if self . type == "followuser" or "curator" in self . type : # target is a user
398+ if _type == "followuser" or "curator" in _type : # target is a user
360399 if self .target_name :
361400 return self ._make_linked_object ("username" , self .target_name , user .User , exceptions .UserNotFound )
362401 if self .followed_username :
@@ -365,7 +404,7 @@ def target(self):
365404 if self .recipient_username : # the recipient_username field always indicates the target is a user
366405 return self ._make_linked_object ("username" , self .recipient_username , user .User , exceptions .UserNotFound )
367406
368- if self . type == "addcomment" : # target is a comment
407+ if _type == "addcomment" : # target is a comment
369408 if self .comment_type == 0 :
370409 # we need author name, but it has not been saved in this object
371410 _proj = self ._session .connect_project (self .comment_obj_id )
@@ -380,7 +419,7 @@ def target(self):
380419
381420 return _c
382421
383- if self . type == "forumpost" :
422+ if _type == "forumpost" :
384423 return forum .ForumTopic (id = 603418 , _session = self ._session , title = self .title )
385424
386425 return None
0 commit comments