scratchattach 2.1.6__tar.gz → 2.1.8__tar.gz
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-2.1.6 → scratchattach-2.1.8}/PKG-INFO +1 -1
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/__init__.py +1 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/eventhandlers/cloud_server.py +2 -2
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/other/other_apis.py +98 -3
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/session.py +2 -1
- scratchattach-2.1.8/scratchattach/utils/enums.py +190 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/utils/exceptions.py +28 -5
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/utils/requests.py +3 -2
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach.egg-info/PKG-INFO +1 -1
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach.egg-info/SOURCES.txt +1 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/setup.py +1 -1
- {scratchattach-2.1.6 → scratchattach-2.1.8}/LICENSE +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/README.md +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/cloud/__init__.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/cloud/_base.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/cloud/cloud.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/eventhandlers/__init__.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/eventhandlers/_base.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/eventhandlers/cloud_events.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/eventhandlers/cloud_recorder.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/eventhandlers/cloud_requests.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/eventhandlers/cloud_storage.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/eventhandlers/combine.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/eventhandlers/filterbot.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/eventhandlers/message_events.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/other/__init__.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/other/project_json_capabilities.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/__init__.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/_base.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/activity.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/backpack_asset.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/classroom.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/cloud_activity.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/comment.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/forum.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/project.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/studio.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/site/user.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/utils/__init__.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/utils/commons.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/utils/encoder.py +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach.egg-info/dependency_links.txt +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach.egg-info/requires.txt +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach.egg-info/top_level.txt +0 -0
- {scratchattach-2.1.6 → scratchattach-2.1.8}/setup.cfg +0 -0
|
@@ -10,6 +10,7 @@ from .eventhandlers.combine import MultiEventHandler
|
|
|
10
10
|
from .other.other_apis import *
|
|
11
11
|
from .other.project_json_capabilities import ProjectBody, get_empty_project_pb, get_pb_from_dict, read_sb3_file, download_asset
|
|
12
12
|
from .utils.encoder import Encoding
|
|
13
|
+
from .utils.enums import Languages, TTSVoices
|
|
13
14
|
|
|
14
15
|
from .site.activity import Activity
|
|
15
16
|
from .site.backpack_asset import BackpackAsset
|
|
@@ -223,7 +223,7 @@ def init_cloud_server(hostname='127.0.0.1', port=8080, *, thread=True, length_li
|
|
|
223
223
|
return False
|
|
224
224
|
return True
|
|
225
225
|
|
|
226
|
-
def
|
|
226
|
+
def _updater(self):
|
|
227
227
|
try:
|
|
228
228
|
# Function called when .start() is executed (.start is inherited from BaseEventHandler)
|
|
229
229
|
print(f"Serving websocket server: ws://{hostname}:{port}")
|
|
@@ -241,4 +241,4 @@ def init_cloud_server(hostname='127.0.0.1', port=8080, *, thread=True, length_li
|
|
|
241
241
|
self.running = False
|
|
242
242
|
self.close()
|
|
243
243
|
|
|
244
|
-
return TwCloudServer(hostname, port=port, websocketclass=TwCloudSocket)
|
|
244
|
+
return TwCloudServer(hostname, port=port, websocketclass=TwCloudSocket)
|
|
@@ -1,38 +1,51 @@
|
|
|
1
1
|
"""Other Scratch API-related functions"""
|
|
2
2
|
|
|
3
|
+
import json
|
|
4
|
+
|
|
3
5
|
from ..utils import commons
|
|
6
|
+
from ..utils.exceptions import BadRequest, InvalidLanguage, InvalidTTSGender
|
|
4
7
|
from ..utils.requests import Requests as requests
|
|
5
|
-
import
|
|
8
|
+
from ..utils.enums import Languages, Language, TTSVoices, TTSVoice
|
|
9
|
+
|
|
6
10
|
|
|
7
11
|
# --- Front page ---
|
|
8
12
|
|
|
9
13
|
def get_news(*, limit=10, offset=0):
|
|
10
|
-
return commons.api_iterative("https://api.scratch.mit.edu/news", limit
|
|
14
|
+
return commons.api_iterative("https://api.scratch.mit.edu/news", limit=limit, offset=offset)
|
|
15
|
+
|
|
11
16
|
|
|
12
17
|
def featured_data():
|
|
13
18
|
return requests.get("https://api.scratch.mit.edu/proxy/featured").json()
|
|
14
19
|
|
|
20
|
+
|
|
15
21
|
def featured_projects():
|
|
16
22
|
return featured_data()["community_featured_projects"]
|
|
17
23
|
|
|
24
|
+
|
|
18
25
|
def featured_studios():
|
|
19
26
|
return featured_data()["community_featured_studios"]
|
|
20
27
|
|
|
28
|
+
|
|
21
29
|
def top_loved():
|
|
22
30
|
return featured_data()["community_most_loved_projects"]
|
|
23
31
|
|
|
32
|
+
|
|
24
33
|
def top_remixed():
|
|
25
34
|
return featured_data()["community_most_remixed_projects"]
|
|
26
35
|
|
|
36
|
+
|
|
27
37
|
def newest_projects():
|
|
28
38
|
return featured_data()["community_newest_projects"]
|
|
29
39
|
|
|
40
|
+
|
|
30
41
|
def curated_projects():
|
|
31
42
|
return featured_data()["curator_top_projects"]
|
|
32
43
|
|
|
44
|
+
|
|
33
45
|
def design_studio_projects():
|
|
34
46
|
return featured_data()["scratch_design_studio"]
|
|
35
47
|
|
|
48
|
+
|
|
36
49
|
# --- Statistics ---
|
|
37
50
|
|
|
38
51
|
def total_site_stats():
|
|
@@ -40,14 +53,17 @@ def total_site_stats():
|
|
|
40
53
|
data.pop("_TS")
|
|
41
54
|
return data
|
|
42
55
|
|
|
56
|
+
|
|
43
57
|
def monthly_site_traffic():
|
|
44
58
|
data = requests.get("https://scratch.mit.edu/statistics/data/monthly-ga/").json()
|
|
45
59
|
data.pop("_TS")
|
|
46
60
|
return data
|
|
47
61
|
|
|
62
|
+
|
|
48
63
|
def country_counts():
|
|
49
64
|
return requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["country_distribution"]
|
|
50
65
|
|
|
66
|
+
|
|
51
67
|
def age_distribution():
|
|
52
68
|
data = requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["age_distribution_data"][0]["values"]
|
|
53
69
|
return_data = {}
|
|
@@ -55,18 +71,23 @@ def age_distribution():
|
|
|
55
71
|
return_data[value["x"]] = value["y"]
|
|
56
72
|
return return_data
|
|
57
73
|
|
|
74
|
+
|
|
58
75
|
def monthly_comment_activity():
|
|
59
76
|
return requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["comment_data"]
|
|
60
77
|
|
|
78
|
+
|
|
61
79
|
def monthly_project_shares():
|
|
62
80
|
return requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["project_data"]
|
|
63
81
|
|
|
82
|
+
|
|
64
83
|
def monthly_active_users():
|
|
65
84
|
return requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["active_user_data"]
|
|
66
85
|
|
|
86
|
+
|
|
67
87
|
def monthly_activity_trends():
|
|
68
88
|
return requests.get("https://scratch.mit.edu/statistics/data/monthly/").json()["activity_data"]
|
|
69
89
|
|
|
90
|
+
|
|
70
91
|
# --- CSRF Token Generation API ---
|
|
71
92
|
|
|
72
93
|
def get_csrf_token():
|
|
@@ -80,32 +101,41 @@ def get_csrf_token():
|
|
|
80
101
|
"https://scratch.mit.edu/csrf_token/"
|
|
81
102
|
).headers["set-cookie"].split(";")[3][len(" Path=/, scratchcsrftoken="):]
|
|
82
103
|
|
|
104
|
+
|
|
83
105
|
# --- Various other api.scratch.mit.edu API endpoints ---
|
|
84
106
|
|
|
85
107
|
def get_health():
|
|
86
108
|
return requests.get("https://api.scratch.mit.edu/health").json()
|
|
87
109
|
|
|
110
|
+
|
|
88
111
|
def get_total_project_count() -> int:
|
|
89
112
|
return requests.get("https://api.scratch.mit.edu/projects/count/all").json()["count"]
|
|
90
113
|
|
|
114
|
+
|
|
91
115
|
def check_username(username):
|
|
92
116
|
return requests.get(f"https://api.scratch.mit.edu/accounts/checkusername/{username}").json()["msg"]
|
|
93
117
|
|
|
118
|
+
|
|
94
119
|
def check_password(password):
|
|
95
|
-
return requests.post("https://api.scratch.mit.edu/accounts/checkpassword/", json={"password":password}).json()[
|
|
120
|
+
return requests.post("https://api.scratch.mit.edu/accounts/checkpassword/", json={"password": password}).json()[
|
|
121
|
+
"msg"]
|
|
122
|
+
|
|
96
123
|
|
|
97
124
|
# --- April fools endpoints ---
|
|
98
125
|
|
|
99
126
|
def aprilfools_get_counter() -> int:
|
|
100
127
|
return requests.get("https://api.scratch.mit.edu/surprise").json()["surprise"]
|
|
101
128
|
|
|
129
|
+
|
|
102
130
|
def aprilfools_increment_counter() -> int:
|
|
103
131
|
return requests.post("https://api.scratch.mit.edu/surprise").json()["surprise"]
|
|
104
132
|
|
|
133
|
+
|
|
105
134
|
# --- Resources ---
|
|
106
135
|
def get_resource_urls():
|
|
107
136
|
return requests.get("https://resources.scratch.mit.edu/localized-urls.json").json()
|
|
108
137
|
|
|
138
|
+
|
|
109
139
|
# --- Misc ---
|
|
110
140
|
# I'm not sure what to label this as
|
|
111
141
|
def scratch_team_members() -> dict:
|
|
@@ -115,3 +145,68 @@ def scratch_team_members() -> dict:
|
|
|
115
145
|
text = text.split("\"}]')")[0] + "\"}]"
|
|
116
146
|
|
|
117
147
|
return json.loads(text)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def translate(language: str | Languages, text: str = "hello"):
|
|
151
|
+
if isinstance(language, str):
|
|
152
|
+
lang = Languages.find_by_attrs(language.lower(), ["code", "tts_locale", "name"], str.lower)
|
|
153
|
+
elif isinstance(language, Languages):
|
|
154
|
+
lang = language.value
|
|
155
|
+
else:
|
|
156
|
+
lang = language
|
|
157
|
+
|
|
158
|
+
if not isinstance(lang, Language):
|
|
159
|
+
raise InvalidLanguage(f"{language} is not a language")
|
|
160
|
+
|
|
161
|
+
if lang.code is None:
|
|
162
|
+
raise InvalidLanguage(f"{lang} is not a valid translate language")
|
|
163
|
+
|
|
164
|
+
response_json = requests.get(
|
|
165
|
+
f"https://translate-service.scratch.mit.edu/translate?language={lang.code}&text={text}").json()
|
|
166
|
+
|
|
167
|
+
if "result" in response_json:
|
|
168
|
+
return response_json["result"]
|
|
169
|
+
else:
|
|
170
|
+
raise BadRequest(f"Language '{language}' does not seem to be valid.\nResponse: {response_json}")
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def text2speech(text: str = "hello", voice_name: str = "female", language: str = "en-US"):
|
|
174
|
+
"""
|
|
175
|
+
Sends a request to Scratch's TTS synthesis service.
|
|
176
|
+
Returns:
|
|
177
|
+
- The TTS audio (mp3) as bytes
|
|
178
|
+
- The playback rate (e.g. for giant it would be 0.84)
|
|
179
|
+
"""
|
|
180
|
+
if isinstance(voice_name, str):
|
|
181
|
+
voice = TTSVoices.find_by_attrs(voice_name.lower(), ["name", "gender"], str.lower)
|
|
182
|
+
elif isinstance(voice_name, TTSVoices):
|
|
183
|
+
voice = voice_name.value
|
|
184
|
+
else:
|
|
185
|
+
voice = voice_name
|
|
186
|
+
|
|
187
|
+
if not isinstance(voice, TTSVoice):
|
|
188
|
+
raise InvalidTTSGender(f"TTS Gender {voice_name} is not supported.")
|
|
189
|
+
|
|
190
|
+
# If it's kitten, make sure to change everything to just meows
|
|
191
|
+
if voice.name == "kitten":
|
|
192
|
+
text = ''
|
|
193
|
+
for word in text.split(' '):
|
|
194
|
+
if word.strip() != '':
|
|
195
|
+
text += "meow "
|
|
196
|
+
|
|
197
|
+
if isinstance(language, str):
|
|
198
|
+
lang = Languages.find_by_attrs(language.lower(), ["code", "tts_locale", "name"], str.lower)
|
|
199
|
+
elif isinstance(language, Languages):
|
|
200
|
+
lang = language.value
|
|
201
|
+
else:
|
|
202
|
+
lang = language
|
|
203
|
+
|
|
204
|
+
if not isinstance(lang, Language):
|
|
205
|
+
raise InvalidLanguage(f"Language '{language}' is not a language")
|
|
206
|
+
|
|
207
|
+
if lang.tts_locale is None:
|
|
208
|
+
raise InvalidLanguage(f"Language '{language}' is not a valid TTS language")
|
|
209
|
+
|
|
210
|
+
response = requests.get(f"https://synthesis-service.scratch.mit.edu/synth"
|
|
211
|
+
f"?locale={lang.tts_locale}&gender={voice.gender}&text={text}")
|
|
212
|
+
return response.content, voice.playback_rate
|
|
@@ -54,7 +54,7 @@ class Session(BaseSiteComponent):
|
|
|
54
54
|
'''
|
|
55
55
|
|
|
56
56
|
def __str__(self):
|
|
57
|
-
return "Login for account: {self.username}"
|
|
57
|
+
return f"Login for account: {self.username}"
|
|
58
58
|
|
|
59
59
|
def __init__(self, **entries):
|
|
60
60
|
|
|
@@ -839,6 +839,7 @@ def login(username, password, *, timeout=10) -> Session:
|
|
|
839
839
|
request = requests.post(
|
|
840
840
|
"https://scratch.mit.edu/login/", data=data, headers=_headers,
|
|
841
841
|
timeout = timeout,
|
|
842
|
+
errorhandling = False
|
|
842
843
|
)
|
|
843
844
|
try:
|
|
844
845
|
session_id = str(re.search('"(.*)"', request.headers["Set-Cookie"]).group())
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""
|
|
2
|
+
List of supported languages of scratch's translate and text2speech extensions.
|
|
3
|
+
Adapted from https://translate-service.scratch.mit.edu/supported?language=en
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
from typing import Callable, Iterable
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(init=True, repr=True)
|
|
13
|
+
class Language:
|
|
14
|
+
name: str = None
|
|
15
|
+
code: str = None
|
|
16
|
+
locales: list[str] = None
|
|
17
|
+
tts_locale: str = None
|
|
18
|
+
single_gender: bool = None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class _EnumWrapper(Enum):
|
|
22
|
+
@classmethod
|
|
23
|
+
def find(cls, value, by: str, apply_func: Callable = None):
|
|
24
|
+
"""
|
|
25
|
+
Finds the enum item with the given attribute that is equal to the given value.
|
|
26
|
+
the apply_func will be applied to the attribute of each language object before comparison.
|
|
27
|
+
|
|
28
|
+
i.e. Languages.find("ukranian", "name", str.lower) will return the Ukrainian language dataclass object
|
|
29
|
+
(even though Ukrainian was spelt lowercase, since str.lower will convert the "Ukrainian" string to lowercase)
|
|
30
|
+
"""
|
|
31
|
+
if apply_func is None:
|
|
32
|
+
def apply_func(x):
|
|
33
|
+
return x
|
|
34
|
+
|
|
35
|
+
for item in cls:
|
|
36
|
+
item_obj = item.value
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
if apply_func(getattr(item_obj, by)) == value:
|
|
40
|
+
return item_obj
|
|
41
|
+
except TypeError:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
@classmethod
|
|
45
|
+
def all_of(cls, attr_name: str, apply_func: Callable = None) -> Iterable:
|
|
46
|
+
"""
|
|
47
|
+
Returns the list of each listed enum item's specified attribute by "attr_name"
|
|
48
|
+
|
|
49
|
+
i.e. Languages.all_of("name") will return a list of names:
|
|
50
|
+
["Albanian", "Amharic", ...]
|
|
51
|
+
|
|
52
|
+
The apply_func function will be applied to every list item,
|
|
53
|
+
i.e. Languages.all_of("name", str.lower) will return the same except in lowercase:
|
|
54
|
+
["albanian", "amharic", ...]
|
|
55
|
+
"""
|
|
56
|
+
if apply_func is None:
|
|
57
|
+
def apply_func(x):
|
|
58
|
+
return x
|
|
59
|
+
|
|
60
|
+
for item in cls:
|
|
61
|
+
item_obj = item.value
|
|
62
|
+
attr = getattr(item_obj, attr_name)
|
|
63
|
+
try:
|
|
64
|
+
yield apply_func(attr)
|
|
65
|
+
|
|
66
|
+
except TypeError:
|
|
67
|
+
yield attr
|
|
68
|
+
|
|
69
|
+
@classmethod
|
|
70
|
+
def find_by_attrs(cls, value, bys: list[str], apply_func: Callable = None) -> list:
|
|
71
|
+
"""
|
|
72
|
+
Calls the EnumWrapper.by function multiple times until a match is found, using the provided 'by' attribute names
|
|
73
|
+
"""
|
|
74
|
+
for by in bys:
|
|
75
|
+
ret = cls.find(value, by, apply_func)
|
|
76
|
+
if ret is not None:
|
|
77
|
+
return ret
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class Languages(_EnumWrapper):
|
|
81
|
+
Albanian = Language('Albanian', 'sq', None, None, None)
|
|
82
|
+
Amharic = Language('Amharic', 'am', None, None, None)
|
|
83
|
+
Arabic = Language('Arabic', 'ar', ['ar'], 'arb', True)
|
|
84
|
+
Armenian = Language('Armenian', 'hy', None, None, None)
|
|
85
|
+
Azerbaijani = Language('Azerbaijani', 'az', None, None, None)
|
|
86
|
+
Basque = Language('Basque', 'eu', None, None, None)
|
|
87
|
+
Belarusian = Language('Belarusian', 'be', None, None, None)
|
|
88
|
+
Bulgarian = Language('Bulgarian', 'bg', None, None, None)
|
|
89
|
+
Catalan = Language('Catalan', 'ca', None, None, None)
|
|
90
|
+
Chinese_Traditional = Language('Chinese (Traditional)', 'zh-tw', ['zh-cn', 'zh-tw'], 'cmn-CN', True)
|
|
91
|
+
Croatian = Language('Croatian', 'hr', None, None, None)
|
|
92
|
+
Czech = Language('Czech', 'cs', None, None, None)
|
|
93
|
+
Danish = Language('Danish', 'da', ['da'], 'da-DK', False)
|
|
94
|
+
Dutch = Language('Dutch', 'nl', ['nl'], 'nl-NL', False)
|
|
95
|
+
English = Language('English', 'en', ['en'], 'en-US', False)
|
|
96
|
+
Esperanto = Language('Esperanto', 'eo', None, None, None)
|
|
97
|
+
Estonian = Language('Estonian', 'et', None, None, None)
|
|
98
|
+
Finnish = Language('Finnish', 'fi', None, None, None)
|
|
99
|
+
French = Language('French', 'fr', ['fr'], 'fr-FR', False)
|
|
100
|
+
Galician = Language('Galician', 'gl', None, None, None)
|
|
101
|
+
German = Language('German', 'de', ['de'], 'de-DE', False)
|
|
102
|
+
Greek = Language('Greek', 'el', None, None, None)
|
|
103
|
+
Haitian_Creole = Language('Haitian Creole', 'ht', None, None, None)
|
|
104
|
+
Hindi = Language('Hindi', 'hi', ['hi'], 'hi-IN', True)
|
|
105
|
+
Hungarian = Language('Hungarian', 'hu', None, None, None)
|
|
106
|
+
Icelandic = Language('Icelandic', 'is', ['is'], 'is-IS', False)
|
|
107
|
+
Indonesian = Language('Indonesian', 'id', None, None, None)
|
|
108
|
+
Irish = Language('Irish', 'ga', None, None, None)
|
|
109
|
+
Italian = Language('Italian', 'it', ['it'], 'it-IT', False)
|
|
110
|
+
Japanese = Language('Japanese', 'ja', ['ja', 'ja-hira'], 'ja-JP', False)
|
|
111
|
+
Kannada = Language('Kannada', 'kn', None, None, None)
|
|
112
|
+
Korean = Language('Korean', 'ko', ['ko'], 'ko-KR', True)
|
|
113
|
+
Kurdish_Kurmanji = Language('Kurdish (Kurmanji)', 'ku', None, None, None)
|
|
114
|
+
Latin = Language('Latin', 'la', None, None, None)
|
|
115
|
+
Latvian = Language('Latvian', 'lv', None, None, None)
|
|
116
|
+
Lithuanian = Language('Lithuanian', 'lt', None, None, None)
|
|
117
|
+
Macedonian = Language('Macedonian', 'mk', None, None, None)
|
|
118
|
+
Malay = Language('Malay', 'ms', None, None, None)
|
|
119
|
+
Malayalam = Language('Malayalam', 'ml', None, None, None)
|
|
120
|
+
Maltese = Language('Maltese', 'mt', None, None, None)
|
|
121
|
+
Maori = Language('Maori', 'mi', None, None, None)
|
|
122
|
+
Marathi = Language('Marathi', 'mr', None, None, None)
|
|
123
|
+
Mongolian = Language('Mongolian', 'mn', None, None, None)
|
|
124
|
+
Myanmar_Burmese = Language('Myanmar (Burmese)', 'my', None, None, None)
|
|
125
|
+
Persian = Language('Persian', 'fa', None, None, None)
|
|
126
|
+
Polish = Language('Polish', 'pl', ['pl'], 'pl-PL', False)
|
|
127
|
+
Portuguese = Language('Portuguese', 'pt', ['pt'], 'pt-PT', False)
|
|
128
|
+
Romanian = Language('Romanian', 'ro', ['ro'], 'ro-RO', True)
|
|
129
|
+
Russian = Language('Russian', 'ru', ['ru'], 'ru-RU', False)
|
|
130
|
+
Scots_Gaelic = Language('Scots Gaelic', 'gd', None, None, None)
|
|
131
|
+
Serbian = Language('Serbian', 'sr', None, None, None)
|
|
132
|
+
Slovak = Language('Slovak', 'sk', None, None, None)
|
|
133
|
+
Slovenian = Language('Slovenian', 'sl', None, None, None)
|
|
134
|
+
Spanish = Language('Spanish', 'es', None, None, None)
|
|
135
|
+
Swedish = Language('Swedish', 'sv', ['sv'], 'sv-SE', True)
|
|
136
|
+
Telugu = Language('Telugu', 'te', None, None, None)
|
|
137
|
+
Thai = Language('Thai', 'th', None, None, None)
|
|
138
|
+
Turkish = Language('Turkish', 'tr', ['tr'], 'tr-TR', True)
|
|
139
|
+
Ukrainian = Language('Ukrainian', 'uk', None, None, None)
|
|
140
|
+
Uzbek = Language('Uzbek', 'uz', None, None, None)
|
|
141
|
+
Vietnamese = Language('Vietnamese', 'vi', None, None, None)
|
|
142
|
+
Welsh = Language('Welsh', 'cy', ['cy'], 'cy-GB', True)
|
|
143
|
+
Zulu = Language('Zulu', 'zu', None, None, None)
|
|
144
|
+
Hebrew = Language('Hebrew', 'he', None, None, None)
|
|
145
|
+
Chinese_Simplified = Language('Chinese (Simplified)', 'zh-cn', ['zh-cn', 'zh-tw'], 'cmn-CN', True)
|
|
146
|
+
Mandarin = Chinese_Simplified
|
|
147
|
+
|
|
148
|
+
nb_NO = Language(None, None, ['nb', 'nn'], 'nb-NO', True)
|
|
149
|
+
pt_BR = Language(None, None, ['pt-br'], 'pt-BR', False)
|
|
150
|
+
Brazilian = pt_BR
|
|
151
|
+
es_ES = Language(None, None, ['es'], 'es-ES', False)
|
|
152
|
+
es_US = Language(None, None, ['es-419'], 'es-US', False)
|
|
153
|
+
|
|
154
|
+
@classmethod
|
|
155
|
+
def find(cls, value, by: str = "name", apply_func: Callable = None) -> Language:
|
|
156
|
+
return super().find(value, by, apply_func)
|
|
157
|
+
|
|
158
|
+
@classmethod
|
|
159
|
+
def all_of(cls, attr_name: str = "name", apply_func: Callable = None) -> list:
|
|
160
|
+
return super().all_of(attr_name, apply_func)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@dataclass(init=True, repr=True)
|
|
164
|
+
class TTSVoice:
|
|
165
|
+
name: str
|
|
166
|
+
gender: str
|
|
167
|
+
playback_rate: float | int = 1
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class TTSVoices(_EnumWrapper):
|
|
171
|
+
alto = TTSVoice("alto", "female")
|
|
172
|
+
# female is functionally equal to alto
|
|
173
|
+
female = TTSVoice("female", "female")
|
|
174
|
+
|
|
175
|
+
tenor = TTSVoice("tenor", "male")
|
|
176
|
+
# male is functionally equal to tenor
|
|
177
|
+
male = TTSVoice("male", "male")
|
|
178
|
+
|
|
179
|
+
squeak = TTSVoice("squeak", "female", 1.19)
|
|
180
|
+
giant = TTSVoice("giant", "male", .84)
|
|
181
|
+
kitten = TTSVoice("kitten", "female", 1.41)
|
|
182
|
+
|
|
183
|
+
@classmethod
|
|
184
|
+
def find(cls, value, by: str = "name", apply_func: Callable = None) -> TTSVoice:
|
|
185
|
+
return super().find(value, by, apply_func)
|
|
186
|
+
|
|
187
|
+
@classmethod
|
|
188
|
+
def all_of(cls, attr_name: str = "name", apply_func: Callable = None) -> Iterable:
|
|
189
|
+
return super().all_of(attr_name, apply_func)
|
|
190
|
+
|
|
@@ -18,7 +18,6 @@ class Unauthenticated(Exception):
|
|
|
18
18
|
def __init__(self, message=""):
|
|
19
19
|
self.message = "No login / session connected.\n\nThe object on which the method was called was created using scratchattach.get_xyz()\nUse session.connect_xyz() instead (xyz is a placeholder for user / project / cloud / ...).\n\nMore information: https://scratchattach.readthedocs.io/en/latest/scratchattach.html#scratchattach.utils.exceptions.Unauthenticated"
|
|
20
20
|
super().__init__(self.message)
|
|
21
|
-
pass
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
class Unauthorized(Exception):
|
|
@@ -32,7 +31,6 @@ class Unauthorized(Exception):
|
|
|
32
31
|
self.message = "The user corresponding to the connected login / session is not allowed to perform this action."
|
|
33
32
|
super().__init__(self.message)
|
|
34
33
|
|
|
35
|
-
pass
|
|
36
34
|
|
|
37
35
|
class XTokenError(Exception):
|
|
38
36
|
"""
|
|
@@ -43,6 +41,7 @@ class XTokenError(Exception):
|
|
|
43
41
|
|
|
44
42
|
pass
|
|
45
43
|
|
|
44
|
+
|
|
46
45
|
# Not found errors:
|
|
47
46
|
|
|
48
47
|
class UserNotFound(Exception):
|
|
@@ -60,6 +59,7 @@ class ProjectNotFound(Exception):
|
|
|
60
59
|
|
|
61
60
|
pass
|
|
62
61
|
|
|
62
|
+
|
|
63
63
|
class ClassroomNotFound(Exception):
|
|
64
64
|
"""
|
|
65
65
|
Raised when a non-existent Classroom is requested.
|
|
@@ -75,15 +75,32 @@ class StudioNotFound(Exception):
|
|
|
75
75
|
|
|
76
76
|
pass
|
|
77
77
|
|
|
78
|
+
|
|
78
79
|
class ForumContentNotFound(Exception):
|
|
79
80
|
"""
|
|
80
81
|
Raised when a non-existent forum topic / post is requested.
|
|
81
82
|
"""
|
|
82
83
|
pass
|
|
83
84
|
|
|
85
|
+
|
|
84
86
|
class CommentNotFound(Exception):
|
|
85
87
|
pass
|
|
86
88
|
|
|
89
|
+
|
|
90
|
+
# Invalid inputs
|
|
91
|
+
class InvalidLanguage(Exception):
|
|
92
|
+
"""
|
|
93
|
+
Raised when an invalid language/language code/language object is provided, for TTS or Translate
|
|
94
|
+
"""
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class InvalidTTSGender(Exception):
|
|
99
|
+
"""
|
|
100
|
+
Raised when an invalid TTS gender is provided.
|
|
101
|
+
"""
|
|
102
|
+
pass
|
|
103
|
+
|
|
87
104
|
# API errors:
|
|
88
105
|
|
|
89
106
|
class LoginFailure(Exception):
|
|
@@ -95,6 +112,7 @@ class LoginFailure(Exception):
|
|
|
95
112
|
|
|
96
113
|
pass
|
|
97
114
|
|
|
115
|
+
|
|
98
116
|
class FetchError(Exception):
|
|
99
117
|
"""
|
|
100
118
|
Raised when getting information from the Scratch API fails. This can have various reasons. Make sure all provided arguments are valid.
|
|
@@ -102,6 +120,7 @@ class FetchError(Exception):
|
|
|
102
120
|
|
|
103
121
|
pass
|
|
104
122
|
|
|
123
|
+
|
|
105
124
|
class BadRequest(Exception):
|
|
106
125
|
"""
|
|
107
126
|
Raised when the Scratch API responds with a "Bad Request" error message. This can have various reasons. Make sure all provided arguments are valid.
|
|
@@ -117,6 +136,7 @@ class Response429(Exception):
|
|
|
117
136
|
|
|
118
137
|
pass
|
|
119
138
|
|
|
139
|
+
|
|
120
140
|
class CommentPostFailure(Exception):
|
|
121
141
|
"""
|
|
122
142
|
Raised when a comment fails to post. This can have various reasons.
|
|
@@ -124,12 +144,14 @@ class CommentPostFailure(Exception):
|
|
|
124
144
|
|
|
125
145
|
pass
|
|
126
146
|
|
|
147
|
+
|
|
127
148
|
class APIError(Exception):
|
|
128
149
|
"""
|
|
129
150
|
For API errors that can't be classified into one of the above errors
|
|
130
151
|
"""
|
|
131
152
|
pass
|
|
132
153
|
|
|
154
|
+
|
|
133
155
|
class ScrapeError(Exception):
|
|
134
156
|
"""
|
|
135
157
|
Raised when something goes wrong while web-scraping a page with bs4.
|
|
@@ -137,9 +159,10 @@ class ScrapeError(Exception):
|
|
|
137
159
|
|
|
138
160
|
pass
|
|
139
161
|
|
|
162
|
+
|
|
140
163
|
# Cloud / encoding errors:
|
|
141
164
|
|
|
142
|
-
class
|
|
165
|
+
class CloudConnectionError(Exception):
|
|
143
166
|
"""
|
|
144
167
|
Raised when connecting to Scratch's cloud server fails. This can have various reasons.
|
|
145
168
|
"""
|
|
@@ -172,12 +195,12 @@ class RequestNotFound(Exception):
|
|
|
172
195
|
|
|
173
196
|
pass
|
|
174
197
|
|
|
198
|
+
|
|
175
199
|
# Websocket server errors:
|
|
176
200
|
|
|
177
201
|
class WebsocketServerError(Exception):
|
|
178
|
-
|
|
179
202
|
"""
|
|
180
203
|
Raised when the self-hosted cloud websocket server fails to start.
|
|
181
204
|
"""
|
|
182
205
|
|
|
183
|
-
pass
|
|
206
|
+
pass
|
|
@@ -31,12 +31,13 @@ class Requests:
|
|
|
31
31
|
return r
|
|
32
32
|
|
|
33
33
|
@staticmethod
|
|
34
|
-
def post(url, *, data=None, json=None, headers=None, cookies=None, timeout=None, params=None):
|
|
34
|
+
def post(url, *, data=None, json=None, headers=None, cookies=None, timeout=None, params=None, errorhandling=True):
|
|
35
35
|
try:
|
|
36
36
|
r = requests.post(url, data=data, json=json, headers=headers, cookies=cookies, params=params, timeout=timeout, proxies=proxies)
|
|
37
37
|
except Exception as e:
|
|
38
38
|
raise exceptions.FetchError(e)
|
|
39
|
-
|
|
39
|
+
if errorhandling:
|
|
40
|
+
Requests.check_response(r)
|
|
40
41
|
return r
|
|
41
42
|
|
|
42
43
|
@staticmethod
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scratchattach-2.1.6 → scratchattach-2.1.8}/scratchattach/other/project_json_capabilities.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|