From 414a60ccfe81822d45729a103e85f9af72ef2ff3 Mon Sep 17 00:00:00 2001 From: r Date: Thu, 29 May 2025 23:44:03 +0100 Subject: [PATCH 1/2] refactor: user.py imports --- scratchattach/site/user.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/scratchattach/site/user.py b/scratchattach/site/user.py index 7e8bf83e..d8c7e88c 100644 --- a/scratchattach/site/user.py +++ b/scratchattach/site/user.py @@ -3,22 +3,26 @@ import json import random +import re import string from datetime import datetime, timezone +from bs4 import BeautifulSoup + +from ._base import BaseSiteComponent from ..eventhandlers import message_events -from . import project + +from ..utils import commons from ..utils import exceptions +from ..utils.commons import headers +from ..utils.requests import Requests as requests + +from . import project from . import studio from . import forum -from bs4 import BeautifulSoup -from ._base import BaseSiteComponent -from ..utils.commons import headers -from ..utils import commons from . import comment from . import activity - -from ..utils.requests import Requests as requests +from . import classroom class Verificator: From 40b339be3cefcedb8a340f65e7b21f66f0b6237b Mon Sep 17 00:00:00 2001 From: r Date: Thu, 29 May 2025 23:44:50 +0100 Subject: [PATCH 2/2] feat: user.classroom getter --- scratchattach/site/user.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/scratchattach/site/user.py b/scratchattach/site/user.py index d8c7e88c..a0d4d0f6 100644 --- a/scratchattach/site/user.py +++ b/scratchattach/site/user.py @@ -74,6 +74,10 @@ def __init__(self, **entries): self.username = None self.name = None + # cache value for classroom getter method (using @property) + # first value is whether the cache has actually been set (because it can be None), second is the value itself + self._classroom: tuple[bool, classroom.Classroom | None] = False, None + # Update attributes from entries dict: entries.setdefault("name", entries.get("username")) self.__dict__.update(entries) @@ -124,6 +128,37 @@ def _assert_permission(self): raise exceptions.Unauthorized( "You need to be authenticated as the profile owner to do this.") + @property + def classroom(self) -> 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` + """ + if not self._classroom[0]: + resp = requests.get(f"https://scratch.mit.edu/users/{self.username}/") + soup = BeautifulSoup(resp.text, "html.parser") + + details = soup.find("p", {"class": "profile-details"}) + + class_name, class_id = None, None + for a in details.find_all("a"): + href = a.get("href") + if re.match(r"/classes/\d*/", href): + class_name = a.text.strip()[len("Student of: "):] + class_id = href.split('/')[2] + break + + if class_name: + self._classroom = True, classroom.Classroom( + _session=self, + id=class_id, + title=class_name + ) + else: + self._classroom = True, None + + return self._classroom[1] + def does_exist(self): """ Returns: