Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
252d276
refactor: Add try-except blocks for loading json on connect and readi…
Boss-1s May 7, 2026
7fdfe0f
Finish debug for json loading and reading 'method' key
Boss-1s May 7, 2026
a44c3f5
a little more context on the ip banned message
Boss-1s May 8, 2026
a05828e
[UNIMPORTANT] notated unsued import
Boss-1s May 9, 2026
270025f
Merge branch 'TimMcCool:main' into main
Boss-1s May 10, 2026
11b1dd9
Merge branch 'TimMcCool:main' into tw-debug-compliance
Boss-1s May 16, 2026
d2d5f0c
Merge branch 'main' into tw-debug-compliance
Boss-1s Jun 2, 2026
7f2c18a
Merge branch 'TimMcCool:main' into tw-debug-compliance
Boss-1s Jun 2, 2026
5fee55e
Merge branch 'TimMcCool:main' into tw-debug-compliance
Boss-1s Jun 6, 2026
67c6148
Merge branch 'TimMcCool:main' into tw-debug-compliance
Boss-1s Jun 21, 2026
958b3d4
Merge branch 'TimMcCool:main' into tw-debug-compliance
Boss-1s Jul 1, 2026
439a12a
Merge branch 'TimMcCool:main' into tw-debug-compliance
Boss-1s Jul 25, 2026
80efca4
Merge branch 'TimMcCool:main' into tw-debug-compliance
Boss-1s Aug 10, 2026
e764962
Merge branch 'TimMcCool:main' into tw-debug-compliance
Boss-1s Aug 23, 2026
435d5f5
feat: rich
Boss-1s Aug 25, 2026
db50b0b
bump ruff up a patch
Boss-1s Aug 25, 2026
9863d50
feat(cloud_server): implement SSL secure websocket from semver2 into …
Boss-1s Aug 26, 2026
7e8fddd
fix(cloud_server): expose `init_ssl_cloud_sever` to top-level
Boss-1s Aug 26, 2026
bab2905
chore(eventhandlers._base): move mixin class to _base
Boss-1s Aug 26, 2026
5cd379d
fatal(eventhandlers._base): missing imports
Boss-1s Aug 26, 2026
494063c
Merge branch 'semver3-secure-ws' into tw-debug-compliance
Boss-1s Aug 26, 2026
4740cc8
fix(eventhandlers._base): remove stale reference
Boss-1s Aug 26, 2026
d3c67fd
chore(eventhandlers): rich cleanup
Boss-1s Aug 27, 2026
38f7135
.
Boss-1s Aug 27, 2026
a54c428
chore(cloud._base): anything in websocketeventstream counts towards r…
Boss-1s Aug 27, 2026
c246779
export cloud server types
TheCommCraft Sep 2, 2026
d9e28f2
[skip ci] new test - temp commit
Boss-1s Sep 2, 2026
2950297
export cloud server types
Boss-1s Sep 2, 2026
a1423ce
fix(sa.eventhandlers): clean up
Boss-1s Sep 2, 2026
8d5aa20
fix(sa.eventhandlers._base): ensure blocked_ips is always some list
Boss-1s Sep 2, 2026
0ef4a2f
Merge branch 'semver3-secure-ws' into tw-debug-compliance
Boss-1s Sep 2, 2026
f3da237
fatal: missing import
Boss-1s Sep 2, 2026
e716022
final debug message refactors in BaseCloudServer
Boss-1s Sep 2, 2026
70ffb36
feat: expose BaseCloudServer
Boss-1s Sep 2, 2026
92cc748
fatal: BaseCloudServer should not have ssl-related stuff
Boss-1s Sep 2, 2026
1924636
docstrings
Boss-1s Sep 2, 2026
2a5dfc9
resolve https://github.com/TimMcCool/scratchattach/pull/723#discussio…
Boss-1s Sep 2, 2026
5b0ff22
resolve
Boss-1s Sep 2, 2026
b80c260
revert
Boss-1s Sep 2, 2026
f81bce7
apply changes
TheCommCraft Sep 3, 2026
1d0bf6e
Merge branch 'TimMcCool:main' into semver3-secure-ws
Boss-1s Sep 3, 2026
e905eb8
.
Boss-1s Sep 3, 2026
16b58b7
replace all references to scratchattach/2.0.0
Boss-1s Sep 3, 2026
6243190
fatal: stale assignment to nonexistent arg websocketclass
Boss-1s Sep 3, 2026
c476784
Merge branch 'main' into semver3-secure-ws
Boss-1s Sep 3, 2026
d0f6d4d
Merge branch 'semver3-secure-ws' into tw-debug-compliance
Boss-1s Sep 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,13 @@ identifier.sqlite
obfuscated.sb3
.pytest_cache
.ruff_cache

.coverage
certfile.pem
coverage.xml
keyfile.pem
.test/test.py
.test/teststststs.py
.test/ws_client_test.py
tests/test_tw_cloud_debug_compliance.py
.vscode
57 changes: 57 additions & 0 deletions .test/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import scratchattach as sa

from rich.traceback import install

from scratchattach.cloud.cloud import CustomCloud

install(show_locals=True)

server_ip = '127.0.0.1'
ws_server_port = 8080
wss_server_port = 8765
project_id=["108566337"]

