Skip to content

Commit efdca88

Browse files
authored
Classroom property (solves TimMcCool#382) (TimMcCool#405)
* refactor: user.py imports * feat: user.classroom getter * feat: detection for closed classes * fix: detect is_closed (by editing init order)
1 parent c38fc6d commit efdca88

File tree

2 files changed

+53
-9
lines changed

2 files changed

+53
-9
lines changed

scratchattach/site/classroom.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ def __init__(self, **entries):
3030
else:
3131
raise KeyError(f"No class id or token provided! Entries: {entries}")
3232

33-
# Set attributes every Project object needs to have:
33+
# Set attributes every Classroom object needs to have:
3434
self._session: Session = None
3535
self.id = None
3636
self.classtoken = None
37+
self.is_closed = False
3738

3839
self.__dict__.update(entries)
3940

@@ -49,7 +50,6 @@ def __init__(self, **entries):
4950
self._json_headers = dict(self._headers)
5051
self._json_headers["accept"] = "application/json"
5152
self._json_headers["Content-Type"] = "application/json"
52-
self.is_closed = False
5353

5454
def __repr__(self) -> str:
5555
return f"classroom called {self.title!r}"

scratchattach/site/user.py

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,26 @@
33

44
import json
55
import random
6+
import re
67
import string
78
from datetime import datetime, timezone
89

10+
from bs4 import BeautifulSoup
11+
12+
from ._base import BaseSiteComponent
913
from ..eventhandlers import message_events
10-
from . import project
14+
15+
from ..utils import commons
1116
from ..utils import exceptions
17+
from ..utils.commons import headers
18+
from ..utils.requests import Requests as requests
19+
20+
from . import project
1221
from . import studio
1322
from . import forum
14-
from bs4 import BeautifulSoup
15-
from ._base import BaseSiteComponent
16-
from ..utils.commons import headers
17-
from ..utils import commons
1823
from . import comment
1924
from . import activity
20-
21-
from ..utils.requests import Requests as requests
25+
from . import classroom
2226

2327
class Verificator:
2428

@@ -70,6 +74,10 @@ def __init__(self, **entries):
7074
self.username = None
7175
self.name = None
7276

77+
# cache value for classroom getter method (using @property)
78+
# first value is whether the cache has actually been set (because it can be None), second is the value itself
79+
self._classroom: tuple[bool, classroom.Classroom | None] = False, None
80+
7381
# Update attributes from entries dict:
7482
entries.setdefault("name", entries.get("username"))
7583
self.__dict__.update(entries)
@@ -120,6 +128,42 @@ def _assert_permission(self):
120128
raise exceptions.Unauthorized(
121129
"You need to be authenticated as the profile owner to do this.")
122130

131+
@property
132+
def classroom(self) -> classroom.Classroom | None:
133+
"""
134+
Get a user's associated classroom, and return it as a `scratchattach.classroom.Classroom` object.
135+
If there is no associated classroom, returns `None`
136+
"""
137+
if not self._classroom[0]:
138+
resp = requests.get(f"https://scratch.mit.edu/users/{self.username}/")
139+
soup = BeautifulSoup(resp.text, "html.parser")
140+
141+
details = soup.find("p", {"class": "profile-details"})
142+
143+
class_name, class_id, is_closed = None, None, None
144+
for a in details.find_all("a"):
145+
href = a.get("href")
146+
if re.match(r"/classes/\d*/", href):
147+
class_name = a.text.strip()[len("Student of: "):]
148+
is_closed = class_name.endswith("\n (ended)") # as this has a \n, we can be sure
149+
if is_closed:
150+
class_name = class_name[:-7].strip()
151+
152+
class_id = href.split('/')[2]
153+
break
154+
155+
if class_name:
156+
self._classroom = True, classroom.Classroom(
157+
_session=self,
158+
id=class_id,
159+
title=class_name,
160+
is_closed=is_closed
161+
)
162+
else:
163+
self._classroom = True, None
164+
165+
return self._classroom[1]
166+
123167
def does_exist(self):
124168
"""
125169
Returns:

0 commit comments

Comments
 (0)