scratchattach 2.1.15b0__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.
Files changed (69) hide show
  1. scratchattach/__init__.py +14 -6
  2. scratchattach/__main__.py +93 -0
  3. {scratchattach-2.1.15b0.dist-info → scratchattach-3.0.0b0.dist-info}/METADATA +7 -11
  4. scratchattach-3.0.0b0.dist-info/RECORD +8 -0
  5. {scratchattach-2.1.15b0.dist-info → scratchattach-3.0.0b0.dist-info}/WHEEL +1 -1
  6. scratchattach-3.0.0b0.dist-info/entry_points.txt +2 -0
  7. scratchattach/cloud/__init__.py +0 -2
  8. scratchattach/cloud/_base.py +0 -458
  9. scratchattach/cloud/cloud.py +0 -183
  10. scratchattach/editor/__init__.py +0 -21
  11. scratchattach/editor/asset.py +0 -253
  12. scratchattach/editor/backpack_json.py +0 -117
  13. scratchattach/editor/base.py +0 -193
  14. scratchattach/editor/block.py +0 -579
  15. scratchattach/editor/blockshape.py +0 -357
  16. scratchattach/editor/build_defaulting.py +0 -51
  17. scratchattach/editor/code_translation/__init__.py +0 -0
  18. scratchattach/editor/code_translation/parse.py +0 -177
  19. scratchattach/editor/comment.py +0 -80
  20. scratchattach/editor/commons.py +0 -273
  21. scratchattach/editor/extension.py +0 -50
  22. scratchattach/editor/field.py +0 -99
  23. scratchattach/editor/inputs.py +0 -135
  24. scratchattach/editor/meta.py +0 -114
  25. scratchattach/editor/monitor.py +0 -183
  26. scratchattach/editor/mutation.py +0 -324
  27. scratchattach/editor/pallete.py +0 -90
  28. scratchattach/editor/prim.py +0 -170
  29. scratchattach/editor/project.py +0 -279
  30. scratchattach/editor/sprite.py +0 -599
  31. scratchattach/editor/twconfig.py +0 -114
  32. scratchattach/editor/vlb.py +0 -134
  33. scratchattach/eventhandlers/__init__.py +0 -0
  34. scratchattach/eventhandlers/_base.py +0 -100
  35. scratchattach/eventhandlers/cloud_events.py +0 -110
  36. scratchattach/eventhandlers/cloud_recorder.py +0 -26
  37. scratchattach/eventhandlers/cloud_requests.py +0 -459
  38. scratchattach/eventhandlers/cloud_server.py +0 -246
  39. scratchattach/eventhandlers/cloud_storage.py +0 -136
  40. scratchattach/eventhandlers/combine.py +0 -30
  41. scratchattach/eventhandlers/filterbot.py +0 -161
  42. scratchattach/eventhandlers/message_events.py +0 -42
  43. scratchattach/other/__init__.py +0 -0
  44. scratchattach/other/other_apis.py +0 -284
  45. scratchattach/other/project_json_capabilities.py +0 -475
  46. scratchattach/site/__init__.py +0 -0
  47. scratchattach/site/_base.py +0 -66
  48. scratchattach/site/activity.py +0 -382
  49. scratchattach/site/alert.py +0 -227
  50. scratchattach/site/backpack_asset.py +0 -118
  51. scratchattach/site/browser_cookie3_stub.py +0 -17
  52. scratchattach/site/browser_cookies.py +0 -61
  53. scratchattach/site/classroom.py +0 -447
  54. scratchattach/site/cloud_activity.py +0 -107
  55. scratchattach/site/comment.py +0 -242
  56. scratchattach/site/forum.py +0 -432
  57. scratchattach/site/project.py +0 -826
  58. scratchattach/site/session.py +0 -1238
  59. scratchattach/site/studio.py +0 -611
  60. scratchattach/site/user.py +0 -956
  61. scratchattach/utils/__init__.py +0 -0
  62. scratchattach/utils/commons.py +0 -255
  63. scratchattach/utils/encoder.py +0 -158
  64. scratchattach/utils/enums.py +0 -236
  65. scratchattach/utils/exceptions.py +0 -243
  66. scratchattach/utils/requests.py +0 -93
  67. scratchattach-2.1.15b0.dist-info/RECORD +0 -66
  68. {scratchattach-2.1.15b0.dist-info → scratchattach-3.0.0b0.dist-info}/licenses/LICENSE +0 -0
  69. {scratchattach-2.1.15b0.dist-info → scratchattach-3.0.0b0.dist-info}/top_level.txt +0 -0