ws_server = sa.init_cloud_server(server_ip,
ws_server_port,
length_limit=65536,
allow_non_numeric=True,
whitelisted_projects=project_id,
allow_nonscratch_names=True,
blocked_ips=None,
sync_players=True,
log_var_sets=True
)

wss_server = sa.init_ssl_cloud_server(server_ip,
wss_server_port,
length_limit=65536,
allow_non_numeric=True,
whitelisted_projects=project_id,
allow_nonscratch_names=True,
blocked_ips=None,
sync_players=True,
log_var_sets=True,
certfile="certfile.pem",
keyfile="keyfile.pem"
)



ws_server.start()

wss_server.start()

cloud = CustomCloud(project_id=project_id[0],
cloud_host=f"wss://{server_ip}:{wss_server_port}",
username = "Boss_1s",
length_limit = None,
allow_non_numeric = True,
_session = None,
header = None,
cookie = None,
origin = None,
print_connect_messages = True)

events = cloud.events()

events.start()
50 changes: 43 additions & 7 deletions scratchattach/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
from .cloud.cloud import CustomCloud, ScratchCloud, TwCloud, get_cloud, get_scratch_cloud, get_tw_cloud
from .cloud.cloud import (
CustomCloud,
ScratchCloud,
TwCloud,
get_cloud,
get_scratch_cloud,
get_tw_cloud,
)
from .cloud._base import BaseCloud, AnyCloud

from .eventhandlers.cloud_server import init_cloud_server
from .eventhandlers._base import BaseEventHandler
from .eventhandlers.cloud_server import (
init_cloud_server,
init_ssl_cloud_server,
TwCloudSocket,
TwCloudServer,
TwSSLCloudServer,
)
from .eventhandlers._base import BaseEventHandler, BaseCloudServer
from .eventhandlers.filterbot import Filterbot, HardFilter, SoftFilter, SpamFilter
from .eventhandlers.cloud_storage import Database
from .eventhandlers.combine import MultiEventHandler

from .other.other_apis import *

# from .other.project_json_capabilities import ProjectBody, get_empty_project_pb, get_pb_from_dict, read_sb3_file, download_asset
# from .other.project_json_capabilities import (
# ProjectBody,
# get_empty_project_pb,
# get_pb_from_dict,
# read_sb3_file,
# download_asset,
# )
from .utils.encoder import Encoding
from .utils.enums import Languages, TTSVoices
from .utils.exceptions import (
Expand All @@ -27,11 +45,29 @@
from .site.cloud_activity import CloudActivity
from .site.forum import ForumPost, ForumTopic, get_topic, get_topic_list, youtube_link_to_scratch
from .site.project import Project, get_project, search_projects, explore_projects
from .site.session import Session, login, login_by_id, login_by_session_string, login_by_io, login_by_file, login_from_browser
from .site.session import (
Session,
login,
login_by_id,
login_by_session_string,
login_by_io,
login_by_file,
login_from_browser,
)
from .site.studio import Studio, get_studio, search_studios, explore_studios
from .site.classroom import Classroom, get_classroom
from .site.user import User, get_user, Rank
from .site._base import BaseSiteComponent
from .site.browser_cookies import Browser, ANY, FIREFOX, CHROME, CHROMIUM, VIVALDI, EDGE, EDGE_DEV, SAFARI
from .site.browser_cookies import (
Browser,
ANY,
FIREFOX,
CHROME,
CHROMIUM,
VIVALDI,
EDGE,
EDGE_DEV,
SAFARI,
)

from . import editor
9 changes: 6 additions & 3 deletions scratchattach/cloud/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from abc import ABC, abstractmethod, ABCMeta
from threading import Lock
from collections.abc import Iterator
from rich import print

from scratchattach.cloud import cloud as cloud_module

Expand Down Expand Up @@ -199,7 +200,7 @@ def __init__(self, cloud: BaseCloud):
except exceptions.CloudConnectionError:
warnings.warn("Initial cloud connection attempt failed, retrying...", exceptions.UnexpectedWebsocketEventWarning)
self.packets_left = []

def wait_before_reconnect(self):
if time.time() - self.most_recent_reconnection_time > self.RECENT_RECONNECT_TIME_DELTA:
self.recent_reconnect_count = 0
Expand Down Expand Up @@ -254,10 +255,12 @@ def read(self, amount: int = -1) -> Iterator[dict[str, Any]]:
i += 1
yield json.loads(self.packets_left.pop(0))
done = True
except json.JSONDecodeError as e:
except json.JSONDecodeError:
# this could happen e.g. when the scratchattach server sends the message
# "This server uses @TimMcCool's scratchattach 2.0.0"
warnings.warn(f"Invalid JSON sent from server: {e}")
# print(f"[yellow]Warning: Cloud events handler received invalid JSON.[/]")
# print(f" [b]Data received:[/] \"{self.packets_left}\"")
warnings.warn(f"Cloud events handler received invalid JSON. Data received: {self.packets_left}")
except (websocket.WebSocketConnectionClosedException, ssl.SSLWantReadError):
self.wait_before_reconnect()
self.source_cloud.reconnect()
Expand Down
Loading