scratchattach package

Submodules

scratchattach.cloud

scratchattach.cloud._base

class scratchattach.cloud._base.AnyCloud[source]

Bases: ABC, Generic[T]

Represents a cloud that is not necessarily using a websocket.

_abc_impl = <_abc._abc_data object>
abstractmethod _enforce_ratelimit(*, n: int) None[source]
_session: Session | None
active_connection: bool
abstractmethod connect()[source]
abstractmethod create_event_stream() EventStream[source]
abstractmethod disconnect()[source]
events() CloudEvents[source]
abstractmethod get_all_vars(*, recorder_initial_values={}) dict[str, T][source]
abstractmethod get_var(var, *, recorder_initial_values={}) T[source]
reconnect()[source]
requests(*, no_packet_loss: bool = False, used_cloud_vars: list[str] = ['1', '2', '3', '4', '5', '6', '7', '8', '9'], respond_order='receive', debug: bool = False) CloudRequests[source]
abstractmethod set_var(variable: str, value: T) None[source]

Sets a cloud variable.

Parameters:
  • variable (str) – The name of the cloud variable that should be set (provided without the cloud emoji)

  • value (Any) – The value the cloud variable should be set to

abstractmethod set_vars(var_value_dict: dict[str, T], *, intelligent_waits: bool = True)[source]

Sets multiple cloud variables at once (works for an unlimited amount of variables).

Parameters:

var_value_dict (dict) – variable:value dictionary with the variables / values to set. The dict should like this: {“var1”:”value1”, “var2”:”value2”, …}

Kwargs:

intelligent_waits (boolean): When enabled, the method will automatically decide how long to wait before performing this cloud variable set, to make sure no rate limits are triggered

storage(*, no_packet_loss: bool = False, used_cloud_vars: list[str] = ['1', '2', '3', '4', '5', '6', '7', '8', '9']) CloudStorage[source]
var_stets_since_first: int
class scratchattach.cloud._base.BaseCloud(*, project_id: int | str | None = None, _session=None)[source]

Bases: AnyCloud[str | int]

Base class for a project’s cloud variables. Represents a cloud.

When inheriting from this class, the __init__ function of the inherited class: - must first call the constructor of the super class: super().__init__() - must then set some attributes

Attributes that must be specified in the __init__ function a class inheriting from this one:

project_id: Project id of the cloud variables

