|
2 | 2 |
|
3 | 3 | import datetime |
4 | 4 | import warnings |
5 | | -from typing import Optional, TYPE_CHECKING, Any |
| 5 | +from dataclasses import dataclass, field |
| 6 | +from datetime import datetime |
| 7 | +from typing import Optional, TYPE_CHECKING, Any, Callable |
6 | 8 |
|
7 | 9 | import bs4 |
| 10 | +from bs4 import BeautifulSoup |
8 | 11 |
|
9 | 12 | if TYPE_CHECKING: |
10 | 13 | from scratchattach.site.session import Session |
|
13 | 16 | from . import user, activity |
14 | 17 | from ._base import BaseSiteComponent |
15 | 18 | from scratchattach.utils import exceptions, commons |
16 | | -from scratchattach.utils.commons import headers |
17 | | - |
18 | | -from bs4 import BeautifulSoup |
19 | 19 |
|
20 | 20 |
|
| 21 | +@dataclass |
21 | 22 | class Classroom(BaseSiteComponent): |
22 | | - def __init__(self, **entries): |
| 23 | + title: str = None |
| 24 | + id: int = None |
| 25 | + classtoken: str = None |
| 26 | + |
| 27 | + author: user.User = None |
| 28 | + about_class: str = None |
| 29 | + working_on: str = None |
| 30 | + |
| 31 | + is_closed: bool = False |
| 32 | + datetime: datetime = None |
| 33 | + |
| 34 | + |
| 35 | + update_function: Callable = field(repr=False, default=requests.get) |
| 36 | + _session: Optional[Session] = field(repr=False, default=None) |
| 37 | + |
| 38 | + def __post_init__(self): |
23 | 39 | # Info on how the .update method has to fetch the data: |
24 | 40 | # NOTE: THIS DOESN'T WORK WITH CLOSED CLASSES! |
25 | | - self.update_function = requests.get |
26 | | - if "id" in entries: |
27 | | - self.update_api = f"https://api.scratch.mit.edu/classrooms/{entries['id']}" |
28 | | - elif "classtoken" in entries: |
29 | | - self.update_api = f"https://api.scratch.mit.edu/classtoken/{entries['classtoken']}" |
| 41 | + if self.id: |
| 42 | + self.update_api = f"https://api.scratch.mit.edu/classrooms/{self.id}" |
| 43 | + elif self.classtoken: |
| 44 | + self.update_api = f"https://api.scratch.mit.edu/classtoken/{self.classtoken}" |
30 | 45 | else: |
31 | | - raise KeyError(f"No class id or token provided! Entries: {entries}") |
32 | | - |
33 | | - # Set attributes every Classroom object needs to have: |
34 | | - self._session: Session = None |
35 | | - self.id = None |
36 | | - self.classtoken = None |
37 | | - self.is_closed = False |
38 | | - |
39 | | - self.__dict__.update(entries) |
| 46 | + raise KeyError(f"No class id or token provided! {self.__dict__ = }") |
40 | 47 |
|
41 | 48 | # Headers and cookies: |
42 | 49 | if self._session is None: |
43 | | - self._headers = headers |
| 50 | + self._headers = commons.headers |
44 | 51 | self._cookies = {} |
45 | 52 | else: |
46 | 53 | self._headers = self._session._headers |
47 | 54 | self._cookies = self._session._cookies |
48 | 55 |
|
49 | 56 | # Headers for operations that require accept and Content-Type fields: |
50 | | - self._json_headers = dict(self._headers) |
51 | | - self._json_headers["accept"] = "application/json" |
52 | | - self._json_headers["Content-Type"] = "application/json" |
| 57 | + self._json_headers = {**self._headers, |
| 58 | + "accept": "application/json", |
| 59 | + "Content-Type": "application/json"} |
53 | 60 |
|
54 | | - def __repr__(self) -> str: |
55 | | - return f"classroom called {self.title!r}" |
| 61 | + def __str__(self) -> str: |
| 62 | + return f"<Classroom {self.title!r}, id={self.id!r}>" |
56 | 63 |
|
57 | 64 | def update(self): |
58 | 65 | try: |
@@ -305,7 +312,8 @@ def close(self) -> None: |
305 | 312 | warnings.warn(f"{self._session} may not be authenticated to edit {self}") |
306 | 313 | raise e |
307 | 314 |
|
308 | | - def register_student(self, username: str, password: str = '', birth_month: Optional[int] = None, birth_year: Optional[int] = None, |
| 315 | + def register_student(self, username: str, password: str = '', birth_month: Optional[int] = None, |
| 316 | + birth_year: Optional[int] = None, |
309 | 317 | gender: Optional[str] = None, country: Optional[str] = None, is_robot: bool = False) -> None: |
310 | 318 | return register_by_token(self.id, self.classtoken, username, password, birth_month, birth_year, gender, country, |
311 | 319 | is_robot) |
@@ -346,7 +354,8 @@ def public_activity(self, *, limit=20): |
346 | 354 |
|
347 | 355 | return activities |
348 | 356 |
|
349 | | - def activity(self, student: str = "all", mode: str = "Last created", page: Optional[int] = None) -> list[dict[str, Any]]: |
| 357 | + def activity(self, student: str = "all", mode: str = "Last created", page: Optional[int] = None) -> list[ |
| 358 | + dict[str, Any]]: |
350 | 359 | """ |
351 | 360 | Get a list of private activity, only available to the class owner. |
352 | 361 | Returns: |
@@ -421,7 +430,7 @@ def register_by_token(class_id: int, class_token: str, username: str, password: |
421 | 430 | "is_robot": is_robot} |
422 | 431 |
|
423 | 432 | response = requests.post("https://scratch.mit.edu/classes/register_new_student/", |
424 | | - data=data, headers=headers, cookies={"scratchcsrftoken": 'a'}) |
| 433 | + data=data, headers=commons.headers, cookies={"scratchcsrftoken": 'a'}) |
425 | 434 | ret = response.json()[0] |
426 | 435 |
|
427 | 436 | if "username" in ret: |
|
0 commit comments