scratchattach 2.1.14__py3-none-any.whl → 3.0.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scratchattach/__init__.py +14 -6
- scratchattach/__main__.py +93 -0
- {scratchattach-2.1.14.dist-info → scratchattach-3.0.0b0.dist-info}/METADATA +7 -11
- scratchattach-3.0.0b0.dist-info/RECORD +8 -0
- {scratchattach-2.1.14.dist-info → scratchattach-3.0.0b0.dist-info}/WHEEL +1 -1
- scratchattach-3.0.0b0.dist-info/entry_points.txt +2 -0
- scratchattach/cloud/__init__.py +0 -2
- scratchattach/cloud/_base.py +0 -458
- scratchattach/cloud/cloud.py +0 -183
- scratchattach/editor/__init__.py +0 -21
- scratchattach/editor/asset.py +0 -253
- scratchattach/editor/backpack_json.py +0 -117
- scratchattach/editor/base.py +0 -193
- scratchattach/editor/block.py +0 -579
- scratchattach/editor/blockshape.py +0 -357
- scratchattach/editor/build_defaulting.py +0 -51
- scratchattach/editor/code_translation/__init__.py +0 -0
- scratchattach/editor/code_translation/parse.py +0 -177
- scratchattach/editor/comment.py +0 -80
- scratchattach/editor/commons.py +0 -306
- scratchattach/editor/extension.py +0 -50
- scratchattach/editor/field.py +0 -99
- scratchattach/editor/inputs.py +0 -135
- scratchattach/editor/meta.py +0 -114
- scratchattach/editor/monitor.py +0 -183
- scratchattach/editor/mutation.py +0 -324
- scratchattach/editor/pallete.py +0 -90
- scratchattach/editor/prim.py +0 -170
- scratchattach/editor/project.py +0 -279
- scratchattach/editor/sprite.py +0 -599
- scratchattach/editor/twconfig.py +0 -114
- scratchattach/editor/vlb.py +0 -134
- scratchattach/eventhandlers/__init__.py +0 -0
- scratchattach/eventhandlers/_base.py +0 -100
- scratchattach/eventhandlers/cloud_events.py +0 -110
- scratchattach/eventhandlers/cloud_recorder.py +0 -26
- scratchattach/eventhandlers/cloud_requests.py +0 -459
- scratchattach/eventhandlers/cloud_server.py +0 -246
- scratchattach/eventhandlers/cloud_storage.py +0 -136
- scratchattach/eventhandlers/combine.py +0 -30
- scratchattach/eventhandlers/filterbot.py +0 -161
- scratchattach/eventhandlers/message_events.py +0 -42
- scratchattach/other/__init__.py +0 -0
- scratchattach/other/other_apis.py +0 -284
- scratchattach/other/project_json_capabilities.py +0 -475
- scratchattach/site/__init__.py +0 -0
- scratchattach/site/_base.py +0 -66
- scratchattach/site/activity.py +0 -382
- scratchattach/site/alert.py +0 -227
- scratchattach/site/backpack_asset.py +0 -118
- scratchattach/site/browser_cookie3_stub.py +0 -17
- scratchattach/site/browser_cookies.py +0 -61
- scratchattach/site/classroom.py +0 -447
- scratchattach/site/cloud_activity.py +0 -107
- scratchattach/site/comment.py +0 -242
- scratchattach/site/forum.py +0 -432
- scratchattach/site/project.py +0 -825
- scratchattach/site/session.py +0 -1238
- scratchattach/site/studio.py +0 -611
- scratchattach/site/user.py +0 -956
- scratchattach/utils/__init__.py +0 -0
- scratchattach/utils/commons.py +0 -255
- scratchattach/utils/encoder.py +0 -158
- scratchattach/utils/enums.py +0 -236
- scratchattach/utils/exceptions.py +0 -243
- scratchattach/utils/requests.py +0 -93
- scratchattach-2.1.14.dist-info/RECORD +0 -66
- {scratchattach-2.1.14.dist-info → scratchattach-3.0.0b0.dist-info}/licenses/LICENSE +0 -0
- {scratchattach-2.1.14.dist-info → scratchattach-3.0.0b0.dist-info}/top_level.txt +0 -0
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import time
|
|
4
|
-
from ._base import BaseSiteComponent
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class CloudActivity(BaseSiteComponent):
|
|
9
|
-
"""
|
|
10
|
-
Represents a cloud activity (a cloud variable set / creation / deletion).
|
|
11
|
-
|
|
12
|
-
Attributes:
|
|
13
|
-
|
|
14
|
-
:.username: The user who caused the cloud event (the user who added / set / deleted the cloud variable)
|
|
15
|
-
|
|
16
|
-
:.var: The name of the cloud variable that was updated (specified without the cloud emoji)
|
|
17
|
-
|
|
18
|
-
:.name: The name of the cloud variable that was updated (specified without the cloud emoji)
|
|
19
|
-
|
|
20
|
-
:.type: The activity type
|
|
21
|
-
|
|
22
|
-
:.timestamp: Then timestamp of when the action was performed
|
|
23
|
-
|
|
24
|
-
:.value: If the cloud variable was set, then this attribute provides the value the cloud variable was set to
|
|
25
|
-
|
|
26
|
-
:.cloud: The cloud (as object inheriting from scratchattach.Cloud.BaseCloud) that the cloud activity corresponds to
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
def __init__(self, **entries):
|
|
30
|
-
# Set attributes every CloudActivity object needs to have:
|
|
31
|
-
self._session = None
|
|
32
|
-
self.cloud = None
|
|
33
|
-
self.user = None
|
|
34
|
-
self.username = None
|
|
35
|
-
self.type = None
|
|
36
|
-
self.timestamp = time.time()
|
|
37
|
-
|
|
38
|
-
# Update attributes from entries dict:
|
|
39
|
-
self.__dict__.update(entries)
|
|
40
|
-
|
|
41
|
-
def update(self):
|
|
42
|
-
print("Warning: CloudActivity objects can't be updated")
|
|
43
|
-
return False # Objects of this type cannot be updated
|
|
44
|
-
|
|
45
|
-
def __eq__(self, activity2):
|
|
46
|
-
# CloudLogEvents needs to check if two activites are equal (to finde new ones), therefore CloudActivity objects need to be comparable
|
|
47
|
-
return self.user == activity2.user and self.type == activity2.type and self.timestamp == activity2.timestamp and self.value == activity2.value and self.name == activity2.name
|
|
48
|
-
|
|
49
|
-
def _update_from_dict(self, data) -> bool:
|
|
50
|
-
try: self.name = data["name"]
|
|
51
|
-
except Exception: pass
|
|
52
|
-
try: self.var = data["name"]
|
|
53
|
-
except Exception: pass
|
|
54
|
-
try: self.value = data["value"]
|
|
55
|
-
except Exception: pass
|
|
56
|
-
try: self.user = data["user"]
|
|
57
|
-
except Exception: pass
|
|
58
|
-
try: self.username = data["user"]
|
|
59
|
-
except Exception: pass
|
|
60
|
-
try: self.timestamp = data["timestamp"]
|
|
61
|
-
except Exception: pass
|
|
62
|
-
try: self.type = data["verb"].replace("_var","")
|
|
63
|
-
except Exception: pass
|
|
64
|
-
try: self.type = data["method"]
|
|
65
|
-
except Exception: pass
|
|
66
|
-
try: self.cloud = data["cloud"]
|
|
67
|
-
except Exception: pass
|
|
68
|
-
return True
|
|
69
|
-
|
|
70
|
-
def load_log_data(self):
|
|
71
|
-
if self.cloud is None:
|
|
72
|
-
print("Warning: There aren't cloud logs available for this cloud, therefore the user and exact timestamp can't be loaded")
|
|
73
|
-
else:
|
|
74
|
-
if hasattr(self.cloud, "logs"):
|
|
75
|
-
logs = self.cloud.logs(filter_by_var_named=self.var, limit=100)
|
|
76
|
-
matching = list(filter(lambda x: x.value == self.value and x.timestamp <= self.timestamp, logs))
|
|
77
|
-
if matching == []:
|
|
78
|
-
return False
|
|
79
|
-
activity = matching[0]
|
|
80
|
-
self.username = activity.username
|
|
81
|
-
self.user = activity.username
|
|
82
|
-
self.timestamp = activity.timestamp
|
|
83
|
-
return True
|
|
84
|
-
else:
|
|
85
|
-
print("Warning: There aren't cloud logs available for this cloud, therefore the user and exact timestamp can't be loaded")
|
|
86
|
-
return False
|
|
87
|
-
|
|
88
|
-
def actor(self):
|
|
89
|
-
"""
|
|
90
|
-
Returns the user that performed the cloud activity as scratchattach.user.User object
|
|
91
|
-
"""
|
|
92
|
-
if self.username is None:
|
|
93
|
-
return None
|
|
94
|
-
from scratchattach.site import user
|
|
95
|
-
from scratchattach.utils import exceptions
|
|
96
|
-
return self._make_linked_object("username", self.username, user.User, exceptions.UserNotFound)
|
|
97
|
-
|
|
98
|
-
def project(self):
|
|
99
|
-
"""
|
|
100
|
-
Returns the project where the cloud activity was performed as scratchattach.project.Project object
|
|
101
|
-
"""
|
|
102
|
-
if self.cloud is None:
|
|
103
|
-
return None
|
|
104
|
-
from scratchattach.site import project
|
|
105
|
-
from scratchattach.utils import exceptions
|
|
106
|
-
return self._make_linked_object("id", self.cloud.project_id, project.Project, exceptions.ProjectNotFound)
|
|
107
|
-
|
scratchattach/site/comment.py
DELETED
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
"""Comment class"""
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
|
|
4
|
-
import html
|
|
5
|
-
from typing import Union, Optional, Any
|
|
6
|
-
from typing_extensions import assert_never # importing from typing caused me errors
|
|
7
|
-
from enum import Enum, auto
|
|
8
|
-
|
|
9
|
-
from . import user, project, studio
|
|
10
|
-
from ._base import BaseSiteComponent
|
|
11
|
-
from scratchattach.utils import exceptions
|
|
12
|
-
|
|
13
|
-
class Comment(BaseSiteComponent):
|
|
14
|
-
"""
|
|
15
|
-
Represents a Scratch comment (on a profile, studio or project)
|
|
16
|
-
"""
|
|
17
|
-
id: Union[int, str]
|
|
18
|
-
source: str
|
|
19
|
-
source_id: Union[int, str]
|
|
20
|
-
cached_replies: Optional[list[Comment]]
|
|
21
|
-
parent_id: Optional[Union[int, str]]
|
|
22
|
-
cached_parent_comment: Optional[Comment]
|
|
23
|
-
commentee_id: Optional[int]
|
|
24
|
-
content: Any
|
|
25
|
-
|
|
26
|
-
def __str__(self):
|
|
27
|
-
return str(self.content)
|
|
28
|
-
|
|
29
|
-
def __init__(self, **entries):
|
|
30
|
-
|
|
31
|
-
# Set attributes every Comment object needs to have:
|
|
32
|
-
self.id = None
|
|
33
|
-
self._session = None
|
|
34
|
-
self.source = None
|
|
35
|
-
self.source_id = None
|
|
36
|
-
self.cached_replies = None
|
|
37
|
-
self.parent_id = None
|
|
38
|
-
self.cached_parent_comment = None
|
|
39
|
-
|
|
40
|
-
# Update attributes from entries dict:
|
|
41
|
-
self.__dict__.update(entries)
|
|
42
|
-
|
|
43
|
-
if "source" not in entries:
|
|
44
|
-
self.source = "Unknown"
|
|
45
|
-
|
|
46
|
-
def update(self):
|
|
47
|
-
print("Warning: Comment objects can't be updated")
|
|
48
|
-
return False # Objects of this type cannot be updated
|
|
49
|
-
|
|
50
|
-
def _update_from_dict(self, data):
|
|
51
|
-
try:
|
|
52
|
-
self.id = data["id"]
|
|
53
|
-
except Exception:
|
|
54
|
-
pass
|
|
55
|
-
try:
|
|
56
|
-
self.parent_id = data["parent_id"]
|
|
57
|
-
except Exception:
|
|
58
|
-
pass
|
|
59
|
-
try:
|
|
60
|
-
self.commentee_id = data["commentee_id"]
|
|
61
|
-
except Exception:
|
|
62
|
-
pass
|
|
63
|
-
try:
|
|
64
|
-
self.content = data["content"]
|
|
65
|
-
except Exception:
|
|
66
|
-
pass
|
|
67
|
-
try:
|
|
68
|
-
self.datetime_created = data["datetime_created"]
|
|
69
|
-
except Exception:
|
|
70
|
-
pass
|
|
71
|
-
try:
|
|
72
|
-
self.author_name = data["author"]["username"]
|
|
73
|
-
except Exception:
|
|
74
|
-
pass
|
|
75
|
-
try:
|
|
76
|
-
self.author_id = data["author"]["id"]
|
|
77
|
-
except Exception:
|
|
78
|
-
pass
|
|
79
|
-
try:
|
|
80
|
-
self.written_by_scratchteam = data["author"]["scratchteam"]
|
|
81
|
-
except Exception:
|
|
82
|
-
pass
|
|
83
|
-
try:
|
|
84
|
-
self.reply_count = data["reply_count"]
|
|
85
|
-
except Exception:
|
|
86
|
-
pass
|
|
87
|
-
try:
|
|
88
|
-
self.source = data["source"]
|
|
89
|
-
except Exception:
|
|
90
|
-
pass
|
|
91
|
-
try:
|
|
92
|
-
self.source_id = data["source_id"]
|
|
93
|
-
except Exception:
|
|
94
|
-
pass
|
|
95
|
-
return True
|
|
96
|
-
|
|
97
|
-
@property
|
|
98
|
-
def text(self) -> str:
|
|
99
|
-
if self.source == "profile":
|
|
100
|
-
return self.content
|
|
101
|
-
return str(html.unescape(self.content))
|
|
102
|
-
|
|
103
|
-
# Methods for getting related entities
|
|
104
|
-
|
|
105
|
-
def author(self) -> user.User:
|
|
106
|
-
return self._make_linked_object("username", self.author_name, user.User, exceptions.UserNotFound)
|
|
107
|
-
|
|
108
|
-
def place(self) -> user.User | studio.Studio | project.Project:
|
|
109
|
-
"""
|
|
110
|
-
Returns the place (the project, profile or studio) where the comment was posted as Project, User, or Studio object.
|
|
111
|
-
|
|
112
|
-
If the place can't be traced back, None is returned.
|
|
113
|
-
"""
|
|
114
|
-
if self.source == "profile":
|
|
115
|
-
return self._make_linked_object("username", self.source_id, user.User, exceptions.UserNotFound)
|
|
116
|
-
elif self.source == "studio":
|
|
117
|
-
return self._make_linked_object("id", self.source_id, studio.Studio, exceptions.UserNotFound)
|
|
118
|
-
elif self.source == "project":
|
|
119
|
-
return self._make_linked_object("id", self.source_id, project.Project, exceptions.UserNotFound)
|
|
120
|
-
else:
|
|
121
|
-
raise ValueError("Unknown source.")
|
|
122
|
-
|
|
123
|
-
def parent_comment(self) -> Comment | None:
|
|
124
|
-
if self.parent_id is None:
|
|
125
|
-
return None
|
|
126
|
-
|
|
127
|
-
if self.cached_parent_comment is not None:
|
|
128
|
-
return self.cached_parent_comment
|
|
129
|
-
|
|
130
|
-
if self.source == "profile":
|
|
131
|
-
self.cached_parent_comment = user.User(username=self.source_id, _session=self._session).comment_by_id(
|
|
132
|
-
self.parent_id)
|
|
133
|
-
|
|
134
|
-
elif self.source == "project":
|
|
135
|
-
p = project.Project(id=self.source_id, _session=self._session)
|
|
136
|
-
p.update()
|
|
137
|
-
self.cached_parent_comment = p.comment_by_id(self.parent_id)
|
|
138
|
-
|
|
139
|
-
elif self.source == "studio":
|
|
140
|
-
self.cached_parent_comment = studio.Studio(id=self.source_id, _session=self._session).comment_by_id(
|
|
141
|
-
self.parent_id)
|
|
142
|
-
|
|
143
|
-
return self.cached_parent_comment
|
|
144
|
-
|
|
145
|
-
def replies(self, *, use_cache: bool = True, limit=40, offset=0):
|
|
146
|
-
"""
|
|
147
|
-
Keyword Arguments:
|
|
148
|
-
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.
|
|
149
|
-
"""
|
|
150
|
-
if (self.cached_replies is None) or (not use_cache):
|
|
151
|
-
if self.source == "profile":
|
|
152
|
-
_cached_replies = user.User(username=self.source_id, _session=self._session).comment_by_id(
|
|
153
|
-
self.id).cached_replies
|
|
154
|
-
if _cached_replies is not None:
|
|
155
|
-
self.cached_replies = _cached_replies[offset:offset + limit]
|
|
156
|
-
|
|
157
|
-
elif self.source == "project":
|
|
158
|
-
p = project.Project(id=self.source_id, _session=self._session)
|
|
159
|
-
p.update()
|
|
160
|
-
self.cached_replies = p.comment_replies(comment_id=self.id, limit=limit, offset=offset)
|
|
161
|
-
|
|
162
|
-
elif self.source == "studio":
|
|
163
|
-
self.cached_replies = studio.Studio(id=self.source_id, _session=self._session).comment_replies(
|
|
164
|
-
comment_id=self.id, limit=limit, offset=offset)
|
|
165
|
-
|
|
166
|
-
return self.cached_replies
|
|
167
|
-
|
|
168
|
-
# Methods for dealing with the comment
|
|
169
|
-
|
|
170
|
-
def reply(self, content, *, commentee_id=None):
|
|
171
|
-
"""
|
|
172
|
-
Posts a reply comment to the comment.
|
|
173
|
-
|
|
174
|
-
Warning:
|
|
175
|
-
Scratch only shows comments replying to top-level comments, and all replies to replies are actually replies to top-level comments in the API.
|
|
176
|
-
|
|
177
|
-
Therefore, if this comment is a reply, this method will not reply to the comment itself but to the corresponding top-level comment.
|
|
178
|
-
|
|
179
|
-
Args:
|
|
180
|
-
content (str): Comment content to post.
|
|
181
|
-
|
|
182
|
-
Keyword args:
|
|
183
|
-
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.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
Returns:
|
|
187
|
-
scratchattach.Comment: The created comment.
|
|
188
|
-
"""
|
|
189
|
-
|
|
190
|
-
self._assert_auth()
|
|
191
|
-
parent_id = str(self.id)
|
|
192
|
-
if self.parent_id is not None:
|
|
193
|
-
parent_id = str(self.parent_id)
|
|
194
|
-
if commentee_id is None:
|
|
195
|
-
if "author_id" in self.__dict__:
|
|
196
|
-
commentee_id = self.author_id
|
|
197
|
-
else:
|
|
198
|
-
commentee_id = ""
|
|
199
|
-
if self.source == "profile":
|
|
200
|
-
return user.User(username=self.source_id, _session=self._session).reply_comment(content,
|
|
201
|
-
parent_id=str(parent_id),
|
|
202
|
-
commentee_id=commentee_id)
|
|
203
|
-
if self.source == "project":
|
|
204
|
-
p = project.Project(id=self.source_id, _session=self._session)
|
|
205
|
-
p.update()
|
|
206
|
-
return p.reply_comment(content, parent_id=str(parent_id), commentee_id=commentee_id)
|
|
207
|
-
if self.source == "studio":
|
|
208
|
-
return studio.Studio(id=self.source_id, _session=self._session).reply_comment(content,
|
|
209
|
-
parent_id=str(parent_id),
|
|
210
|
-
commentee_id=commentee_id)
|
|
211
|
-
|
|
212
|
-
def delete(self):
|
|
213
|
-
"""
|
|
214
|
-
Deletes the comment.
|
|
215
|
-
"""
|
|
216
|
-
self._assert_auth()
|
|
217
|
-
if self.source == "profile":
|
|
218
|
-
user.User(username=self.source_id, _session=self._session).delete_comment(comment_id=self.id)
|
|
219
|
-
|
|
220
|
-
elif self.source == "project":
|
|
221
|
-
p = project.Project(id=self.source_id, _session=self._session)
|
|
222
|
-
p.update()
|
|
223
|
-
p.delete_comment(comment_id=self.id)
|
|
224
|
-
|
|
225
|
-
elif self.source == "studio":
|
|
226
|
-
studio.Studio(id=self.source_id, _session=self._session).delete_comment(comment_id=self.id)
|
|
227
|
-
|
|
228
|
-
def report(self):
|
|
229
|
-
"""
|
|
230
|
-
Reports the comment to the Scratch team.
|
|
231
|
-
"""
|
|
232
|
-
self._assert_auth()
|
|
233
|
-
if self.source == "profile":
|
|
234
|
-
user.User(username=self.source_id, _session=self._session).report_comment(comment_id=self.id)
|
|
235
|
-
|
|
236
|
-
elif self.source == "project":
|
|
237
|
-
p = project.Project(id=self.source_id, _session=self._session)
|
|
238
|
-
p.update()
|
|
239
|
-
p.report_comment(comment_id=self.id)
|
|
240
|
-
|
|
241
|
-
elif self.source == "studio":
|
|
242
|
-
studio.Studio(id=self.source_id, _session=self._session).report_comment(comment_id=self.id)
|