Module edupage_api.substitution

Classes

class Action (value, names=None, *, module=None, qualname=None, type=None, start=1)
Expand source code
class Action(str, Enum):
    ADDITION = "add"
    CHANGE = "change"
    DELETION = "remove"

    @staticmethod
    def parse(string: str) -> Optional[Action]:
        return ModuleHelper.parse_enum(string, Action)

An enumeration.

Ancestors

  • builtins.str
  • enum.Enum

Class variables

var ADDITION
var CHANGE
var DELETION

Static methods

def parse(string: str) ‑> Action | None
Expand source code
@staticmethod
def parse(string: str) -> Optional[Action]:
    return ModuleHelper.parse_enum(string, Action)
class Substitution (edupage: EdupageModule)
Expand source code
class Substitution(Module):
    def __get_substitution_data(self, date: date) -> str:
        url = (
            f"https://{self.edupage.subdomain}.edupage.org/substitution/server/viewer.js"
            "?__func=getSubstViewerDayDataHtml"
        )

        data = {
            "__args": [None, {"date": date.strftime("%Y-%m-%d"), "mode": "classes"}],
            "__gsh": self.edupage.gsec_hash,
        }

        response = self.edupage.session.post(url, json=data).content.decode()
        response = json.loads(response)

        if response.get("reload"):
            raise ExpiredSessionException(
                "Invalid gsec hash! " "(Expired session, try logging in again!)"
            )

        return response.get("r")

    @ModuleHelper.logged_in
    def get_missing_teachers(self, date: date) -> Optional[list[EduTeacher]]:
        html = self.__get_substitution_data(date)
        missing_teachers_string = html.split('<span class="print-font-resizable">')[
            1
        ].split("</span>")[0]

        if not missing_teachers_string:
            return None

        _title, missing_teachers = missing_teachers_string.split(": ")

        all_teachers = People(self.edupage).get_teachers()

        missing_teachers = [
            item
            for sublist in [
                (t.strip().split("  (")[0]).split(" + ")
                for t in missing_teachers.split(", ")
            ]
            for item in sublist
        ]

        try:
            missing_teachers = [
                list(filter(lambda x: x.name == t, all_teachers))[0]
                for t in missing_teachers
            ]
        except IndexError:
            raise InvalidTeacherException(
                "Invalid teacher in substitution! "
                "(The teacher is no longer frequenting this school)"
            )

        return missing_teachers

    @ModuleHelper.logged_in
    def get_timetable_changes(self, date: date) -> Optional[list[TimetableChange]]:
        html = self.__get_substitution_data(date)

        class_delim = (
            '</div><div class="section print-nobreak">'
            '<div class="header"><span class="print-font-resizable">'
        )
        changes_by_class_dirty = html.split(class_delim)[1:]

        if not changes_by_class_dirty:
            return None

        footer_delim = (
            '<div style="text-align:center;font-size:12px">'
            '<a href="https://www.asctimetables.com" target="_blank">'
            "www.asctimetables.com</a> -"
        )
        changes_by_class_dirty[-1] = changes_by_class_dirty[-1].split(footer_delim)[0]

        changes = [
            (
                x.replace("</div>", "")
                .replace('<div class="period">', "")
                .replace('<span class="print-font-resizable">', "")
                .replace('<div class="info">', "")
            )
            for x in changes_by_class_dirty
        ]

        lesson_changes = []
        for class_changes in changes:
            class_changes_data = class_changes.split('</span><div class="rows">')
            change_class = class_changes_data[0]

            class_changes_rows = class_changes_data[1].split('<div class="row ')[1:]

            for change in class_changes_rows:
                change = change.replace('">', "</span>")
                action, lesson_n, title = change.split("</span>", 3)[:-1]

                if "<img src=" in title:
                    title = title.split(">")[1]

                action = Action.parse(action)

                if "-" in lesson_n:
                    lesson_from, lesson_to = lesson_n.split(" - ")
                    lesson_n = (
                        ModuleHelper.parse_int(lesson_from),
                        ModuleHelper.parse_int(lesson_to),
                    )
                else:
                    lesson_n = ModuleHelper.parse_int(lesson_n)

                lesson_change = TimetableChange(change_class, lesson_n, title, action)
                lesson_changes.append(lesson_change)

        return lesson_changes