@@ -1,284 +0,0 @@
1
- """Other Scratch API-related functions"""
2
- from __future__ import annotations
3
-
4
- import json
5
- from dataclasses import dataclass, field
6
-
7
- from scratchattach.utils import commons
8
- from scratchattach.utils.enums import Languages, Language, TTSVoices, TTSVoice
9
- from scratchattach.utils.exceptions import BadRequest, InvalidLanguage, InvalidTTSGender
10
- from scratchattach.utils.requests import requests
11
- from typing import Optional
12
-
13
-
14
- # --- Front page ---
15
-
16
- def get_news(*, limit=10, offset=0):
17
- return commons.api_iterative("https://api.scratch.mit.edu/news", limit=limit, offset=offset)
18
-
19
-
20
- def featured_data():
21
- return requests.get("https://api.scratch.mit.edu/proxy/featured").json()
22
-
23
-
24
- def featured_projects():
25
- return featured_data()["community_featured_projects"]
26
-
27
-
28
- def featured_studios():
29
- return featured_data()["community_featured_studios"]
30
-
31
-
32
- def top_loved():
33
- return featured_data()["community_most_loved_projects"]
34
-
35
-
36
- def top_remixed():
37
- return featured_data()["community_most_remixed_projects"]
38
-
39
-
40
- def newest_projects():
41
- return featured_data()["community_newest_projects"]
42
-
43
-
44
- def curated_projects():
45
- return featured_data()["curator_top_projects"]
46
-
47
-
48
- def design_studio_projects():
49
- return featured_data()["scratch_design_studio"]
50
-
51
-
52
- # --- Statistics ---
53
-
54
- def total_site_stats():
55
- data = requests.get("https://scratch.mit.edu/statistics/data/daily/").json()
56
- data.pop("_TS")
57
- return data
58
-
59
-
60
- def monthly_site_traffic():
61
- data = requests.get("https://scratch.mit.edu/statistics/data/monthly-ga/").json()
62
- data.pop("_TS")
63
- return data
64
-
65
-
66
- def country_counts():
67
- return requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["country_distribution"]
68
-
69
-
70
- def age_distribution():
71
- data = requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["age_distribution_data"][0]["values"]
72
- return_data = {}
73
- for value in data:
74
- return_data[value["x"]] = value["y"]
75
- return return_data
76
-
77
-
78
- def monthly_comment_activity():
79
- return requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["comment_data"]
80
-
81
-
82
- def monthly_project_shares():
83
- return requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["project_data"]
84
-
85
-
86
- def monthly_active_users():
87
- return requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["active_user_data"]
88
-
89
-
90
- def monthly_activity_trends():
91
- return requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["activity_data"]
92
-
93
-
94
- # --- CSRF Token Generation API ---
95
-
96
- def get_csrf_token():
97
- """
98
- Generates a scratchcsrftoken using Scratch's API.
99
-
100
- Returns:
101
- str: The generated scratchcsrftoken
102
- """
103
- return requests.get(
104
- "https://scratch.mit.edu/csrf_token/"
105
- ).headers["set-cookie"].split(";")[3][len(" Path=/, scratchcsrftoken="):]
106
-
107
-
108
- # --- Various other api.scratch.mit.edu API endpoints ---
109
-
110
- def get_health():
111
- return requests.get("https://api.scratch.mit.edu/health").json()
112
-
113
-
114
- def get_total_project_count() -> int:
115
- return requests.get("https://api.scratch.mit.edu/projects/count/all").json()["count"]
116
-
117
-
118
- def check_username(username):
119
- return requests.get(f"https://api.scratch.mit.edu/accounts/checkusername/{username}").json()["msg"]
120
-
121
-
122
- def check_password(password):
123
- return requests.post("https://api.scratch.mit.edu/accounts/checkpassword/", json={"password": password}).json()[
124
- "msg"]
125
-
126
-
127
- # --- April fools endpoints ---
128
-
129
- def aprilfools_get_counter() -> int:
130
- return requests.get("https://api.scratch.mit.edu/surprise").json()["surprise"]
131
-
132
-
133
- def aprilfools_increment_counter() -> int:
134
- return requests.post("https://api.scratch.mit.edu/surprise").json()["surprise"]
135
-
136
-
137
- # --- Resources ---
138
- def get_resource_urls():
139
- return requests.get("https://resources.scratch.mit.edu/localized-urls.json").json()
140
-
141
-
142
- # --- ScratchTools endpoints ---
143
- def scratchtools_online_status(username: str) -> bool | None:
144
- """
145
- Get the online status of an account.
146
- :return: Boolean whether the account is online; if they do not use scratchtools, return None.
147
- """
148
- data = requests.get(f"https://data.scratchtools.app/isonline/{username}").json()
149
-
150
- if data["scratchtools"]:
151
- return data["online"]
152
- else:
153
- return None
154
-
155
-
156
- def scratchtools_beta_user(username: str) -> bool:
157
- """
158
- Get whether a user is a scratchtools beta tester (I think that's what it means)
159
- """
160
- return requests.get(f"https://data.scratchtools.app/isbeta/{username}").json()["beta"]
161
-
162
-
163
- def scratchtools_display_name(username: str) -> str | None:
164
- """
165
- Get the display name of a user for scratchtools. Returns none if there is no display name or the username is invalid
166
- """
167
- return requests.get(f"https://data.scratchtools.app/name/{username}").json().get("displayName")
168
-
169
-
170
- @dataclass(init=True, repr=True)
171
- class ScratchToolsTutorial:
172
- title: str
173
- description: str = field(repr=False)
174
- id: str
175
-
176
- @classmethod
177
- def from_json(cls, data: dict[str, str]) -> ScratchToolsTutorial:
178
- return cls(**data)
179
-
180
- @property
181
- def yt_link(self):
182
- return f"https://www.youtube.com/watch?v={self.id}"
183
-
184
-
185
- def scratchtools_tutorials() -> list[ScratchToolsTutorial]:
186
- """
187
- Returns a list of scratchtools tutorials (just yt videos)
188
- """
189
- data_list = requests.get("https://data.scratchtools.app/tutorials/").json()
190
- return [ScratchToolsTutorial.from_json(data) for data in data_list]
191
-
192
-
193
- def scratchtools_emoji_status(username: str) -> str | None:
194
- return requests.get(f"https://data.scratchtools.app/status/{username}").json().get("status",
195
- '🍪') # Cookie is the default status, even if the user does not use ScratchTools
196
-
197
-
198
- def scratchtools_pinned_comment(project_id: int) -> dict[str, str | int]:
199
- data = requests.get(f"https://data.scratchtools.app/pinned/{project_id}/").json()
200
- # Maybe use this info to instantiate a partial comment object?
201
- return data
202
-
203
-
204
- # --- Misc ---
205
- # I'm not sure what to label this as
206
- def scratch_team_members() -> dict:
207
- # Unfortunately, the only place to find this is a js file, not a json file, which is annoying
208
- text = requests.get("https://scratch.mit.edu/js/credits.bundle.js").text
209
- text = "[{\"userName\"" + text.split("JSON.parse('[{\"userName\"")[1]
210
- text = text.split("\"}]')")[0] + "\"}]"
211
-
212
- return json.loads(text)
213
-
214
-
215
- def send_password_reset_email(username: Optional[str] = None, email: Optional[str] = None):
216
- requests.post("https://scratch.mit.edu/accounts/password_reset/", data={
217
- "username": username,
218
- "email": email,
219
- }, headers=commons.headers, cookies={"scratchcsrftoken": 'a'})
220
-
221
-
222
- def translate(language: str | Languages, text: str = "hello"):
223
- if isinstance(language, str):
224
- lang = Languages.find_by_attrs(language.lower(), ["code", "tts_locale", "name"], str.lower)
225
- elif isinstance(language, Languages):
226
- lang = language.value
227
- else:
228
- lang = language
229
-
230
- if not isinstance(lang, Language):
231
- raise InvalidLanguage(f"{language} is not a language")
232
-
233
- if lang.code is None:
234
- raise InvalidLanguage(f"{lang} is not a valid translate language")
235
-
236
- response_json = requests.get(
237
- f"https://translate-service.scratch.mit.edu/translate?language={lang.code}&text={text}").json()
238
-
239
- if "result" in response_json:
240
- return response_json["result"]
241
- else:
242
- raise BadRequest(f"Language '{language}' does not seem to be valid.\nResponse: {response_json}")
243
-
244
-
245
- def text2speech(text: str = "hello", voice_name: str = "female", language: str = "en-US"):
246
- """
247
- Sends a request to Scratch's TTS synthesis service.
248
- Returns:
249
- - The TTS audio (mp3) as bytes
250
- - The playback rate (e.g. for giant it would be 0.84)
251
- """
252
- if isinstance(voice_name, str):
253
- voice = TTSVoices.find_by_attrs(voice_name.lower(), ["name", "gender"], str.lower)
254
- elif isinstance(voice_name, TTSVoices):
255
- voice = voice_name.value
256
- else:
257
- voice = voice_name
258
-
259
- if not isinstance(voice, TTSVoice):
260
- raise InvalidTTSGender(f"TTS Gender {voice_name} is not supported.")
261
-
262
- # If it's kitten, make sure to change everything to just meows
263
- if voice.name == "kitten":
264
- text = ''
265
- for word in text.split(' '):
266
- if word.strip() != '':
267
- text += "meow "
268
-
269
- if isinstance(language, str):
270
- lang = Languages.find_by_attrs(language.lower(), ["code", "tts_locale", "name"], str.lower)
271
- elif isinstance(language, Languages):
272
- lang = language.value
273
- else:
274
- lang = language
275
-
276
- if not isinstance(lang, Language):
277
- raise InvalidLanguage(f"Language '{language}' is not a language")
278
-
279
- if lang.tts_locale is None:
280
- raise InvalidLanguage(f"Language '{language}' is not a valid TTS language")
281
-
282
- response = requests.get(f"https://synthesis-service.scratch.mit.edu/synth"
283
- f"?locale={lang.tts_locale}&gender={voice.gender}&text={text}")
284
- return response.content, voice.playback_rate