cloud_host: URL of the websocket server (“wss://…” or “ws://…”)

Attributes that can, but don’t have to be specified in the __init__ function:

_session: Either None or a scratchattach.site.session.Session object. Defaults to None.

ws_shortterm_ratelimit: The wait time between cloud variable sets. Defaults to 0.1

ws_longterm_ratelimit: The amount of cloud variable set that can be performed long-term without ever getting ratelimited

allow_non_numeric: Whether non-numeric cloud variable values are allowed. Defaults to False

length_limit: Length limit for cloud variable values. Defaults to 100000

username: The username to send during handshake. Defaults to “scratchattach”

header: The header to send. Defaults to None

cookie: The cookie to send. Defaults to None

origin: The origin to send. Defaults to None

print_connect_messages: Whether to print a message on every connect to the cloud server. Defaults to False.

__init__(*, project_id: int | str | None = None, _session=None)[source]
_abc_impl = <_abc._abc_data object>
_assert_auth()[source]
_assert_valid_value(value)[source]
_enforce_ratelimit(*, n)[source]
_handshake()[source]
_send_packet(packet)[source]
_send_packet_list(packet_list)[source]
allow_non_numeric: bool
cloud_host: str
connect()[source]
cookie: dict | None
create_event_stream()[source]
disconnect()[source]
event_stream: EventStream | None = None
get_all_vars(*, recorder_initial_values={})[source]
get_var(var, *, recorder_initial_values={})[source]
header: dict | None
length_limit: int
origin: str | None
print_connect_message: bool
project_id: int | str | None
set_var(variable, value)[source]

Sets a cloud variable.

Parameters:
  • variable (str) – The name of the cloud variable that should be set (provided without the cloud emoji)

  • value (str) – The value the cloud variable should be set to

set_vars(var_value_dict, *, intelligent_waits=True)[source]

Sets multiple cloud variables at once (works for an unlimited amount of variables).

Parameters:

var_value_dict (dict) – variable:value dictionary with the variables / values to set. The dict should like this: {“var1”:”value1”, “var2”:”value2”, …}

Kwargs:

intelligent_waits (boolean): When enabled, the method will automatically decide how long to wait before performing this cloud variable set, to make sure no rate limits are triggered

username: str
websocket: WebSocket
ws_longterm_ratelimit: float
ws_shortterm_ratelimit: float
ws_timeout: int | None
class scratchattach.cloud._base.EventStream[source]

Bases: SupportsRead[Iterator[dict[str, Any]]], SupportsClose

Allows you to stream events

_abc_impl = <_abc._abc_data object>
class scratchattach.cloud._base.LogCloud(*, project_id: int | str | None = None, _session=None)[source]

Bases: BaseCloud

_abc_impl = <_abc._abc_data object>
abstractmethod logs(*, filter_by_var_named: str | None = None, limit: int = 100, offset: int = 0) list[CloudActivity][source]
class scratchattach.cloud._base.LogCloudMeta(name, bases, namespace, /, **kwargs)[source]

Bases: ABCMeta

class scratchattach.cloud._base.SupportsClose[source]

Bases: ABC

_abc_impl = <_abc._abc_data object>
abstractmethod close() None[source]
class scratchattach.cloud._base.SupportsRead[source]

Bases: ABC, Generic[T]

_abc_impl = <_abc._abc_data object>
abstractmethod read() T[source]
class scratchattach.cloud._base.WebSocketEventStream(cloud: BaseCloud)[source]

Bases: EventStream

__init__(cloud: BaseCloud)[source]
_abc_impl = <_abc._abc_data object>
close() None[source]
packets_left: list[str | bytes]
read(amount: int = -1) Iterator[dict[str, Any]][source]
reading: allocate_lock
receive_new(non_blocking: bool = False)[source]
source_cloud: BaseCloud

scratchattach.cloud.cloud

v2 ready: ScratchCloud, TwCloud and CustomCloud classes

class scratchattach.cloud.cloud.CustomCloud(*, project_id, cloud_host, **kwargs)[source]

Bases: BaseCloud

__init__(*, project_id, cloud_host, **kwargs)[source]
_abc_impl = <_abc._abc_data object>
_session: session.Session | None
active_connection: bool
allow_non_numeric: bool
cloud_host: str
cookie: dict | None
header: dict | None
length_limit: int
origin: str | None
print_connect_message: bool
project_id: str | int | None
username: str
var_stets_since_first: int
websocket: websocket.WebSocket
ws_longterm_ratelimit: float
ws_shortterm_ratelimit: float
ws_timeout: int | None
class scratchattach.cloud.cloud.ScratchCloud(*, project_id, _session=None)[source]

Bases: BaseCloud

__init__(*, project_id, _session=None)[source]
_abc_impl = <_abc._abc_data object>
_session: session.Session | None
active_connection: bool
allow_non_numeric: bool
cloud_host: str
connect()[source]
cookie: dict | None
events(*, use_logs=False)[source]
get_all_vars(*, use_logs=False)[source]
get_var(var, *, use_logs=False)[source]
header: dict | None
length_limit: int
logs(*, filter_by_var_named=None, limit=100, offset=0) list[CloudActivity][source]

Gets the data from Scratch’s clouddata logs.

Keyword Arguments:
  • filter_by_var_named (str or None) – If you only want to get data for one cloud variable, set this argument to its name.

  • limit (int) – Max. amount of returned activity.

  • offset (int) – Offset of the first activity in the returned list.

  • log_url (str) – If you want to get the clouddata from a cloud log API different to Scratch’s normal cloud log API, set this argument to the URL of the API. Only set this argument if you know what you are doing. If you want to get the clouddata from the normal API, don’t put this argument.

origin: str | None
print_connect_message: bool
project_id: str | int | None
set_var(variable, value)[source]

Sets a cloud variable.

Parameters:
  • variable (str) – The name of the cloud variable that should be set (provided without the cloud emoji)

  • value (str) – The value the cloud variable should be set to

set_vars(var_value_dict, *, intelligent_waits=True)[source]

Sets multiple cloud variables at once (works for an unlimited amount of variables).

Parameters:

var_value_dict (dict) – variable:value dictionary with the variables / values to set. The dict should like this: {“var1”:”value1”, “var2”:”value2”, …}

Kwargs:

intelligent_waits (boolean): When enabled, the method will automatically decide how long to wait before performing this cloud variable set, to make sure no rate limits are triggered

username: str
var_stets_since_first: int
websocket: websocket.WebSocket
ws_longterm_ratelimit: float
ws_shortterm_ratelimit: float
ws_timeout: int | None
class scratchattach.cloud.cloud.TwCloud(*, project_id, cloud_host='wss://clouddata.turbowarp.org', purpose='', contact='', _session=None)[source]

Bases: BaseCloud

__init__(*, project_id, cloud_host='wss://clouddata.turbowarp.org', purpose='', contact='', _session=None)[source]
_abc_impl = <_abc._abc_data object>
_session: session.Session | None
active_connection: bool
allow_non_numeric: bool
cloud_host: str
cookie: dict | None
header: dict | None
length_limit: int
origin: str | None
print_connect_message: bool
project_id: str | int | None
username: str
var_stets_since_first: int
websocket: websocket.WebSocket
ws_longterm_ratelimit: float
ws_shortterm_ratelimit: float
ws_timeout: int | None
scratchattach.cloud.cloud.get_cloud(project_id, *, CloudClass: ~typing.Type[~scratchattach.cloud._base.BaseCloud] = <class 'scratchattach.cloud.cloud.ScratchCloud'>) BaseCloud[source]

Connects to a cloud (by default Scratch’s cloud) as logged out user.

Warning

Since this method doesn’t connect a login / session to the returned object, setting Scratch cloud variables won’t be possible with it.

To set Scratch cloud variables, use scratchattach.site.session.Session.connect_scratch_cloud instead.

Parameters:

project_id

Keyword Arguments:

CloudClass – The class that the returned object should be of. By default this class is scratchattach.cloud.ScratchCloud.

Returns:

An object representing the cloud of a project. Can be of any class inheriting from BaseCloud.

Return type:

Type[scratchattach.cloud._base.BaseCloud]

scratchattach.cloud.cloud.get_scratch_cloud(project_id)[source]

Warning

Since this method doesn’t connect a login / session to the returned object, setting Scratch cloud variables won’t be possible with it.

To set Scratch cloud variables, use scratchattach.Session.connect_scratch_cloud instead.

Returns:

An object representing the Scratch cloud of a project.

Return type:

scratchattach.cloud.ScratchCloud

scratchattach.cloud.cloud.get_tw_cloud(project_id, *, purpose='', contact='', cloud_host='wss://clouddata.turbowarp.org')[source]
Returns:

An object representing the TurboWarp cloud of a project.

Return type:

scratchattach.cloud.TwCloud

scratchattach.eventhandlers

scratchattach.eventhandlers._base

class scratchattach.eventhandlers._base.BaseEventHandler[source]

Bases: ABC

__init__()[source]
_abc_impl = <_abc._abc_data object>
_events: defaultdict[str, list[Callable]]
_threaded_events: defaultdict[str, list[Callable]]
abstractmethod _updater()[source]
call_event(event_name, args: list = [])[source]
event(function=None, *, thread=False)[source]

Decorator function. Adds an event.

pause()[source]

Pauses the event handler.

resume()[source]

Resumes the event handler.

start(*, thread=True, ignore_exceptions=True)[source]

Starts the event handler.

Keyword Arguments:
  • thread (bool) – Whether the event handler should be run in a thread.

  • ignore_exceptions (bool) – Whether to catch exceptions that happen in individual events

stop()[source]

Permanently stops the event handler.

scratchattach.eventhandlers.cloud_events

CloudEvents class

class scratchattach.eventhandlers.cloud_events.CloudEvents(cloud: AnyCloud)[source]

Bases: BaseEventHandler

Class that calls events when on cloud updates that are received through a websocket connection.

__init__(cloud: AnyCloud)[source]
_abc_impl = <_abc._abc_data object>
_events: defaultdict[str, list[Callable]]
_threaded_events: defaultdict[str, list[Callable]]
_updater()[source]

A process that listens for cloud activity and executes events on cloud activity

disconnect()[source]
class scratchattach.eventhandlers.cloud_events.CloudLogEvents(cloud: LogCloud, *, update_interval=0.1)[source]

Bases: BaseEventHandler

Class that calls events on cloud updates that are received from a clouddata log.

__init__(cloud: LogCloud, *, update_interval=0.1)[source]
_abc_impl = <_abc._abc_data object>
_events: defaultdict[str, list[Callable]]
_threaded_events: defaultdict[str, list[Callable]]
_updater()[source]
class scratchattach.eventhandlers.cloud_events.ManualCloudLogEvents(cloud: LogCloud)[source]

Bases: object

Class that calls events on cloud updates that are received from a clouddata log.

__init__(cloud: LogCloud)[source]
update() Iterator[tuple[str, list[CloudActivity]]][source]

Update once and yield all packets

scratchattach.eventhandlers.cloud_recorder

CloudRecorder class (used by ScratchCloud, TwCloud and other classes inheriting from BaseCloud to deliver cloud var values)

class scratchattach.eventhandlers.cloud_recorder.CloudRecorder(cloud, *, initial_values: dict | None = None)[source]

Bases: CloudEvents

__init__(cloud, *, initial_values: dict | None = None)[source]
_abc_impl = <_abc._abc_data object>
_events: defaultdict[str, list[Callable]]
_threaded_events: defaultdict[str, list[Callable]]
get_all_vars()[source]
get_var(var)[source]
on_set(activity)[source]

scratchattach.eventhandlers.cloud_requests

CloudRequests class (threading.Event version)

class scratchattach.eventhandlers.cloud_requests.CloudRequests(cloud, used_cloud_vars=['1', '2', '3', '4', '5', '6', '7', '8', '9'], no_packet_loss=False, respond_order='receive', debug=False)[source]

Bases: CloudEvents

__init__(cloud, used_cloud_vars=['1', '2', '3', '4', '5', '6', '7', '8', '9'], no_packet_loss=False, respond_order='receive', debug=False)[source]
_abc_impl = <_abc._abc_data object>
_events: defaultdict[str, list[Callable]]
_executer()[source]

A process that detects new requests in .received_requests, moves them to .executed_requests and executes them. Only requests not running in threads are handled in this process.

_parse_output(request_name, output, request_id)[source]

Prepares the transmission of the request output to the Scratch project

_request_packet_from_memory(request_id, packet_id)[source]
_respond(request_id, response, *, validation=2222)[source]

Sends back the request response to the Scratch project

_responder()[source]

A process that detects incoming request outputs in .request_outputs and handles them by sending them back to the Scratch project, also removes the corresponding ReceivedRequest object from .executed_requests

_set_FROM_HOST_var(value)[source]
_threaded_events: defaultdict[str, list[Callable]]
add_request(function, *, enabled=True, name=None)[source]
credit_check()[source]
get_exact_timestamp()[source]

Can be used inside a request to get the exact timestamp of when the request was performed.

get_requester()[source]

Can be used inside a request to get the username that performed the request.

get_timestamp()[source]

Can be used inside a request to get the timestamp of when the request was received.

hard_stop()[source]

Stops the request handler and all associated threads forever. Stops running response sending processes immediately.

on_reconnect()[source]

Called when the underlying cloud events reconnect. Makes sure that no requests are missed in this case.

on_set(activity)[source]

This function is automatically called on cloud activites by the underlying cloud events that this CloudRequests class inherits from It registers incoming cloud activity and (if request.thread is True) runs them directly or (else) adds detected request to the .received_requests list

remove_request(name)[source]
request(function=None, *, enabled=True, name=None, thread=True, response_priority=0, debug=False)[source]

Decorator function. Adds a request to the request handler.

run()[source]
send(data, *, priority=0)[source]

Send data to the Scratch project without a priorly received request. The Scratch project will only receive the data if it’s running.

stop()[source]

Stops the request handler and all associated threads forever. Lets running response sending processes finish.

class scratchattach.eventhandlers.cloud_requests.ReceivedRequest(**entries)[source]

Bases: object

__init__(**entries)[source]
class scratchattach.eventhandlers.cloud_requests.Request(request_name, *, on_call, cloud_requests, thread=True, enabled=True, response_priority=0, debug=False)[source]

Bases: object

Saves a request added to the request handler

__init__(request_name, *, on_call, cloud_requests, thread=True, enabled=True, response_priority=0, debug=False)[source]

scratchattach.eventhandlers.cloud_server

class scratchattach.eventhandlers.cloud_server.TwCloudSocket(server, sock, address)[source]

Bases: WebSocket

handleClose()[source]

Called when a websocket server gets a Close frame from a client.

handleConnected()[source]

Called when a websocket client connects to the server.

handleMessage()[source]

Called when websocket frame is received. To access the frame data call self.data.

If the frame is Text then self.data is a unicode object. If the frame is Binary then self.data is a bytearray object.

scratchattach.eventhandlers.cloud_server.init_cloud_server(hostname='127.0.0.1', port=8080, *, thread=True, length_limit=None, allow_non_numeric=True, whitelisted_projects=None, allow_nonscratch_names=True, blocked_ips=[], sync_players=True, log_var_sets=True)[source]

Inits a websocket server which can be used with TurboWarp’s ?cloud_host URL parameter.

Prints out the websocket address in the console.

scratchattach.eventhandlers.cloud_storage

CloudStorage class

class scratchattach.eventhandlers.cloud_storage.CloudStorage(cloud, used_cloud_vars=['1', '2', '3', '4', '5', '6', '7', '8', '9'], no_packet_loss=False)[source]

Bases: CloudRequests

A CloudStorage object saves multiple databases and allows the connected Scratch project to access and modify the data of these databases through cloud requests

The CloudStorage class is built upon CloudRequests

__init__(cloud, used_cloud_vars=['1', '2', '3', '4', '5', '6', '7', '8', '9'], no_packet_loss=False)[source]
_abc_impl = <_abc._abc_data object>
_events: defaultdict[str, list[Callable]]
_threaded_events: defaultdict[str, list[Callable]]
add_database(database: Database)[source]
database_names() list[source]
databases() list[source]
get(db_name, key) str[source]
get_database(name) Database[source]
keys(db_name) list[source]
ping()[source]
save()[source]

Saves the data in the JSON files for all databases in self._databases

set(db_name, key, value)[source]
class scratchattach.eventhandlers.cloud_storage.Database(name, *, json_file_path, save_interval=30)[source]

Bases: object

A Database is a simple key-value storage that stores data in a JSON file saved locally (other database services like MongoDB can be implemented)

__init__(name, *, json_file_path, save_interval=30)[source]
_autosaver()[source]
event(event_function)[source]
get(key) str[source]
keys() list[source]
save_to_json()[source]
set(key, value)[source]

scratchattach.eventhandlers.combine

class scratchattach.eventhandlers.combine.MultiEventHandler(*handlers)[source]

Bases: object

__init__(*handlers)[source]
event(function, *args, **kwargs)[source]
pause(*args, **kwargs)[source]
request(function, *args, **kwargs)[source]
resume(*args, **kwargs)[source]
start(*args, **kwargs)[source]
stop(*args, **kwargs)[source]

scratchattach.eventhandlers.filterbot

FilterBot class

class scratchattach.eventhandlers.filterbot.Filterbot(user, *, log_deletions=True)[source]

Bases: MessageEvents

__init__(user, *, log_deletions=True)[source]
_abc_impl = <_abc._abc_data object>
_events: defaultdict[str, list[Callable]]
_threaded_events: defaultdict[str, list[Callable]]
add_ads_filter()[source]
add_f4f_filter()[source]
add_filter(filter_obj)[source]
add_genalpha_nonsense_filter()[source]
add_spam_filter()[source]
on_message(message)[source]
class scratchattach.eventhandlers.filterbot.HardFilter(filter_name='UntitledFilter', *, equals=None, contains=None, author_name=None, project_id=None, profile=None, case_sensitive=False)[source]

Bases: object

__init__(filter_name='UntitledFilter', *, equals=None, contains=None, author_name=None, project_id=None, profile=None, case_sensitive=False)[source]
apply(content, author_name, source_id)[source]
class scratchattach.eventhandlers.filterbot.SoftFilter(score: float, filter_name='UntitledFilter', *, equals=None, contains=None, author_name=None, project_id=None, profile=None, case_sensitive=False)[source]

Bases: HardFilter

__init__(score: float, filter_name='UntitledFilter', *, equals=None, contains=None, author_name=None, project_id=None, profile=None, case_sensitive=False)[source]
class scratchattach.eventhandlers.filterbot.SpamFilter(filter_name='UntitledFilter', *, equals=None, contains=None, author_name=None, project_id=None, profile=None, case_sensitive=False)[source]

Bases: HardFilter

__init__(filter_name='UntitledFilter', *, equals=None, contains=None, author_name=None, project_id=None, profile=None, case_sensitive=False)[source]
apply(content, author_name, source_id)[source]

scratchattach.eventhandlers.message_events

MessageEvents class

class scratchattach.eventhandlers.message_events.MessageEvents(user, *, update_interval=2)[source]

Bases: BaseEventHandler

Class that calls events when you receive messages on your Scratch account. Data fetched from Scratch’s API.

__init__(user, *, update_interval=2)[source]
_abc_impl = <_abc._abc_data object>
_events: defaultdict[str, list[Callable]]
_threaded_events: defaultdict[str, list[Callable]]
_updater()[source]

A process that listens for cloud activity and executes events on cloud activity

scratchattach.other

scratchattach.other.other_apis

Other Scratch API-related functions

class scratchattach.other.other_apis.ScratchToolsTutorial(title: 'str', description: 'str', id: 'str')[source]

Bases: object

__init__(title: str, description: str, id: str) None
description: str
classmethod from_json(data: dict[str, str]) ScratchToolsTutorial[source]
id: str
title: str
scratchattach.other.other_apis.age_distribution()[source]
scratchattach.other.other_apis.aprilfools_get_counter() int[source]
scratchattach.other.other_apis.aprilfools_increment_counter() int[source]
scratchattach.other.other_apis.check_password(password)[source]
scratchattach.other.other_apis.check_username(username)[source]
scratchattach.other.other_apis.country_counts()[source]
scratchattach.other.other_apis.curated_projects()[source]
scratchattach.other.other_apis.design_studio_projects()[source]
scratchattach.other.other_apis.featured_data()[source]
scratchattach.other.other_apis.featured_projects()[source]
scratchattach.other.other_apis.featured_studios()[source]
scratchattach.other.other_apis.get_csrf_token()[source]

Generates a scratchcsrftoken using Scratch’s API.

Returns:

The generated scratchcsrftoken

Return type:

str

scratchattach.other.other_apis.get_health()[source]
scratchattach.other.other_apis.get_news(*, limit=10, offset=0)[source]
scratchattach.other.other_apis.get_resource_urls()[source]
scratchattach.other.other_apis.get_total_project_count() int[source]
scratchattach.other.other_apis.monthly_active_users()[source]
scratchattach.other.other_apis.monthly_comment_activity()[source]
scratchattach.other.other_apis.monthly_project_shares()[source]
scratchattach.other.other_apis.monthly_site_traffic()[source]
scratchattach.other.other_apis.newest_projects()[source]
scratchattach.other.other_apis.scratch_team_members() dict[source]
scratchattach.other.other_apis.scratchtools_beta_user(username: str) bool[source]

Get whether a user is a scratchtools beta tester (I think that’s what it means)

scratchattach.other.other_apis.scratchtools_display_name(username: str) str | None[source]

Get the display name of a user for scratchtools. Returns none if there is no display name or the username is invalid

scratchattach.other.other_apis.scratchtools_emoji_status(username: str) str | None[source]
scratchattach.other.other_apis.scratchtools_online_status(username: str) bool | None[source]

Get the online status of an account. :return: Boolean whether the account is online; if they do not use scratchtools, return None.

scratchattach.other.other_apis.scratchtools_pinned_comment(project_id: int) dict[str, str | int][source]
scratchattach.other.other_apis.scratchtools_tutorials() list[ScratchToolsTutorial][source]

Returns a list of scratchtools tutorials (just yt videos)

scratchattach.other.other_apis.send_password_reset_email(username: str | None = None, email: str | None = None)[source]
scratchattach.other.other_apis.text2speech(text: str = 'hello', voice_name: str = 'female', language: str = 'en-US')[source]

Sends a request to Scratch’s TTS synthesis service. :returns:

  • The TTS audio (mp3) as bytes

  • The playback rate (e.g. for giant it would be 0.84)

scratchattach.other.other_apis.top_loved()[source]
scratchattach.other.other_apis.top_remixed()[source]
scratchattach.other.other_apis.total_site_stats()[source]
scratchattach.other.other_apis.translate(language: str | Languages, text: str = 'hello')[source]

scratchattach.other.project_json_capabilities

Project JSON reading and editing capabilities. This code is still in BETA, there are still bugs and potential consistency issues to be fixed. New features will be added.

class scratchattach.other.project_json_capabilities.ProjectBody(*, sprites=[], monitors=[], extensions=[], meta=[{'agent': None}], _session=None)[source]

Bases: object

class Asset(**entries)[source]

Bases: BaseProjectBodyComponent

_abc_impl = <_abc._abc_data object>
download(*, filename=None, dir='')[source]
from_json(data: dict)[source]
to_json()[source]
class BaseProjectBodyComponent(**entries)[source]

Bases: ABC

__init__(**entries)[source]
_abc_impl = <_abc._abc_data object>
_generate_new_id()[source]

Generates a new id and updates the id. .. warning:: When done on Block objects, the next_id attribute of the parent block and the parent_id attribute of the next block will NOT be updated by this method.

abstractmethod from_json(data: dict)[source]
abstractmethod to_json()[source]
class Block(**entries)[source]

Bases: BaseProjectBodyComponent

_abc_impl = <_abc._abc_data object>
_reattach(new_parent_id, new_next_id_of_old_parent)[source]
attached_block()[source]
attached_chain()[source]
complete_chain()[source]
delete_chain()[source]
delete_single_block()[source]
duplicate_chain()[source]
duplicate_single_block()[source]
from_json(data: dict)[source]
inputs_as_blocks()[source]
previous_block()[source]
previous_chain()[source]
reattach_chain(new_parent_id)[source]
reattach_single_block(new_parent_id)[source]
to_json()[source]
top_level_block()[source]
class List(**entries)[source]

Bases: BaseProjectBodyComponent

__init__(**entries)[source]
_abc_impl = <_abc._abc_data object>
from_json(data: list)[source]
to_json()[source]
class Monitor(**entries)[source]

Bases: BaseProjectBodyComponent

_abc_impl = <_abc._abc_data object>
from_json(data: dict)[source]
target()[source]
to_json()[source]
class Sprite(**entries)[source]

Bases: BaseProjectBodyComponent

_abc_impl = <_abc._abc_data object>
add_block(block, *, parent_id=None)[source]
add_block_chain(block_chain, *, parent_id=None)[source]
block_by_id(block_id)[source]
create_costume(asset_content, *, name='new costume', dataFormat='svg', rotationCenterX=0, rotationCenterY=0)[source]
create_list(name, *, value=[])[source]
create_sound(asset_content, *, name='new sound', dataFormat='mp3', rate=4800, sampleCount=4800)[source]
create_variable(name, *, value=0, is_cloud=False)[source]
from_json(data: dict)[source]
list_by_id(list_id)[source]
list_by_name(list_name)[source]
to_json()[source]
variable_by_id(variable_id)[source]
variable_by_name(variable_name)[source]
class Variable(**entries)[source]

Bases: BaseProjectBodyComponent

__init__(**entries)[source]
_abc_impl = <_abc._abc_data object>
from_json(data: list)[source]
make_cloud_variable()[source]
to_json()[source]
__init__(*, sprites=[], monitors=[], extensions=[], meta=[{'agent': None}], _session=None)[source]
asset_count()[source]
assets()[source]
block_count()[source]
blocks()[source]
from_json(data: dict)[source]

Imports the project data from a dict that contains the raw project json

list_by_id(list_id)[source]
save(*, filename=None, dir='')[source]

Saves the project body to the given directory. :param filename: The name that will be given to the downloaded file. :type filename: str :param dir: The path of the directory the file will be saved in. :type dir: str

sprite_by_name(sprite_name)[source]
to_json()[source]

Returns a valid project JSON dict with the contents of this project

user_agent()[source]
variable_by_id(variable_id)[source]
scratchattach.other.project_json_capabilities._load_sb3_file(path_to_file)[source]
scratchattach.other.project_json_capabilities.download_asset(asset_id_with_file_ext, *, filename=None, dir='')[source]
scratchattach.other.project_json_capabilities.get_empty_project_pb()[source]
scratchattach.other.project_json_capabilities.get_pb_from_dict(project_json: dict)[source]
scratchattach.other.project_json_capabilities.load_components(json_data: list, ComponentClass: type, target_list: list)[source]
scratchattach.other.project_json_capabilities.read_sb3_file(path_to_file)[source]

scratchattach.site

scratchattach.site._base

class scratchattach.site._base.BaseSiteComponent[source]

Bases: ABC

_abc_impl = <_abc._abc_data object>
_assert_auth()[source]
_cookies: dict[str, str]
_headers: dict[str, str]
_make_linked_object(identificator_id, identificator, Class: type[C], NotFoundException) C[source]

Internal function for making a linked object (authentication kept) based on an identificator (like a project id or username) Class must inherit from BaseSiteComponent

_session: Session | None
abstractmethod _update_from_dict(data) bool[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

update()[source]

Updates the attributes of the object by performing an API response. Returns True if the update was successful.

update_api: str
update_function(params=None, **kwargs)

Internal function run on update. Function is a method of the ‘requests’ module/class

scratchattach.site.activity

Activity and CloudActivity class

class scratchattach.site.activity.Activity(**entries)[source]

Bases: BaseSiteComponent

Represents a Scratch activity (message or other user page activity)

__init__(**entries)[source]
_abc_impl = <_abc._abc_data object>
_cookies: dict[str, str]
_headers: dict[str, str]
_session: session.Session | None
_update_from_dict(data)[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

_update_from_html(data: PageElement)[source]
_update_from_json(data: dict)[source]

Update using JSON, used in the classroom API.

actor()[source]

Returns the user that performed the activity as User object

target()[source]

Returns the activity’s target (depending on the activity, this is either a User, Project, Studio or Comment object). May also return None if the activity type is unknown.

update()[source]

Updates the attributes of the object by performing an API response. Returns True if the update was successful.

update_api: str

scratchattach.site.backpack_asset

class scratchattach.site.backpack_asset.BackpackAsset(**entries)[source]

Bases: BaseSiteComponent

Represents an asset from the backpack.

Attributes:

.id:

.type:

The asset type (costume, script etc.)

.mime:

The format in which the content of the backpack asset is saved

.name:

The name of the backpack asset

.filename:

Filename of the file containing the content of the backpack asset

.thumbnail_url:

Link that leads to the asset’s thumbnail (the image shown in the backpack UI)

.download_url:

Link that leads to a file containing the content of the backpack asset

__init__(**entries)[source]
_abc_impl = <_abc._abc_data object>
_cookies: dict[str, str]
property _data_bytes: bytes
_headers: dict[str, str]
_session: session.Session | None
_update_from_dict(data) bool[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

property data: dict | list | int | None | str | bytes | float
delete()[source]
download(*, fp: str = '')[source]

Downloads the asset content to the given directory. The given filename is equal to the value saved in the .filename attribute.

Parameters:

fp (str) – The path of the directory the file will be saved in.

property file_ext
property is_json
update()[source]

Updates the attributes of the object by performing an API response. Returns True if the update was successful.

update_api: str

scratchattach.site.cloud_activity

class scratchattach.site.cloud_activity.CloudActivity(**entries)[source]

Bases: BaseSiteComponent

Represents a cloud activity (a cloud variable set / creation / deletion).

Attributes:

.username:

The user who caused the cloud event (the user who added / set / deleted the cloud variable)

.var:

The name of the cloud variable that was updated (specified without the cloud emoji)

.name:

The name of the cloud variable that was updated (specified without the cloud emoji)

.type:

The activity type

.timestamp:

Then timestamp of when the action was performed

.value:

If the cloud variable was set, then this attribute provides the value the cloud variable was set to

.cloud:

The cloud (as object inheriting from scratchattach.Cloud.BaseCloud) that the cloud activity corresponds to

__init__(**entries)[source]
_abc_impl = <_abc._abc_data object>
_cookies: dict[str, str]
_headers: dict[str, str]
_session: session.Session | None
_update_from_dict(data) bool[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

actor()[source]

Returns the user that performed the cloud activity as scratchattach.user.User object

load_log_data()[source]
project()[source]

Returns the project where the cloud activity was performed as scratchattach.project.Project object

update()[source]

Updates the attributes of the object by performing an API response. Returns True if the update was successful.

update_api: str

scratchattach.site.comment

Comment class

class scratchattach.site.comment.Comment(**entries)[source]

Bases: BaseSiteComponent

Represents a Scratch comment (on a profile, studio or project)

__init__(**entries)[source]
_abc_impl = <_abc._abc_data object>
_update_from_dict(data)[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

author() User[source]
cached_parent_comment: Comment | None
cached_replies: list[Comment] | None
commentee_id: int | None
content: Any
delete()[source]

Deletes the comment.

id: int | str
parent_comment() Comment | None[source]
parent_id: int | str | None
place() User | Studio | Project[source]

Returns the place (the project, profile or studio) where the comment was posted as Project, User, or Studio object.

If the place can’t be traced back, None is returned.

replies(*, use_cache: bool = True, limit=40, offset=0)[source]
Keyword Arguments:

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.

reply(content, *, commentee_id=None)[source]

Posts a reply comment to the comment.

Warning

Scratch only shows comments replying to top-level comments, and all replies to replies are actually replies to top-level comments in the API.

Therefore, if this comment is a reply, this method will not reply to the comment itself but to the corresponding top-level comment.

Parameters:

content (str) – Comment content to post.

Keyword Arguments:

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.

Returns:

The created comment.

Return type:

scratchattach.Comment

report()[source]

Reports the comment to the Scratch team.

source: str
source_id: int | str
property text: str
update()[source]

Updates the attributes of the object by performing an API response. Returns True if the update was successful.

scratchattach.site.forum

ForumTopic and ForumPost classes

class scratchattach.site.forum.ForumPost(id: int = 0, topic_id: int = 0, topic_name: str = '', topic_category: str = '', topic_num_pages: int = 0, author_name: str = '', author_avatar_url: str = '', posted: str = '', deleted: bool = False, html_content: str = '', content: str = '', post_index: int = 0, _session: Session | None = None)[source]

Bases: BaseSiteComponent

Represents a Scratch forum post.

Attributes:

.id:

.author_name:

The name of the user who created this post

.author_avatar_url:

.posted:

The date the post was made

.topic_id:

The id of the topic this post is in

.topic_name:

The name of the topic the post is in

.topic_category:

The name of the category the post topic is in

.topic_num_pages:

The number of pages the post topic has

.deleted:

Whether the post was deleted (always False because deleted posts can’t be retrieved anymore)

.html_content:

Returns the content as HTML

.content:

Returns the content as text

.post_index:

The index that the post has in the topic

.update():

Updates the attributes

__init__(id: int = 0, topic_id: int = 0, topic_name: str = '', topic_category: str = '', topic_num_pages: int = 0, author_name: str = '', author_avatar_url: str = '', posted: str = '', deleted: bool = False, html_content: str = '', content: str = '', post_index: int = 0, _session: Session | None = None) None
_abc_impl = <_abc._abc_data object>
_session: Session | None = None
_update_from_dict(data: dict[str, Any])[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

_update_from_html(soup_html: Tag)[source]
author()[source]
Returns:

An object representing the user who created this forum post.

Return type:

scratchattach.user.User

author_avatar_url: str = ''
author_name: str = ''
content: str = ''
deleted: bool = False
edit(new_content: str)[source]

Changes the content of the forum post. You can only use this function if this object was created using scratchattach.session.Session.connect_post() or through another method that requires authentication. You must own the forum post.

Parameters:

new_content (str) – The text that the forum post will be set to.

html_content: str = ''
id: int = 0
ocular_reactions()[source]
post_index: int = 0
posted: str = ''
topic()[source]
Returns:

An object representing the forum topic this post is in.

Return type:

scratchattach.forum.ForumTopic

topic_category: str = ''
topic_id: int = 0
topic_name: str = ''
topic_num_pages: int = 0
update()[source]

Updates the attributes of the ForumPost object. As there is no API for retrieving a single post anymore, this requires reloading the forum page.

update_from_html(soup_html: Tag)[source]
update_function(*args, **kwargs)[source]

Sends a GET request.

Parameters:
  • url – URL for the new Request object.

  • params – (optional) Dictionary, list of tuples or bytes to send in the query string for the Request.

  • **kwargs – Optional arguments that request takes.

Returns:

Response object

Return type:

requests.Response

class scratchattach.site.forum.ForumTopic(id: int, title: str, category_name: str, last_updated: str, _session: Session | None = None, reply_count: int | None = None, view_count: int | None = None)[source]

Bases: BaseSiteComponent

Represents a Scratch forum topic.

Attributes:

.id:

.title:

.category_name:

.last_updated:

Attributes only available if the object was created using scratchattach.get_topic_list or scratchattach.Session.connect_topic_list:

.reply_count:

.view_count:

.update():

Updates the attributes

__init__(id: int, title: str, category_name: str, last_updated: str, _session: Session | None = None, reply_count: int | None = None, view_count: int | None = None) None
_abc_impl = <_abc._abc_data object>
_session: Session | None = None
_update_from_dict(data: dict[str, Any])[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

category_name: str
first_post()[source]
Returns:

An object representing the first topic post

Return type:

scratchattach.forum.ForumPost

classmethod from_id(_ForumTopic__id: int, session: Session, update: bool = False)[source]
id: int
last_updated: str
posts(*, page=1, order='oldest') list[ForumPost][source]
Parameters:

page (int) – The page of the forum topic that should be returned. First page is at index 1.

Returns:

A list containing the posts from the specified page of the forum topic

Return type:

list<scratchattach.forum.ForumPost>

reply_count: int | None = None
title: str
update()[source]

Updates the attributes of the object by performing an API response. Returns True if the update was successful.

view_count: int | None = None
scratchattach.site.forum.get_topic(topic_id) ForumTopic[source]

Gets a forum topic without logging in. Data received from Scratch’s RSS feed XML API.

Parameters:

topic_id (int) – ID of the requested forum topic

Returns:

An object representing the requested forum topic

Return type:

scratchattach.forum.ForumTopic

Warning

Scratch’s API uses very heavy caching for logged out users, therefore the returned data will not be up to date.

Any methods that require authentication will not work on the returned object.

If you need up-to-date data or want to use methods that require authentication, create the object with scratchattach.session.Session.connect_topic() instead.

scratchattach.site.forum.get_topic_list(category_id, *, page=1)[source]

Gets the topics from a forum category without logging in. Data web-scraped from Scratch’s forums UI.

Parameters:

category_id (str) – ID of the forum category

Keyword Arguments:

page (str) – Page of the category topics that should be returned

Returns:

A list containing the forum topics from the specified category

Return type:

list<scratchattach.forum.ForumTopic>

Warning

Scratch’s API uses very heavy caching for logged out users, therefore the returned data will not be up to date.

Any methods that require authentication will not work on the returned objects.

If you need up-to-date data or want to use methods that require authentication, get the forum topics with scratchattach.session.Session.connect_topic_list() instead.

Converts a YouTube url (in multiple formats) like https://youtu.be/1JTgg4WVAX8?si=fIEskaEaOIRZyTAz to a link like https://scratch.mit.edu/discuss/youtube/1JTgg4WVAX8

scratchattach.site.project

Project and PartialProject classes

class scratchattach.site.project.PartialProject(**entries)[source]

Bases: BaseSiteComponent

Represents an unshared Scratch project that can’t be accessed.

__init__(**entries)[source]
_abc_impl = <_abc._abc_data object>
_cookies: dict[str, str]
_headers: dict[str, str]
_session: session.Session | None
_update_from_dict(data)[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

create_remix(*, title=None, project_json=None)[source]

Creates a project on the Scratch website.

Warning

Don’t spam this method - it WILL get you banned from Scratch. To prevent accidental spam, a rate limit (5 projects per minute) is implemented for this function.

property embed_url

Returns: the url of the embed of the project

is_shared()[source]
Returns:

Returns whether the project is currently shared

Return type:

boolean

load_description()[source]

Gets the instructions of the unshared project. Requires authentication.

Warning

It’s unclear if Scratch allows using this method. This method will create a remix of the unshared project using your account.

raw_json_or_empty() dict[str, Any][source]
remixes(*, limit=40, offset=0)[source]
Returns:

A list containing the remixes of the project, each project is represented by a Project object.

Return type:

list<scratchattach.project.Project>

update_api: str
class scratchattach.site.project.Project(**entries)[source]

Bases: PartialProject

Represents a Scratch project.

Attributes:

.id:

The project id

.url:

The project url

.title:

.author_name:

The username of the author

.comments_allowed:

boolean that is True if comments are enabled

.instructions:

.notes:

The ‘Notes and Credits’ section

.created:

The date of the project creation

.last_modified:

The date when the project was modified the last time

.share_date:

.thumbnail_url:

.remix_parent:

.remix_root:

.loves:

The project’s love count

.favorites:

The project’s favorite count

.remix_count:

The number of remixes

.views:

The view count

.project_token:

The project token (required to access the project json)

.update():

Updates the attributes

_abc_impl = <_abc._abc_data object>
_assert_permission()[source]
_cookies: dict[str, str]
_headers: dict[str, str]
_session: session.Session | None
author()[source]
Returns:

An object representing the Scratch user who created this project.

Return type:

scratchattach.user.User

body()[source]

Method only works for project created with Scratch 3.

Returns:

The contents of the project as ProjectBody object

Return type:

scratchattach.ProjectBody

comment_by_id(comment_id)[source]
Returns:

A Comment object representing the requested comment.

Return type:

scratchattach.comments.Comment

comment_replies(*, comment_id, limit=40, offset=0)[source]
comments(*, limit=40, offset=0) list[Comment][source]

Returns the comments posted on the project (except for replies. To get replies use scratchattach.project.Project.comment_replies()).

Keyword Arguments:
  • page – The page of the comments that should be returned.

  • limit – Max. amount of returned comments.

Returns:

A list containing the requested comments as Comment objects.

Return type:

list<scratchattach.comment.Comment>

creator_agent()[source]

Method only works for project created with Scratch 3.

Returns:

The user agent of the browser that this project was saved with.

Return type:

str

delete_comment(*, comment_id)[source]

Deletes a comment by its ID. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

Parameters:

comment_id – The id of the comment that should be deleted

download(*, filename=None, dir='')[source]

Downloads the project json to the given directory.

Parameters:
  • filename (str) – The name that will be given to the downloaded file.

  • dir (str) – The path of the directory the file will be saved in.

favorite()[source]

Posts a favorite on the project. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

get_json() str[source]

Downloads the project json and returns it as a string

load_description()[source]

Gets the instructions of the unshared project. Requires authentication.

Warning

It’s unclear if Scratch allows using this method. This method will create a remix of the unshared project using your account.

love()[source]

Posts a love on the project. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

moderation_status()[source]

Gets information about the project’s moderation status. Fetched from jeffalo’s API.

Returns:

The moderation status of the project.

Return type:

str

These moderation statuses exist:

safe: The project was reviewed by the Scratch team and was considered safe for everyone.

notsafe: The project was reviewed by the Scratch team and was considered not safe for everyone (nfe). It can’t appear in search results, on the explore page and on the front page.

notreviewed: The project hasn’t been reviewed yet.

no_remixes: Unable to fetch the project’s moderation status.

post_comment(content, *, parent_id='', commentee_id='')[source]

Posts a comment on the project. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

Parameters:

content – Content of the comment that should be posted

Keyword Arguments:
  • parent_id – ID of the comment you want to reply to. If you don’t want to mention a user, don’t put the argument.

  • commentee_id – ID of the user that will be mentioned in your comment and will receive a message about your comment. If you don’t want to mention a user, don’t put the argument.

Returns:

Comment object representing the posted comment.

Return type:

scratchattach.comments.Comment

post_view()[source]

Increases the project’s view counter by 1. Doesn’t require a login.

ranks()[source]

Gets information about the project’s ranks. Fetched from ScratchDB.

Warning

This method is deprecated because ScratchDB is down indefinitely.

Returns:

A dict containing the project’s ranks. If the ranks aren’t available, all values will be -1.

Return type:

dict

raw_json()[source]

Method only works for project created with Scratch 3.

Returns:

The raw project JSON as decoded Python dictionary

Return type:

dict

raw_json_or_empty()[source]
reply_comment(content, *, parent_id, commentee_id='')[source]

Posts a reply to a comment on the project. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

Parameters:

content – Content of the comment that should be posted

Warning

Only replies to top-level comments are shown on the Scratch website. Replies to replies are actually replies to the corresponding top-level comment in the API.

Therefore, parent_id should be the comment id of a top level comment.

Keyword Arguments:
  • parent_id – ID of the comment you want to reply to

  • commentee_id – ID of the user you are replying to

report_comment(*, comment_id)[source]

Reports a comment by its ID to the Scratch team. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

Parameters:

comment_id – The id of the comment that should be reported

set_body(project_body: ProjectBody)[source]

Sets the project’s contents You can use this to upload projects to the Scratch website. Returns a dict with Scratch’s raw JSON API response.

Parameters:

project_body (scratchattach.ProjectBody) – A ProjectBody object containing the contents of the project

set_fields(fields_dict, *, use_site_api=False)[source]

Sets fields. By default, ueses the api.scratch.mit.edu/projects/xxx/ PUT API.

Keyword Arguments: use_site_api (bool):

When enabled, the fields are set using the scratch.mit.edu/site-api API. This function allows setting more fields than Project.set_fields. For example you can also share / unshare the project by setting the “shared” field. According to the Scratch team, this API is deprecated. As of 2024 it’s still fully functional tho.

set_instructions(text)[source]

Changes the projects instructions. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

set_json(json_data)[source]

Sets the project json. You can use this to upload projects to the Scratch website. Returns a dict with Scratch’s raw JSON API response.

Parameters:

json_data (dict or JSON) – The new project JSON as encoded JSON object or as dict

set_notes(text)[source]

Changes the projects notes and credits. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

set_thumbnail(*, file)[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_project()

set_title(text)[source]

Changes the projects title. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

share()[source]

Shares the project. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

studios(*, limit=40, offset=0)[source]
Returns:

A list containing the studios this project is in, each studio is represented by a Studio object.

Return type:

list<scratchattach.studio.Studio>

toggle_commenting()[source]

Switches commenting on / off on the project (If comments are on, they will be turned off, else they will be turned on). You can only use this function if this object was created using scratchattach.session.Session.connect_project()

turn_off_commenting()[source]

Disables commenting on the project. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

turn_on_commenting()[source]

Enables commenting on the project. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

unfavorite()[source]

Removes the favorite from this project. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

unlove()[source]

Removes the love from this project. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

unshare()[source]

Unshares the project. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

update_api: str
upload_json_from(project_id)[source]

Uploads the project json from the project with the given id to the project represented by this Project object

visibility()[source]

Returns info about the project’s visibility. Requires authentication.

scratchattach.site.project.explore_projects(*, query='*', mode='trending', language='en', limit=40, offset=0)[source]

Gets projects from the explore page.

Keyword Arguments:
  • query (str) – Specifies the tag of the explore page. To get the projects from the “All” tag, set this argument to “*”.

  • mode (str) – Has to be one of these values: “trending”, “popular” or “recent”. Defaults to “trending”.

  • language (str) – A language abbreviation, defaults to “en”. (Depending on the language used on the Scratch website, Scratch displays you different explore pages.)

  • limit (int) – Max. amount of returned projects.

  • offset (int) – Offset of the first returned project.

Returns:

List that contains the explore page projects.

Return type:

list<scratchattach.project.Project>

scratchattach.site.project.get_project(project_id) Project[source]

Gets a project without logging in.

Parameters:

project_id (int) – Project id of the requested project

Returns:

An object representing the requested project.

Return type:

scratchattach.project.Project

Warning

Any methods that require authentication (like project.love) will not work on the returned object.

If you want to use these methods, get the project with scratchattach.session.Session.connect_project() instead.

scratchattach.site.project.search_projects(*, query='', mode='trending', language='en', limit=40, offset=0)[source]

Uses the Scratch search to search projects.

Keyword Arguments:
  • query (str) – The query that will be searched.

  • mode (str) – Has to be one of these values: “trending”, “popular” or “recent”. Defaults to “trending”.

  • language (str) – A language abbreviation, defaults to “en”. (Depending on the language used on the Scratch website, Scratch displays you different results.)

  • limit (int) – Max. amount of returned projects.

  • offset (int) – Offset of the first returned project.

Returns:

List that contains the search results.

Return type:

list<scratchattach.project.Project>

scratchattach.site.session

Session class and login function

class scratchattach.site.session.Session(username: str = None, _user: User = None, id: str = None, session_string: str | None = None, xtoken: str = None, email: str = None, new_scratcher: bool = None, mute_status: Any = None, banned: bool = None, is_teacher: bool = None, time_created: datetime = None, language: str = 'en')[source]

Bases: BaseSiteComponent

Represents a Scratch log in / session. Stores authentication data (session id and xtoken).

id

The session id associated with the login

Type:

str

username

The username associated with the login

Type:

str

xtoken

The xtoken associated with the login

Type:

str

email

The email address associated with the logged in account

Type:

str

new_scratcher

True if the associated account is a new Scratcher

Type:

bool

mute_status

Information about commenting restrictions of the associated account

Type:

Any

banned

Returns True if the associated account is banned

Type:

bool

__init__(username: str = None, _user: User = None, id: str = None, session_string: str | None = None, xtoken: str = None, email: str = None, new_scratcher: bool = None, mute_status: Any = None, banned: bool = None, is_teacher: bool = None, time_created: datetime = None, language: str = 'en') None
_abc_impl = <_abc._abc_data object>
_make_linked_object(identificator_name, identificator, _Session__class: type[C], NotFoundException: type[Exception]) C[source]

The Session class doesn’t save the login in a ._session attribute, but IS the login ITSELF.

Therefore, the _make_linked_object method has to be adjusted to get it to work for in the Session class.

Class must inherit from BaseSiteComponent

_process_session_id()[source]
_update_from_dict(data: dict)[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

_user: user.User = None
admin_messages(*, limit=40, offset=0) list[dict][source]

Returns your messages sent by the Scratch team (alerts).

backpack(limit: int = 20, offset: int = 0) list[BackpackAsset][source]

Lists the assets that are in the backpack of the user associated with the session.

Returns:

List that contains the backpack items

Return type:

list<backpack_asset.BackpackAsset>

banned: bool = None
become_scratcher_invite() dict[source]

If you are a new Scratcher and have been invited for becoming a Scratcher, this API endpoint will provide more info on the invite.

classroom_alerts(_classroom: Classroom | int | None = None, mode: str = 'Last created', page: int | None = None)[source]

Load and parse admin alerts, optionally for a specific class, using https://scratch.mit.edu/site-api/classrooms/alerts/

Returns:

A list of parsed EducatorAlert objects

Return type:

list[alert.EducatorAlert]

clear_messages()[source]

Clears all messages.

connect_classroom(class_id) Classroom[source]

Gets a class using this session.

Parameters:

class_id (str) – class id of the requested class

Returns:

An object representing the requested classroom

Return type:

scratchattach.classroom.Classroom

connect_classroom_from_token(class_token) Classroom[source]

Gets a class using this session.

Parameters:

class_token (str) – class token of the requested class

Returns:

An object representing the requested classroom

Return type:

scratchattach.classroom.Classroom

connect_cloud(project_id, *, cloud_class: type[T]) T[source]
connect_cloud(project_id) ScratchCloud
static connect_empty_project_pb() ProjectBody[source]
connect_filterbot(*, log_deletions=True) Filterbot[source]
connect_linked_user() User[source]

Gets the user associated with the login / session.

Warning

The returned User object is cached. To ensure its attribute are up to date, you need to run .update() on it.

Returns:

Object representing the user associated with the session.

Return type:

scratchattach.user.User

connect_message_events(*, update_interval=2) MessageEvents[source]
static connect_pb_from_dict(project_json: dict) ProjectBody[source]
static connect_pb_from_file(path_to_file) ProjectBody[source]
connect_project(project_id) Project[source]

Gets a project using this session, connects the session to the Project object to allow authenticated actions

sess
Args:

project_id (int): ID of the requested project

Returns:

scratchattach.project.Project: An object that represents the requested project and allows you to perform actions on the project (like project.love)

connect_scratch_cloud(project_id) ScratchCloud[source]
Returns:

An object representing the Scratch cloud of a project.

Return type:

scratchattach.cloud.ScratchCloud

connect_studio(studio_id) Studio[source]

Gets a studio using this session, connects the session to the Studio object to allow authenticated actions

Parameters:

studio_id (int) – ID of the requested studio

Returns:

An object that represents the requested studio and allows you to perform actions on the studio (like studio.follow)

Return type:

scratchattach.studio.Studio

connect_topic(topic_id) ForumTopic[source]

Gets a forum topic using this session, connects the session to the ForumTopic object to allow authenticated actions Data is up-to-date. Data received from Scratch’s RSS feed XML API.

Parameters:

topic_id (int) – ID of the requested forum topic (can be found in the browser URL bar)

Returns:

An object that represents the requested forum topic

Return type:

scratchattach.forum.ForumTopic

connect_topic_list(category_id, *, page=1)[source]

Gets the topics from a forum category. Data web-scraped from Scratch’s forums UI. Data is up-to-date.

Parameters:

category_id (str) – ID of the forum category

Keyword Arguments:

page (str) – Page of the category topics that should be returned

Returns:

A list containing the forum topics from the specified category

Return type:

list<scratchattach.forum.ForumTopic>

connect_tw_cloud(project_id, *, purpose='', contact='', cloud_host='wss://clouddata.turbowarp.org') TwCloud[source]
Returns:

An object representing the TurboWarp cloud of a project.

Return type:

scratchattach.cloud.TwCloud

connect_user(username: str) User[source]

Gets a user using this session, connects the session to the User object to allow authenticated actions

Parameters:

username (str) – Username of the requested user

Returns:

An object that represents the requested user and allows you to perform actions on the user (like user.follow)

Return type:

scratchattach.user.User

connect_user_by_id(user_id: int) User[source]

Gets a user using this session, connects the session to the User object to allow authenticated actions

This method … 1) gets the username by posting a comment with the user_id as commentee_id. 2) deletes the posted comment. 3) fetches other information about the user using Scratch’s api.scratch.mit.edu/users/username API.

Warning

Every time this functions is run, a comment on your profile is posted and deleted. Therefore, you shouldn’t run this too often.

Parameters:

user_id (int) – User ID of the requested user

Returns:

An object that represents the requested user and allows you to perform actions on the user (like user.follow)

Return type:

scratchattach.user.User

create_class(title: str, desc: str = '') Classroom[source]

Create a class on the scratch website

Warning

Don’t spam this method - it WILL get you banned from Scratch. To prevent accidental spam, a rate limit (5 classes per minute) is implemented for this function.

create_project(*, title: str | None = None, project_json: dict = {'extensions': [], 'meta': {'agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36', 'semver': '3.0.0', 'vm': '2.3.0'}, 'monitors': [], 'targets': [{'blocks': {}, 'broadcasts': {}, 'comments': {}, 'costumes': [{'assetId': '14e46ec3e2ba471c2adfe8f119052307', 'bitmapResolution': 1, 'dataFormat': 'svg', 'md5ext': '14e46ec3e2ba471c2adfe8f119052307.svg', 'name': '', 'rotationCenterX': 0, 'rotationCenterY': 0}], 'currentCostume': 0, 'isStage': True, 'layerOrder': 0, 'lists': {}, 'name': 'Stage', 'sounds': [], 'tempo': 60, 'textToSpeechLanguage': None, 'variables': {'`jEk@4|i[#Fk?(8x)AV.-my variable': ['my variable', 0]}, 'videoState': 'on', 'videoTransparency': 50, 'volume': 100}]}, parent_id=None) Project[source]

Creates a project on the Scratch website.

Warning

Don’t spam this method - it WILL get you banned from Scratch. To prevent accidental spam, a rate limit (5 projects per minute) is implemented for this function.

create_studio(*, title: str | None = None, description: str | None = None) Studio[source]

Create a studio on the scratch website

Warning

Don’t spam this method - it WILL get you banned from Scratch. To prevent accidental spam, a rate limit (5 studios per minute) is implemented for this function.

delete_from_backpack(backpack_asset_id) BackpackAsset[source]

Deletes an asset from the backpack.

Parameters:

backpack_asset_id – ID of the backpack asset that will be deleted

static download_asset(asset_id_with_file_ext, *, filename: str | None = None, fp='')[source]
email: str = None
explore_projects(*, query: str = '*', mode: str = 'trending', language: str = 'en', limit: int = 40, offset: int = 0) list[Project][source]

Gets projects from the explore page.

Keyword Arguments:
  • query (str) – Specifies the tag of the explore page. To get the projects from the “All” tag, set this argument to “*”.

  • mode (str) – Has to be one of these values: “trending”, “popular” or “recent”. Defaults to “trending”.

  • language (str) – A language abbreviation, defaults to “en”. (Depending on the language used on the Scratch website, Scratch displays you different explore pages.)

  • limit (int) – Max. amount of returned projects.

  • offset (int) – Offset of the first returned project.

Returns:

List that contains the explore page projects.

Return type:

list<scratchattach.project.Project>

explore_studios(*, query: str = '', mode: str = 'trending', language: str = 'en', limit: int = 40, offset: int = 0) list[Studio][source]
feed(*, limit=20, offset=0, date_limit=None) list[Activity][source]

Returns the “What’s happening” section (frontpage).

Returns:

List that contains all “What’s happening” entries as Activity objects

Return type:

list<scratch.activity.Activity>

find_username_from_id(user_id: int) str[source]

Warning

Every time this functions is run, a comment on your profile is posted and deleted. Therefore you shouldn’t run this too often.

Returns:

The username that corresponds to the user id

Return type:

str

get_cookies() dict[str, str][source]
get_feed(*, limit=20, offset=0, date_limit=None)[source]
get_headers() dict[str, str][source]
get_linked_user() User[source]
get_new_email_address() str[source]

Gets the (unconfirmed) email address that this session has requested to transfer to, if any, otherwise the current address.

Returns:

The email that this session wants to switch to

Return type:

str

get_session_string() str[source]
id: str = None
is_teacher: bool = None
language: str = 'en'
logout()[source]

Sends a logout request to scratch. (Might not do anything, might log out this account on other ips/sessions.)

loved_by_followed_users(*, limit=40, offset=0) list[Project][source]

Returns the “Projects loved by Scratchers I’m following” section (frontpage).

Returns:

List that contains all “Projects loved by Scratchers I’m following” entries as Project objects

Return type:

list<scratchattach.project.Project>

message_count() int[source]

Returns the message count.

Returns:

message count

Return type:

int

messages(*, limit: int = 40, offset: int = 0, date_limit=None, filter_by=None) list[Activity][source]

Returns the messages.

Keyword Arguments:
  • date_limit (limit, offset,)

  • filter_by (str or None) – Can either be None (no filter), “comments”, “projects”, “studios” or “forums”

Returns:

List that contains all messages as Activity objects.

Return type:

list<scratch.activity.Activity>

mute_status: Any = None
mystuff_classes(mode: str = 'Last created', page: int | None = None) list[Classroom][source]
mystuff_ended_classes(mode: str = 'Last created', page: int | None = None) list[Classroom][source]
mystuff_projects(filter_arg: str = 'all', *, page: int = 1, sort_by: str = '', descending: bool = True) list[Project][source]

Gets the projects from the “My stuff” page.

Parameters:

filter_arg (str) – Possible values for this parameter are “all”, “shared”, “unshared” and “trashed”

Keyword Arguments:
  • page (int) – The page of the “My Stuff” projects that should be returned

  • sort_by (str) – The key the projects should be sorted based on. Possible values for this parameter are “” (then the projects are sorted based on last modified), “view_count”, love_count”, “remixers_count” (then the projects are sorted based on remix count) and “title” (then the projects are sorted based on title)

  • descending (boolean) – Determines if the element with the highest key value (the key is specified in the sort_by argument) should be returned first. Defaults to True.

Returns:

A list with the projects from the “My Stuff” page, each project is represented by a Project object.

Return type:

list<scratchattach.project.Project>

mystuff_studios(filter_arg: str = 'all', *, page: int = 1, sort_by: str = '', descending: bool = True) list[Studio][source]
property new_email_address: str

Gets the (unconfirmed) email address that this session has requested to transfer to, if any, otherwise the current address.

Returns:

The email that this session wants to switch to

Return type:

str

new_scratcher: bool = None
resend_email(password: str)[source]

Sends a request to resend a confirmation email for this session’s account

Keyword Arguments:

password (str) – Password associated with the session (not stored)

search_projects(*, query: str = '', mode: str = 'trending', language: str = 'en', limit: int = 40, offset: int = 0) list[Project][source]

Uses the Scratch search to search projects.

Keyword Arguments:
  • query (str) – The query that will be searched.

  • mode (str) – Has to be one of these values: “trending”, “popular” or “recent”. Defaults to “trending”.

  • language (str) – A language abbreviation, defaults to “en”. (Depending on the language used on the Scratch website, Scratch displays you different results.)

  • limit (int) – Max. amount of returned projects.

  • offset (int) – Offset of the first returned project.

Returns:

List that contains the search results.

Return type:

list<scratchattach.project.Project>

search_studios(*, query: str = '', mode: str = 'trending', language: str = 'en', limit: int = 40, offset: int = 0) list[Studio][source]
session_string: str | None = None
set_country(country: str = 'Antarctica')[source]

Sets the profile country of the session’s associated user

Parameters:

country (str) – The country to relocate to

time_created: datetime.datetime = None
upload_asset(asset_content, *, asset_id=None, file_ext=None)[source]
username: str = None
xtoken: str = None
scratchattach.site.session.decode_session_id(session_id: str) tuple[dict[str, str], datetime][source]

Extract the JSON data from the main part of a session ID string Session id is in the format: <p1: long base64 string>:<p2: short base64 string>:<p3: medium base64 string>

p1 contains a base64-zlib compressed JSON string p2 is a base 62 encoded timestamp p3 might be a synchronous signature for the first 2 parts (might be useless for us)

The dict has these attributes: - username - _auth_user_id - testcookie - _auth_user_backend - token - login-ip - _language - django_timezone - _auth_user_hash

scratchattach.site.session.enforce_ratelimit(__type: str, name: str, amount: int = 5, duration: int = 60) None[source]
scratchattach.site.session.issue_login_warning() None[source]

Issue a login data warning.

scratchattach.site.session.login(username, password, *, timeout=10) Session[source]

Creates a session / log in to the Scratch website with the specified username and password.

This method … 1. creates a session id by posting a login request to Scratch’s login API. (If this fails, scratchattach.exceptions.LoginFailure is raised) 2. fetches the xtoken and other information by posting a request to scratch.mit.edu/session. (If this fails, a warning is displayed)

Parameters:
  • username (str)

  • password (str)

Keyword Arguments:

timeout (int) – Timeout for the request to Scratch’s login API (in seconds). Defaults to 10.

Returns:

An object that represents the created login / session

Return type:

scratchattach.session.Session

scratchattach.site.session.login_by_file(file: FileDescriptorOrPath) Session[source]

Login using a path to a file.

scratchattach.site.session.login_by_id(session_id: str, *, username: str | None = None, password: str | None = None, xtoken=None) Session[source]

Creates a session / log in to the Scratch website with the specified session id. Structured similarly to Session._connect_object method.

Parameters:

session_id (str)

Keyword Arguments:
  • username (str)

  • password (str)

  • xtoken (str)

Returns:

An object that represents the created login / session

Return type:

scratchattach.session.Session

scratchattach.site.session.login_by_io(file: SupportsRead[str]) Session[source]

Login using a file object.

scratchattach.site.session.login_by_session_string(session_string: str) Session[source]

Login using a session string.

scratchattach.site.session.login_from_browser(browser: Browser = Browser.ANY)[source]

Login from a browser

scratchattach.site.session.suppress_login_warning()[source]

Suppress the login warning.

scratchattach.site.studio

Studio class

class scratchattach.site.studio.Studio(**entries)[source]

Bases: BaseSiteComponent

Represents a Scratch studio.

Attributes:

.id:

.title:

.description:

.host_id:

The user id of the studio host

.open_to_all:

Whether everyone is allowed to add projects

.comments_allowed:

.image_url:

.created:

.modified:

.follower_count:

.manager_count:

.project_count:

.update():

Updates the attributes

__init__(**entries)[source]
_abc_impl = <_abc._abc_data object>
_cookies: dict[str, str]
_headers: dict[str, str]
_session: session.Session | None
_update_from_dict(studio)[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

accept_invite()[source]
activity(*, limit=40, offset=0, date_limit=None)[source]
add_project(project_id)[source]

Adds a project to the studio. You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

Parameters:

project_id – Project id of the project that should be added

close_projects()[source]

Changes the studio settings so only curators can add projects to the studio. You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

comment_by_id(comment_id)[source]
comment_replies(*, comment_id, limit=40, offset=0) list[Comment][source]
comments(*, limit=40, offset=0) list[Comment][source]

Returns the comments posted on the studio (except for replies. To get replies use scratchattach.studio.Studio.get_comment_replies()).

Keyword Arguments:
  • page – The page of the comments that should be returned.

  • limit – Max. amount of returned comments.

Returns:

A list containing the requested comments as Comment objects.

Return type:

list<Comment>

curators(limit=40, offset=0)[source]

Gets the studio curators.

Keyword Arguments:
  • limit (int) – Max amount of returned curators.

  • offset (int) – Offset of the first returned curator.

Returns:

A list containing the studio curators as User objects

Return type:

list<scratchattach.user.User>

delete_comment(*, comment_id)[source]

Deletes a comment by ID. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

Parameters:

comment_id – The id of the comment that should be deleted

follow()[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

host()[source]

Gets the studio host.

Returns:

An object representing the studio host.

Return type:

scratchattach.user.User

invite_curator(curator)[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

leave()[source]

Removes yourself from the studio. You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

managers(limit=40, offset=0)[source]

Gets the studio managers.

Keyword Arguments:
  • limit (int) – Max amount of returned managers

  • offset (int) – Offset of the first returned manager.

Returns:

A list containing the studio managers as user objects

Return type:

list<scratchattach.user.User>

open_projects()[source]

Changes the studio settings so everyone (including non-curators) is able to add projects to the studio. You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

post_comment(content, *, parent_id='', commentee_id='')[source]

Posts a comment on the studio. You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

Parameters:

content – Content of the comment that should be posted

Keyword Arguments:
  • parent_id – ID of the comment you want to reply to. If you don’t want to mention a user, don’t put the argument.

  • commentee_id – ID of the user that will be mentioned in your comment and will receive a message about your comment. If you don’t want to mention a user, don’t put the argument.

Returns:

The posted comment as Comment object.

Return type:

scratchattach.comment.Comment

projects(limit=40, offset=0)[source]

Gets the studio projects.

Keyword Arguments:
  • limit (int) – Max amount of returned projects.

  • offset (int) – Offset of the first returned project.

Returns:

A list containing the studio projects as Project objects

Return type:

list<scratchattach.project.Project>

promote_curator(curator)[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

remove_curator(curator)[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

remove_project(project_id)[source]

Removes a project from the studio. You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

Parameters:

project_id – Project id of the project that should be removed

reply_comment(content, *, parent_id, commentee_id='')[source]

Posts a reply to a comment on the studio. You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

Parameters:

content – Content of the comment that should be posted

Warning

Only replies to top-level comments are shown on the Scratch website. Replies to replies are actually replies to the corresponding top-level comment in the API.

Therefore, parent_id should be the comment id of a top level comment.

Keyword Arguments:
  • parent_id – ID of the comment you want to reply to

  • commentee_id – ID of the user you are replying to

report_comment(*, comment_id)[source]

Reports a comment by ID to the Scratch team. You can only use this function if this object was created using scratchattach.session.Session.connect_project()

Parameters:

comment_id – The id of the comment that should be reported

set_description(new)[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

set_fields(fields_dict)[source]

Sets fields. Uses the scratch.mit.edu/site-api PUT API.

set_thumbnail(*, file)[source]

Sets the studio thumbnail. You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

Keyword Arguments:

file – The path to the image file

Returns:

Scratch cdn link to the set thumbnail

Return type:

str

set_title(new)[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

toggle_commenting()[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

transfer_ownership(new_owner, *, password)[source]

Makes another Scratcher studio host. You need to specify your password to do this.

Parameters:

new_owner (str) – Username of new host

Keyword Arguments:

password (str) – The password of your Scratch account

Warning

This action is irreversible!

turn_off_commenting()[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

turn_on_commenting()[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

unfollow()[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_studio()

update_api: str
your_role()[source]

Returns a dict with information about your role in the studio (whether you’re following, curating, managing it or are invited)

scratchattach.site.studio.explore_studios(*, query='', mode='trending', language='en', limit=40, offset=0)[source]
scratchattach.site.studio.get_studio(studio_id) Studio[source]

Gets a studio without logging in.

Parameters:

studio_id (int) – Studio id of the requested studio

Returns:

An object representing the requested studio

Return type:

scratchattach.studio.Studio

Warning

Any methods that authentication (like studio.follow) will not work on the returned object.

If you want to use these, get the studio with scratchattach.session.Session.connect_studio() instead.

scratchattach.site.studio.search_studios(*, query='', mode='trending', language='en', limit=40, offset=0)[source]

scratchattach.site.user

User class

class scratchattach.site.user.Rank(value)[source]

Bases: Enum

Possible ranks in scratch

NEW_SCRATCHER = 0
SCRATCHER = 1
SCRATCH_TEAM = 2
class scratchattach.site.user.User(**entries)[source]

Bases: BaseSiteComponent

Represents a Scratch user.

Attributes:

.join_date:

.about_me:

.wiwo:

Returns the user’s ‘What I’m working on’ section

.country:

Returns the country from the user profile

.icon_url:

Returns the link to the user’s pfp (90x90)

.id:

Returns the id of the user

.scratchteam:

Retuns True if the user is in the Scratch team

.update():

Updates the attributes

__init__(**entries)[source]
_abc_impl = <_abc._abc_data object>
_assert_permission()[source]
_cookies: dict[str, str]
_headers: dict[str, str]
_session: session.Session | None
_update_from_dict(data)[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

activity(*, limit=1000)[source]
Returns:

The user’s activity data as parsed list of scratchattach.activity.Activity objects

Return type:

list<scratchattach.Activity>

activity_html(*, limit=1000)[source]
Returns:

The raw user activity HTML data

Return type:

str

property classroom: Classroom | None

Get a user’s associated classroom, and return it as a scratchattach.classroom.Classroom object. If there is no associated classroom, returns None

comment_by_id(comment_id) Comment[source]

Gets a comment on this user’s profile by id.

Warning

For comments very far down on the user’s profile, this method will take a while to find the comment. Very old comment are deleted from Scratch’s database and may not appear.

Returns:

The request comment.

Return type:

scratchattach.comments.Comment

comments(*, page=1, limit=None)[source]

Returns the comments posted on the user’s profile (with replies).

Keyword Arguments:
  • page – The page of the comments that should be returned.

  • limit – Max. amount of returned comments.

Returns:

A list containing the requested comments as Comment objects.

Return type:

list<scratchattach.comment.Comment>

delete_comment(*, comment_id)[source]

Deletes a comment by its ID. You can only use this function if this object was created using scratchattach.session.Session.connect_user()

Parameters:

comment_id – The id of the comment that should be deleted

does_exist()[source]
Returns:

True if the user exists, False if the user is deleted, None if an error occured

Return type:

boolean

favorites(*, limit=40, offset=0)[source]
Returns:

The user’s favorite projects

Return type:

list<projects.projects.Project>

favorites_count()[source]
featured_data()[source]
Returns:

Gets info on the user’s featured project and featured label (like “Featured project”, “My favorite things”, etc.)

Return type:

dict

follow()[source]

Follows the user represented by the User object. You can only use this function if this object was created using scratchattach.session.Session.connect_user()

follower_count()[source]
follower_names(*, limit=40, offset=0)[source]
Returns:

The usernames of the user’s followers

Return type:

list<str>

followers(*, limit=40, offset=0)[source]
Returns:

The user’s followers as list of scratchattach.user.User objects

Return type:

list<scratchattach.user.User>

following(*, limit=40, offset=0)[source]
Returns:

The users that the user is following as list of scratchattach.user.User objects

Return type:

list<scratchattach.user.User>

following_count()[source]
following_names(*, limit=40, offset=0)[source]
Returns:

The usernames of the users the user is following

Return type:

list<str>

is_followed_by(user)[source]
Returns:

Whether the user is followed by the user provided as argument

Return type:

boolean

is_following(user: str)[source]
Returns:

Whether the user is following the user provided as argument

Return type:

boolean

is_new_scratcher()[source]
Returns:

True if the user has the New Scratcher status, else False

Return type:

boolean

loves(*, limit=40, offset=0, get_full_project: bool = False) list[Project][source]
Returns:

The user’s loved projects

Return type:

list<projects.projects.Project>

loves_count()[source]
message_count()[source]
message_events()[source]
ocular_status()[source]

Gets information about the user’s ocular status. Ocular is a website developed by jeffalo: https://ocular.jeffalo.net/

Returns:

dict

post_comment(content, *, parent_id='', commentee_id='')[source]

Posts a comment on the user’s profile. You can only use this function if this object was created using scratchattach.session.Session.connect_user()

Parameters:

content – Content of the comment that should be posted

Keyword Arguments:
  • parent_id – ID of the comment you want to reply to. If you don’t want to mention a user, don’t put the argument.

  • commentee_id – ID of the user that will be mentioned in your comment and will receive a message about your comment. If you don’t want to mention a user, don’t put the argument.

Returns:

An object representing the created comment.

Return type:

scratchattach.comment.Comment

project_count()[source]
projects(*, limit=40, offset=0) list[Project][source]
Returns:

The user’s shared projects

Return type:

list<projects.projects.Project>

rank()[source]

Finds the rank of the user. May replace user.scratchteam and user.is_new_scratcher in the future.

ranks()[source]

Gets information about the user’s ranks. Fetched from ScratchDB.

Warning

ScratchDB is down indefinitely, therefore this method is deprecated.

Returns:

A dict containing the user’s ranks. If the ranks aren’t available, all values will be -1.

Return type:

dict

reply_comment(content, *, parent_id, commentee_id='')[source]

Replies to a comment given by its id

Warning

Only replies to top-level comments are shown on the Scratch website. Replies to replies are actually replies to the corresponding top-level comment in the API.

Therefore, parent_id should be the comment id of a top level comment.

Parameters:

content – Content of the comment that should be posted

Keyword Arguments:
  • parent_id – ID of the comment you want to reply to

  • commentee_id – ID of the user that will be mentioned in your comment and will receive a message about your comment. If you don’t want to mention a user, don’t put the argument.

report_comment(*, comment_id)[source]

Reports a comment by its ID to the Scratch team. You can only use this function if this object was created using scratchattach.session.Session.connect_user()

Parameters:

comment_id – The id of the comment that should be reported

set_bio(text)[source]

Sets the user’s “About me” section. You can only use this function if this object was created using scratchattach.session.Session.connect_user()

Sets the user’s featured project. You can only use this function if this object was created using scratchattach.session.Session.connect_user()

Parameters:

project_id – Project id of the project that should be set as featured

Keyword Arguments:

label – The label that should appear above the featured project on the user’s profile (Like “Featured project”, “Featured tutorial”, “My favorite things”, etc.)

set_forum_signature(text)[source]

Sets the user’s discuss forum signature. You can only use this function if this object was created using scratchattach.session.Session.connect_user()

set_pfp(image: bytes)[source]

Sets the user’s profile picture. You can only use this function if this object was created using scratchattach.session.Session.connect_user()

set_wiwo(text)[source]

Sets the user’s “What I’m working on” section. You can only use this function if this object was created using scratchattach.session.Session.connect_user()

stats()[source]

Gets information about the user’s stats. Fetched from ScratchDB.

Warning

ScratchDB is down indefinitely, therefore this method is deprecated.

Returns:

A dict containing the user’s stats. If the stats aren’t available, all values will be -1.

Return type:

dict

studio_count()[source]
studios(*, limit=40, offset=0)[source]
studios_following_count()[source]
toggle_commenting()[source]

You can only use this function if this object was created using scratchattach.session.Session.connect_user()

unfollow()[source]

Unfollows the user represented by the User object. You can only use this function if this object was created using scratchattach.session.Session.connect_user()

update_api: str
verify_identity(*, verification_project_id=395330233)[source]

Can be used in applications to verify a user’s identity.

This function returns a Verifactor object. Attributs of this object: :.projecturl: The link to the project where the user has to go to verify :.project: The project where the user has to go to verify as scratchattach.Project object :.code: The code that the user has to comment

To check if the user verified successfully, call the .check() function on the returned object. It will return True if the user commented the code.

viewed_projects(limit=24, offset=0)[source]
Returns:

The user’s recently viewed projects

Return type:

list<projects.projects.Project>

You can only use this function if this object was created using scratchattach.session.Session.connect_user()

class scratchattach.site.user.Verificator(user: User, project_id: int)[source]

Bases: object

__init__(user: User, project_id: int)[source]
check() bool[source]
scratchattach.site.user.get_user(username) User[source]

Gets a user without logging in.

Parameters:

username (str) – Username of the requested user

Returns:

An object representing the requested user

Return type:

scratchattach.user.User

Warning

Any methods that require authentication (like user.follow) will not work on the returned object.

If you want to use these, get the user with scratchattach.session.Session.connect_user() instead.

scratchattach.site.classroom

class scratchattach.site.classroom.Classroom(title: 'str' = None, id: 'int' = None, classtoken: 'str' = None, author: 'user.User' = None, about_class: 'str' = None, working_on: 'str' = None, is_closed: 'bool' = False, datetime: 'datetime' = None, update_function: 'Callable' = <bound method Requests.get of <scratchattach.utils.requests.Requests object at 0x7fad041739d0>>, _session: 'Optional[Session]' = None)[source]

Bases: BaseSiteComponent

__init__(title: str = None, id: int = None, classtoken: str = None, author: user.User = None, about_class: str = None, working_on: str = None, is_closed: bool = False, datetime: datetime = None, update_function: Callable = <bound method Requests.get of <scratchattach.utils.requests.Requests object>>, _session: Optional[Session] = None) None
_abc_impl = <_abc._abc_data object>
_check_session() None[source]
_session: Session | None = None
_update_from_dict(classrooms)[source]

Parses the API response that is fetched in the update-method. Class specific, must be overridden in classes inheriting from this one.

about_class: str = None
activity(student: str = 'all', mode: str = 'Last created', page: int | None = None) list[dict[str, Any]][source]

Get a list of private activity, only available to the class owner. :returns: list<activity.Activity> The private activity of users in the class

add_studio(name: str, description: str = '') None[source]
author: user.User = None
class_studio_count() int[source]
class_studio_ids(*, page: int = 1) list[int][source]

Returns the class studio on the class.

Keyword Arguments:

page – The page of the students that should be returned.

Returns:

The id of the class studios

Return type:

list<int>

classtoken: str = None
close() None[source]
datetime: datetime = None
id: int = None
is_closed: bool = False
public_activity(*, limit=20)[source]
Returns:

The user’s activity data as parsed list of scratchattach.activity.Activity objects

Return type:

list<scratchattach.Activity>

register_student(username: str, password: str = '', birth_month: int | None = None, birth_year: int | None = None, gender: str | None = None, country: str | None = None, is_robot: bool = False) None[source]
reopen() None[source]
set_description(desc: str) None[source]
set_thumbnail(thumbnail: bytes) None[source]
set_title(title: str) None[source]
set_working_on(status: str) None[source]
student_count() int[source]
student_names(*, page=1) list[str][source]

Returns the student on the class.

Keyword Arguments:

page – The page of the students that should be returned.

Returns:

The usernames of the class students

Return type:

list<str>

title: str = None
update()[source]

Updates the attributes of the object by performing an API response. Returns True if the update was successful.

update_function(*args, **kwargs)

Sends a GET request.

Parameters:
  • url – URL for the new Request object.

  • params – (optional) Dictionary, list of tuples or bytes to send in the query string for the Request.

  • **kwargs – Optional arguments that request takes.

Returns:

Response object

Return type:

requests.Response

working_on: str = None
scratchattach.site.classroom.get_classroom(class_id: str) Classroom[source]

Gets a class without logging in.

Parameters:

class_id (str) – class id of the requested class

Returns:

An object representing the requested classroom

Return type:

scratchattach.classroom.Classroom

Warning

Any methods that require authentication will not work on the returned object.

If you want to use these, get the user with scratchattach.session.Session.connect_classroom() instead.

scratchattach.site.classroom.get_classroom_from_token(class_token) Classroom[source]

Gets a class without logging in.

Parameters:

class_token (str) – class token of the requested class

Returns:

An object representing the requested classroom

Return type:

scratchattach.classroom.Classroom

Warning

Any methods that require authentication will not work on the returned object.

If you want to use these, get the user with scratchattach.session.Session.connect_classroom() instead.

scratchattach.site.classroom.register_by_token(class_id: int, class_token: str, username: str, password: str, birth_month: int, birth_year: int, gender: str, country: str, is_robot: bool = False) None[source]

scratchattach.utils

scratchattach.utils.commons

v2 ready: Common functions used by various internal modules

class scratchattach.utils.commons.LockEvent[source]

Bases: object

Can be waited on and triggered. Not to be confused with threading.Event, which has to be reset.

__init__()[source]
_access_locks: allocate_lock
_event: Event
_locks: list[allocate_lock]
on() allocate_lock[source]

Return a lock that will unlock once the event takes place. Return value has to be waited on to wait for the event.

trigger()[source]

Trigger all threads waiting on this event to continue.

wait(blocking: bool = True, timeout: int | float | None = None) bool[source]

Wait for the event.

scratchattach.utils.commons._get_object(identificator_name, identificator, __class: type[C], NotFoundException, session=None) C[source]
scratchattach.utils.commons.api_iterative(url: str, *, limit: int, offset: int, max_req_limit: int = 40, add_params: str = '', _headers: dict | None = None, cookies: dict | None = None)[source]

Function for getting data from one of Scratch’s iterative JSON API endpoints (like /users/<user>/followers, or /users/<user>/projects)

scratchattach.utils.commons.api_iterative_data(fetch_func: Callable[[int, int], list], limit: int, offset: int, max_req_limit: int = 40, unpack: bool = True) list[source]

Iteratively gets data by calling fetch_func with a moving offset and a limit. Once fetch_func returns None, the retrieval is completed.

scratchattach.utils.commons.b62_decode(s: str)[source]
scratchattach.utils.commons.get_class_sort_mode(mode: str) tuple[str, str][source]

Returns the sort mode for the given mode for classes only

scratchattach.utils.commons.parse_object_list(raw, __class: type[C], session=None, primary_key='id') list[C][source]
scratchattach.utils.commons.webscrape_count(raw, text_before, text_after, cls: type = <class 'int'>) int | Any[source]

scratchattach.utils.encoder

class scratchattach.utils.encoder.Encoding[source]

Bases: object

Class that contains tools for encoding / decoding strings. The strings encoded / decoded with these functions can be decoded / encoded with Scratch using this sprite: https://scratch3-assets.1tim.repl.co/Encoder.sprite3

static decode(inp)[source]
Parameters:

inp (str) – The encoded input.

Returns:

The decoded output.

Return type:

str

static encode(inp)[source]
Parameters:

inp (str) – The decoded input.

Returns:

The encoded output.

Return type:

str

static replace_char(old_char, new_char)[source]

Replaces a character in the list that the encoder uses to encode / decode values. You can access this list using scratchattach.encoder.letters

scratchattach.utils.exceptions

exception scratchattach.utils.exceptions.APIError[source]

Bases: Exception

For API errors that can’t be classified into one of the above errors

exception scratchattach.utils.exceptions.AnonymousSiteComponentWarning[source]

Bases: UserWarning

Warns about a usage of an anonymous site component.

exception scratchattach.utils.exceptions.BadBlockShape[source]

Bases: Exception

Raised when the block shape cannot allow for the operation

exception scratchattach.utils.exceptions.BadRequest[source]

Bases: Exception

Raised when the Scratch API responds with a “Bad Request” error message. This can have various reasons. Make sure all provided arguments are valid.

exception scratchattach.utils.exceptions.BadScript[source]

Bases: Exception

Raised when the block script cannot allow for the operation

exception scratchattach.utils.exceptions.BadVLBPrimitiveError[source]

Bases: Exception

Raised when a Primitive claiming to be a variable/list/broadcast actually isn’t

exception scratchattach.utils.exceptions.ClassroomNotFound[source]

Bases: Exception

Raised when a non-existent Classroom is requested.

exception scratchattach.utils.exceptions.CloudConnectionError[source]

Bases: Exception

Raised when connecting to Scratch’s cloud server fails. This can have various reasons.

exception scratchattach.utils.exceptions.CommentNotFound[source]

Bases: Exception

exception scratchattach.utils.exceptions.CommentPostFailure[source]

Bases: Exception

Raised when a comment fails to post. This can have various reasons.

exception scratchattach.utils.exceptions.FetchError[source]

Bases: Exception

Raised when getting information from the Scratch API fails. This can have various reasons. Make sure all provided arguments are valid.

exception scratchattach.utils.exceptions.ForumContentNotFound[source]

Bases: Exception

Raised when a non-existent forum topic / post is requested.

exception scratchattach.utils.exceptions.InvalidCloudValue[source]

Bases: Exception

Raised when a cloud variable is set to an invalid value.

exception scratchattach.utils.exceptions.InvalidDecodeInput[source]

Bases: Exception

Raised when the built-in decoder scratchattach.encoder.Encoding.decode() receives an invalid input.

exception scratchattach.utils.exceptions.InvalidLanguage[source]

Bases: Exception

Raised when an invalid language/language code/language object is provided, for TTS or Translate

exception scratchattach.utils.exceptions.InvalidStageCount[source]

Bases: Exception

Raised when a project has too many or too few Stage sprites

exception scratchattach.utils.exceptions.InvalidTTSGender[source]

Bases: Exception

Raised when an invalid TTS gender is provided.

exception scratchattach.utils.exceptions.InvalidVLBName[source]

Bases: Exception

Raised when an invalid VLB name is provided (not variable, list or broadcast)

exception scratchattach.utils.exceptions.LoginDataWarning[source]

Bases: UserWarning

Warns you not to accidentally share your login data.

exception scratchattach.utils.exceptions.LoginFailure[source]

Bases: Exception

Raised when the Scratch server doesn’t respond with a session id.

This could be caused by an invalid username / password. Another cause could be that your IP address was banned from logging in to Scratch. If you’re using an online IDE (like replit), try running the code on your computer.

exception scratchattach.utils.exceptions.ProjectNotFound[source]

Bases: Exception

Raised when a non-existent project is requested.

exception scratchattach.utils.exceptions.RateLimitedError[source]

Bases: Exception

Indicates a ratelimit enforced by scratchattach

exception scratchattach.utils.exceptions.RequestNotFound[source]

Bases: Exception

Cloud Requests: Raised when a non-existent cloud request is edited using scratchattach.cloud_requests.CloudRequests.edit_request().

exception scratchattach.utils.exceptions.Response429[source]

Bases: Exception

Raised when the Scratch API responds with a 429 error. This means that your network was ratelimited or blocked by Scratch. If you’re using an online IDE (like replit.com), try running the code on your computer.

exception scratchattach.utils.exceptions.ScrapeError[source]

Bases: Exception

Raised when something goes wrong while web-scraping a page with bs4.

exception scratchattach.utils.exceptions.StudioNotFound[source]

Bases: Exception

Raised when a non-existent studio is requested.

exception scratchattach.utils.exceptions.Unauthenticated(message='')[source]

Bases: Exception

Raised when a method that requires a login / session is called on an object that wasn’t created with a session.

If you create Project, Studio, or User objects using scratchattach.get_project(), scratchattach.get_studio(), or scratchattach.get_user(), they cannot be used for actions that require authentication. Instead, use the following methods to ensure the objects are connected to an authenticated session:

  • scratchattach.Session.connect_project()

  • scratchattach.Session.connect_user()

  • scratchattach.Session.connect_studio()

This also applies to cloud variables, forum topics, and forum posts.

__init__(message='')[source]
exception scratchattach.utils.exceptions.Unauthorized(message='')[source]

Bases: Exception

Raised when an action is performed that the user associated with the session that the object was created with is not allowed to do.

Example: Changing the “about me” of other users will raise this error.

__init__(message='')[source]
exception scratchattach.utils.exceptions.UnclosedJSONError[source]

Bases: Exception

Raised when a JSON string is never closed.

exception scratchattach.utils.exceptions.UnexpectedWebsocketEventWarning[source]

Bases: RuntimeWarning

Warns about an unexpected occurrence with a websocket.

exception scratchattach.utils.exceptions.UnlinkedVLB[source]

Bases: Exception

Raised when a Primitive cannot be linked to variable/list/broadcast because the provided ID does not have an associated variable/list/broadcast

exception scratchattach.utils.exceptions.UserNotFound[source]

Bases: Exception

Raised when a non-existent user is requested.

exception scratchattach.utils.exceptions.WebsocketServerError[source]

Bases: Exception

Raised when the self-hosted cloud websocket server fails to start.

exception scratchattach.utils.exceptions.XTokenError[source]

Bases: Exception

Raised when an action can’t be performed because there is no XToken available.

This error can occur if the xtoken couldn’t be fetched when the session was created. Some actions (like loving projects) require providing this token.

scratchattach.utils.requests

class scratchattach.utils.requests.Requests[source]

Bases: Session

Centralized HTTP request handler (for better error handling and proxies)

check_response(r: Response)[source]
delete(*args, **kwargs)[source]

Sends a DELETE request. Returns Response object.

Parameters:
  • url – URL for the new Request object.

  • **kwargs – Optional arguments that request takes.

Return type:

requests.Response

error_handling: bool = True
get(*args, **kwargs)[source]

Sends a GET request. Returns Response object.

Parameters:
  • url – URL for the new Request object.

  • **kwargs – Optional arguments that request takes.

Return type:

requests.Response

no_error_handling() Iterator[None][source]
post(*args, **kwargs)[source]

Sends a POST request. Returns Response object.

Parameters:
  • url – URL for the new Request object.

  • data – (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the Request.

  • json – (optional) json to send in the body of the Request.

  • **kwargs – Optional arguments that request takes.

Return type:

requests.Response

put(*args, **kwargs)[source]

Sends a PUT request. Returns Response object.

Parameters:
  • url – URL for the new Request object.

  • data – (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the Request.

  • **kwargs – Optional arguments that request takes.

Return type:

requests.Response

yes_error_handling() Iterator[None][source]