Ancestors

Methods

def get_missing_teachers(self, date: date) ‑> list[EduTeacher] | None
Expand source code
@ModuleHelper.logged_in
def get_missing_teachers(self, date: date) -> Optional[list[EduTeacher]]:
    html = self.__get_substitution_data(date)
    missing_teachers_string = html.split('<span class="print-font-resizable">')[
        1
    ].split("</span>")[0]

    if not missing_teachers_string:
        return None

    _title, missing_teachers = missing_teachers_string.split(": ")

    all_teachers = People(self.edupage).get_teachers()

    missing_teachers = [
        item
        for sublist in [
            (t.strip().split("  (")[0]).split(" + ")
            for t in missing_teachers.split(", ")
        ]
        for item in sublist
    ]

    try:
        missing_teachers = [
            list(filter(lambda x: x.name == t, all_teachers))[0]
            for t in missing_teachers
        ]
    except IndexError:
        raise InvalidTeacherException(
            "Invalid teacher in substitution! "
            "(The teacher is no longer frequenting this school)"
        )

    return missing_teachers
def get_timetable_changes(self, date: date) ‑> list[TimetableChange] | None
Expand source code
@ModuleHelper.logged_in
def get_timetable_changes(self, date: date) -> Optional[list[TimetableChange]]:
    html = self.__get_substitution_data(date)

    class_delim = (
        '</div><div class="section print-nobreak">'
        '<div class="header"><span class="print-font-resizable">'
    )
    changes_by_class_dirty = html.split(class_delim)[1:]

    if not changes_by_class_dirty:
        return None

    footer_delim = (
        '<div style="text-align:center;font-size:12px">'
        '<a href="https://www.asctimetables.com" target="_blank">'
        "www.asctimetables.com</a> -"
    )
    changes_by_class_dirty[-1] = changes_by_class_dirty[-1].split(footer_delim)[0]

    changes = [
        (
            x.replace("</div>", "")
            .replace('<div class="period">', "")
            .replace('<span class="print-font-resizable">', "")
            .replace('<div class="info">', "")
        )
        for x in changes_by_class_dirty
    ]

    lesson_changes = []
    for class_changes in changes:
        class_changes_data = class_changes.split('</span><div class="rows">')
        change_class = class_changes_data[0]

        class_changes_rows = class_changes_data[1].split('<div class="row ')[1:]

        for change in class_changes_rows:
            change = change.replace('">', "</span>")
            action, lesson_n, title = change.split("</span>", 3)[:-1]

            if "<img src=" in title:
                title = title.split(">")[1]

            action = Action.parse(action)

            if "-" in lesson_n:
                lesson_from, lesson_to = lesson_n.split(" - ")
                lesson_n = (
                    ModuleHelper.parse_int(lesson_from),
                    ModuleHelper.parse_int(lesson_to),
                )
            else:
                lesson_n = ModuleHelper.parse_int(lesson_n)

            lesson_change = TimetableChange(change_class, lesson_n, title, action)
            lesson_changes.append(lesson_change)

    return lesson_changes
class TimetableChange (change_class: str,
lesson_n: int,
title: str,
action: Union[Action, tuple[int, int]])
Expand source code
@dataclass
class TimetableChange:
    change_class: str
    lesson_n: int
    title: str
    action: Union[Action, tuple[int, int]]

TimetableChange(change_class: 'str', lesson_n: 'int', title: 'str', action: 'Union[Action, tuple[int, int]]')

Class variables

var actionAction | tuple[int, int]
var change_class : str
var lesson_n : int
var title : str