From 01346ab25068a6af85f096272a9b1a906b2d41dc Mon Sep 17 00:00:00 2001 From: MilesWK <121042782+MilesWK@users.noreply.github.com> Date: Thu, 20 Nov 2025 11:53:50 -0500 Subject: [PATCH 1/5] Implement cloud status check function Added a function to check the cloud status of Scratch. This resolves issue [#535](https://github.com/TimMcCool/scratchattach/issues/535) and adds `sa.check_cloud_status()` and is indeed functional! Signed-off-by: MilesWK <121042782+MilesWK@users.noreply.github.com> --- scratchattach/other/other_apis.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scratchattach/other/other_apis.py b/scratchattach/other/other_apis.py index 51831d6a..0b41c55c 100644 --- a/scratchattach/other/other_apis.py +++ b/scratchattach/other/other_apis.py @@ -106,6 +106,12 @@ def monthly_site_traffic() -> MonthlySiteTraffic: data.pop("_TS") return data +def check_cloud_status(): # MilesWK Actually did something good! + try: + resp = requests.get("https://clouddata.scratch.mit.edu/health", timeout=5) + return "Online" if resp.status_code == 200 else "Offline" + except requests.RequestException: + return "Offline" type CountryCounts = TypedDict("CountryCounts", { '0': int, # not sure what 0 is. maybe it's the 'other' category From e1c51865bac9ece7e1da792f962c40c833baebdd Mon Sep 17 00:00:00 2001 From: MilesWK <121042782+MilesWK@users.noreply.github.com> Date: Thu, 20 Nov 2025 13:55:55 -0500 Subject: [PATCH 2/5] Fix the AI slop Changed the code back to a stable, non-AI version. This should work Signed-off-by: MilesWK <121042782+MilesWK@users.noreply.github.com> --- scratchattach/other/other_apis.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scratchattach/other/other_apis.py b/scratchattach/other/other_apis.py index 0b41c55c..6bdae9de 100644 --- a/scratchattach/other/other_apis.py +++ b/scratchattach/other/other_apis.py @@ -106,13 +106,13 @@ def monthly_site_traffic() -> MonthlySiteTraffic: data.pop("_TS") return data -def check_cloud_status(): # MilesWK Actually did something good! - try: - resp = requests.get("https://clouddata.scratch.mit.edu/health", timeout=5) - return "Online" if resp.status_code == 200 else "Offline" - except requests.RequestException: +def check_cloud_status(): + data = requests.get("https://clouddata.scratch.mit.edu/health", timeout=5) + if data.status_code == 200: + return "Online" + else: return "Offline" - + type CountryCounts = TypedDict("CountryCounts", { '0': int, # not sure what 0 is. maybe it's the 'other' category 'AT': int, From ad22d69f1961c1e0612ef0512782201dfb868fbb Mon Sep 17 00:00:00 2001 From: faretek Date: Thu, 20 Nov 2025 19:05:09 +0000 Subject: [PATCH 3/5] feat: cloud status check This is a wip commit (sorry). I'm trying to use git worktrees to fix this from now on --- scratchattach/other/other_apis.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/scratchattach/other/other_apis.py b/scratchattach/other/other_apis.py index 0b41c55c..e5d185e4 100644 --- a/scratchattach/other/other_apis.py +++ b/scratchattach/other/other_apis.py @@ -2,9 +2,11 @@ from __future__ import annotations import json +import traceback from scratchattach.site import project, studio, session from scratchattach.utils import commons +from scratchattach.utils import exceptions from scratchattach.utils.commons import parse_object_list from scratchattach.utils.enums import Languages, Language, TTSVoices, TTSVoice from scratchattach.utils.exceptions import BadRequest, InvalidLanguage, InvalidTTSGender @@ -106,12 +108,13 @@ def monthly_site_traffic() -> MonthlySiteTraffic: data.pop("_TS") return data -def check_cloud_status(): # MilesWK Actually did something good! - try: - resp = requests.get("https://clouddata.scratch.mit.edu/health", timeout=5) - return "Online" if resp.status_code == 200 else "Offline" - except requests.RequestException: - return "Offline" +def check_cloud_status(): + with requests.no_error_handling(): + try: + resp = requests.get("https://clouddata.scratch.mit.edu/health", timeout=5) + return f"Online: {resp.content}" if resp.status_code == 200 else "Offline" # WIP! + except exceptions.FetchError as e: + return f"Offline {e}" type CountryCounts = TypedDict("CountryCounts", { '0': int, # not sure what 0 is. maybe it's the 'other' category From 1e2b31c2b958d6f014a428821cfaa1b68e23876e Mon Sep 17 00:00:00 2001 From: faretek Date: Thu, 20 Nov 2025 19:12:14 +0000 Subject: [PATCH 4/5] fix: remove httpx --- scratchattach/site/placeholder.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scratchattach/site/placeholder.py b/scratchattach/site/placeholder.py index 0619d7c0..9885f70f 100644 --- a/scratchattach/site/placeholder.py +++ b/scratchattach/site/placeholder.py @@ -2,7 +2,6 @@ import re import bs4 import json -import httpx import io from dataclasses import dataclass @@ -103,7 +102,7 @@ def create_placeholder_project(title: str, data: bytes): print(f"{asset_information = }") print(f"{body.name = }") with requests.no_error_handling(): - resp = httpx.post("https://share.turbowarp.org/api/projects/new", data={ + resp = requests.post("https://share.turbowarp.org/api/projects/new", data={ "title": title, "assetInformation": asset_information, }, files={ From 9dc56e68090917b4edf8823c5292a53e3e4f9f59 Mon Sep 17 00:00:00 2001 From: faretek Date: Thu, 20 Nov 2025 19:27:50 +0000 Subject: [PATCH 5/5] feat: cloudstatus dataclass This allows for parsing the data, and at the least, it would be a good idea to use a boolean for is_online --- scratchattach/other/other_apis.py | 35 ++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/scratchattach/other/other_apis.py b/scratchattach/other/other_apis.py index e5d185e4..0dec8d94 100644 --- a/scratchattach/other/other_apis.py +++ b/scratchattach/other/other_apis.py @@ -1,8 +1,10 @@ """Other Scratch API-related functions""" from __future__ import annotations +from dataclasses import dataclass, field +from typing import Any import json -import traceback +import dataclasses from scratchattach.site import project, studio, session from scratchattach.utils import commons @@ -102,19 +104,42 @@ class MonthlySiteTraffic(TypedDict): users: str sessions: str +class CloudStatusRedis(TypedDict): + connected: bool + ready: bool + +@dataclass +class CloudStatus: + is_online: bool + _raw: Any = field(repr=False, default=None) + + _: dataclasses.KW_ONLY + uptime: Optional[float] = None + load: Optional[list[float]] = None + redis: Optional[CloudStatusRedis] = None def monthly_site_traffic() -> MonthlySiteTraffic: data = requests.get("https://scratch.mit.edu/statistics/data/monthly-ga/").json() data.pop("_TS") return data -def check_cloud_status(): +def get_cloud_status() -> CloudStatus: with requests.no_error_handling(): try: resp = requests.get("https://clouddata.scratch.mit.edu/health", timeout=5) - return f"Online: {resp.content}" if resp.status_code == 200 else "Offline" # WIP! - except exceptions.FetchError as e: - return f"Offline {e}" + if resp.status_code != 200: + return CloudStatus(False, resp.content) + try: + data = resp.json() + return CloudStatus(True, resp.content, + uptime=data["uptime"], + load=data["load"], + redis=data["redis"]) + + except json.JSONDecodeError: + return CloudStatus(True, resp.content) + except exceptions.FetchError: + return CloudStatus(False) type CountryCounts = TypedDict("CountryCounts", { '0': int, # not sure what 0 is. maybe it's the 'other' category