Crank dat!
This commit is contained in:
17 files changed
+6624
No files matched your search
@@ -0,0 +1,563 @@
|
||||
"""Offline demo data for librus-tui.
|
||||
|
||||
Start the server with --demo to explore the interface without a real
|
||||
Librus account. All dates are generated relative to today so the dashboard
|
||||
and timetable always look alive.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import copy
|
||||
from datetime import date, datetime, timedelta
|
||||
|
||||
WEEKDAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
|
||||
|
||||
SUBJECTS = [
|
||||
"Język polski",
|
||||
"Matematyka",
|
||||
"Język angielski",
|
||||
"Fizyka",
|
||||
"Chemia",
|
||||
"Biologia",
|
||||
"Historia",
|
||||
"Informatyka",
|
||||
"Geografia",
|
||||
"Wychowanie fizyczne",
|
||||
]
|
||||
|
||||
TEACHERS = {
|
||||
"polski": {"FirstName": "Maria", "LastName": "Wiśniewska"},
|
||||
"matma": {"FirstName": "Piotr", "LastName": "Zieliński"},
|
||||
"angielski": {"FirstName": "Sarah", "LastName": "Kowalczyk"},
|
||||
"fizyka": {"FirstName": "Andrzej", "LastName": "Lewandowski"},
|
||||
"chemia": {"FirstName": "Ewa", "LastName": "Szymańska"},
|
||||
"biologia": {"FirstName": "Katarzyna", "LastName": "Wójcik"},
|
||||
"historia": {"FirstName": "Tomasz", "LastName": "Kamiński"},
|
||||
"informatyka": {"FirstName": "Michał", "LastName": "Nowicki"},
|
||||
"geografia": {"FirstName": "Agnieszka", "LastName": "Dąbrowska"},
|
||||
"wf": {"FirstName": "Marek", "LastName": "Jankowski"},
|
||||
}
|
||||
|
||||
|
||||
def iso(d):
|
||||
return d.strftime("%Y-%m-%d")
|
||||
|
||||
|
||||
def grade(value, weight, category, teacher, days_ago=3, comment="No comment", **extra):
|
||||
base = {
|
||||
"Grade": value,
|
||||
"Weight": weight,
|
||||
"Comment": comment,
|
||||
"Category": category,
|
||||
"isFinal": False,
|
||||
"isSemester": False,
|
||||
"separator": False,
|
||||
"underlined": False,
|
||||
"Semester": 1,
|
||||
"AddDate": iso(date.today() - timedelta(days=days_ago)),
|
||||
"AddedBy": copy.deepcopy(teacher),
|
||||
}
|
||||
base.update(extra)
|
||||
return base
|
||||
|
||||
|
||||
def build_grades():
|
||||
t = TEACHERS
|
||||
return {
|
||||
"Język polski": [
|
||||
grade("5", "2", "Sprawdzian", t["polski"], 12, "Świetna analiza lektury."),
|
||||
grade("4", "1", "Kartkówka", t["polski"], 9),
|
||||
grade("5", "1", "Aktywność", t["polski"], 2),
|
||||
grade("4", "2", "Wypracowanie", t["polski"], 21, "Bardzo dobry styl, drobne błędy."),
|
||||
],
|
||||
"Matematyka": [
|
||||
grade("5", "3", "Sprawdzian", t["matma"], 7, "Bezbłędnie!"),
|
||||
grade("4", "1", "Kartkówka", t["matma"], 3),
|
||||
grade("3", "2", "Praca domowa", t["matma"], 14),
|
||||
grade("5", "2", "Sprawdzian", t["matma"], 28),
|
||||
grade("4", "1", "Aktywność", t["matma"], 1),
|
||||
],
|
||||
"Język angielski": [
|
||||
grade("5", "2", "Test", t["angielski"], 5),
|
||||
grade("5", "1", "Speaking", t["angielski"], 10),
|
||||
grade("4", "2", "Essay", t["angielski"], 19),
|
||||
],
|
||||
"Fizyka": [
|
||||
grade("4", "2", "Sprawdzian", t["fizyka"], 8),
|
||||
grade("3", "1", "Kartkówka", t["fizyka"], 16),
|
||||
grade("4", "1", "Doświadczenie", t["fizyka"], 4),
|
||||
],
|
||||
"Chemia": [
|
||||
grade("4", "2", "Sprawdzian", t["chemia"], 11),
|
||||
grade("5", "1", "Kartkówka", t["chemia"], 6),
|
||||
],
|
||||
"Biologia": [
|
||||
grade("5", "2", "Sprawdzian", t["biologia"], 13),
|
||||
grade("5", "1", "Projekt", t["biologia"], 20),
|
||||
],
|
||||
"Historia": [
|
||||
grade("4", "2", "Sprawdzian", t["historia"], 9),
|
||||
grade("4", "1", "Kartkówka", t["historia"], 2),
|
||||
grade("5", "1", "Wypowiedź", t["historia"], 25),
|
||||
],
|
||||
"Informatyka": [
|
||||
grade("6", "2", "Projekt", t["informatyka"], 6, "Wyjątkowo dobrze zaprojektowana aplikacja."),
|
||||
grade("5", "1", "Kartkówka", t["informatyka"], 15),
|
||||
],
|
||||
"Geografia": [
|
||||
grade("4", "2", "Sprawdzian", t["geografia"], 10),
|
||||
grade("4", "1", "Mapa", t["geografia"], 5),
|
||||
],
|
||||
"Wychowanie fizyczne": [
|
||||
grade("5", "1", "Aktywność", t["wf"], 3),
|
||||
grade("5", "1", "Test sprawności", t["wf"], 17),
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def lesson(no, subject, teacher, room, start, end, **extra):
|
||||
item = {
|
||||
"Lesson": no,
|
||||
"Subject": subject,
|
||||
"isSubstitution": False,
|
||||
"isCancelled": False,
|
||||
"Teacher": copy.deepcopy(teacher),
|
||||
"HourFrom": start,
|
||||
"HourTo": end,
|
||||
"Classroom": room,
|
||||
}
|
||||
item.update(extra)
|
||||
return item
|
||||
|
||||
|
||||
PLAN = {
|
||||
"Monday": [
|
||||
(1, "Język polski", "polski", "A12", "08:00", "08:45"),
|
||||
(2, "Matematyka", "matma", "B04", "08:55", "09:40"),
|
||||
(3, "Język angielski", "angielski", "A07", "09:50", "10:35"),
|
||||
(4, "Historia", "historia", "A21", "10:45", "11:30"),
|
||||
(6, "Wychowanie fizyczne", "wf", "SALA", "12:45", "13:30"),
|
||||
],
|
||||
"Tuesday": [
|
||||
(1, "Fizyka", "fizyka", "C02", "08:00", "08:45"),
|
||||
(2, "Chemia", "chemia", "C03", "08:55", "09:40"),
|
||||
(3, "Matematyka", "matma", "B04", "09:50", "10:35"),
|
||||
(5, "Język polski", "polski", "A12", "11:45", "12:30"),
|
||||
(7, "Informatyka", "informatyka", "INF", "13:45", "14:30"),
|
||||
],
|
||||
"Wednesday": [
|
||||
(1, "Biologia", "biologia", "B11", "08:00", "08:45"),
|
||||
(2, "Geografia", "geografia", "A19", "08:55", "09:40"),
|
||||
(3, "Język angielski", "angielski", "A07", "09:50", "10:35"),
|
||||
(4, "Matematyka", "matma", "B04", "10:45", "11:30"),
|
||||
(6, "Historia", "historia", "A21", "12:45", "13:30"),
|
||||
],
|
||||
"Thursday": [
|
||||
(1, "Matematyka", "matma", "B04", "08:00", "08:45"),
|
||||
(2, "Fizyka", "fizyka", "C02", "08:55", "09:40"),
|
||||
(3, "Język polski", "polski", "A12", "09:50", "10:35"),
|
||||
(5, "Wychowanie fizyczne", "wf", "SALA", "11:45", "12:30"),
|
||||
],
|
||||
"Friday": [
|
||||
(1, "Chemia", "chemia", "C03", "08:00", "08:45"),
|
||||
(2, "Biologia", "biologia", "B11", "08:55", "09:40"),
|
||||
(3, "Informatyka", "informatyka", "INF", "09:50", "10:35"),
|
||||
(4, "Język angielski", "angielski", "A07", "10:45", "11:30"),
|
||||
],
|
||||
}
|
||||
|
||||
SUBSTITUTIONS = {
|
||||
"Wednesday": {4: {"isSubstitution": True, "Classroom": "A02"}},
|
||||
"Friday": {3: {"isCancelled": True, "isSubstitution": True}},
|
||||
}
|
||||
|
||||
|
||||
def build_timetable(week=0):
|
||||
today = date.today()
|
||||
week_start = today - timedelta(days=today.weekday()) + timedelta(weeks=week)
|
||||
week_end = week_start + timedelta(days=6)
|
||||
data = {}
|
||||
|
||||
for index, day in enumerate(WEEKDAYS[:5]):
|
||||
entries = []
|
||||
for no, subject, teacher_key, room, start, end in PLAN[day]:
|
||||
extra = SUBSTITUTIONS.get(day, {}).get(no, {}) if week == 0 else {}
|
||||
item = lesson(
|
||||
no,
|
||||
subject,
|
||||
TEACHERS[teacher_key],
|
||||
extra.get("Classroom", room),
|
||||
start,
|
||||
end,
|
||||
**{k: v for k, v in extra.items() if k != "Classroom"},
|
||||
)
|
||||
item["Date"] = iso(week_start + timedelta(days=index))
|
||||
entries.append(item)
|
||||
if week == 1 and day == "Thursday":
|
||||
entries.append(
|
||||
{
|
||||
"Lesson": "-",
|
||||
"Subject": "Konsultacje z matematyki",
|
||||
"isSubstitution": False,
|
||||
"isCancelled": False,
|
||||
"Teacher": copy.deepcopy(TEACHERS["matma"]),
|
||||
"HourFrom": "15:00",
|
||||
"HourTo": "16:00",
|
||||
"Classroom": "B04",
|
||||
"Date": iso(week_start + timedelta(days=3)),
|
||||
"isAdditional": True,
|
||||
}
|
||||
)
|
||||
if entries:
|
||||
data[day] = entries
|
||||
|
||||
return {
|
||||
"Timetable": data,
|
||||
"weekStart": iso(week_start),
|
||||
"weekEnd": iso(week_end),
|
||||
"week": week,
|
||||
}
|
||||
|
||||
|
||||
def build_exams():
|
||||
today = date.today()
|
||||
return [
|
||||
{
|
||||
"Lesson": "Matematyka",
|
||||
"AddedBy": copy.deepcopy(TEACHERS["matma"]),
|
||||
"Type": "Sprawdzian",
|
||||
"StartTime": "09:50",
|
||||
"EndTime": "10:35",
|
||||
"Date": iso(today + timedelta(days=2)),
|
||||
"AddDate": iso(today - timedelta(days=4)) + " 14:12:00",
|
||||
"Content": "Funkcja kwadratowa: postać ogólna, kanoniczna i iloczynowa. Zadania 1-8, str. 142.",
|
||||
},
|
||||
{
|
||||
"Lesson": "Język polski",
|
||||
"AddedBy": copy.deepcopy(TEACHERS["polski"]),
|
||||
"Type": "Wypracowanie",
|
||||
"StartTime": "08:00",
|
||||
"EndTime": "08:45",
|
||||
"Date": iso(today + timedelta(days=4)),
|
||||
"AddDate": iso(today - timedelta(days=2)) + " 10:03:00",
|
||||
"Content": "Rozprawka: „Czy warto znać przeszłość?”. Minimum 300 słów, odwołanie do lektury.",
|
||||
},
|
||||
{
|
||||
"Lesson": "Fizyka",
|
||||
"AddedBy": copy.deepcopy(TEACHERS["fizyka"]),
|
||||
"Type": "Kartkówka",
|
||||
"StartTime": "08:55",
|
||||
"EndTime": "09:40",
|
||||
"Date": iso(today + timedelta(days=7)),
|
||||
"AddDate": iso(today - timedelta(days=1)) + " 16:44:00",
|
||||
"Content": "Zasady dynamiki Newtona. Wzory i jednostki.",
|
||||
},
|
||||
{
|
||||
"Lesson": "Informatyka",
|
||||
"AddedBy": copy.deepcopy(TEACHERS["informatyka"]),
|
||||
"Type": "Projekt",
|
||||
"StartTime": "",
|
||||
"EndTime": "",
|
||||
"Date": iso(today + timedelta(days=10)),
|
||||
"AddDate": iso(today - timedelta(days=6)) + " 09:15:00",
|
||||
"Content": "Aplikacja terminalowa w Pythonie: minimum 3 podkomendy, obsługa błędów i README.",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def build_attendances():
|
||||
today = date.today()
|
||||
entries = [
|
||||
("Matematyka", "Obecność", "ob.", True, 0),
|
||||
("Język polski", "Obecność", "ob.", True, 0),
|
||||
("Fizyka", "Spóźnienie", "sp.", False, 1),
|
||||
("Chemia", "Nieobecność", "nb.", False, 2),
|
||||
("Historia", "Obecność", "ob.", True, 2),
|
||||
("Język angielski", "Zwolnienie", "zw.", True, 3),
|
||||
("Biologia", "Nieobecność", "nb.", False, 4),
|
||||
("Informatyka", "Obecność", "ob.", True, 5),
|
||||
("Geografia", "Obecność", "ob.", True, 6),
|
||||
("Wychowanie fizyczne", "Obecność", "ob.", True, 7),
|
||||
("Matematyka", "Nieobecność", "nb.", False, 8),
|
||||
("Język polski", "Obecność", "ob.", True, 9),
|
||||
]
|
||||
result = []
|
||||
for subject, kind, short, presence, days_ago in entries:
|
||||
teacher_key = {
|
||||
"Matematyka": "matma",
|
||||
"Język polski": "polski",
|
||||
"Fizyka": "fizyka",
|
||||
"Chemia": "chemia",
|
||||
"Historia": "historia",
|
||||
"Język angielski": "angielski",
|
||||
"Biologia": "biologia",
|
||||
"Informatyka": "informatyka",
|
||||
"Geografia": "geografia",
|
||||
"Wychowanie fizyczne": "wf",
|
||||
}[subject]
|
||||
d = today - timedelta(days=days_ago)
|
||||
result.append(
|
||||
{
|
||||
"Lesson": subject,
|
||||
"Type": kind,
|
||||
"Short": short,
|
||||
"isPresence": presence,
|
||||
"Added": iso(d) + " 18:00:00",
|
||||
"Date": iso(d),
|
||||
"AddedBy": copy.deepcopy(TEACHERS[teacher_key]),
|
||||
}
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
MESSAGES = [
|
||||
{
|
||||
"from": "Maria Wiśniewska",
|
||||
"subject": "Wyniki próbnej matury z języka polskiego",
|
||||
"date": "07.11.2026 14:22",
|
||||
"link": "1081-1",
|
||||
},
|
||||
{
|
||||
"from": "Piotr Zieliński",
|
||||
"subject": "Konsultacje przed sprawdzianem",
|
||||
"date": "06.11.2026 09:10",
|
||||
"link": "1074-1",
|
||||
},
|
||||
{
|
||||
"from": "Sekretariat",
|
||||
"subject": "Zebranie z rodzicami – 12 listopada",
|
||||
"date": "05.11.2026 16:45",
|
||||
"link": "1069-1",
|
||||
},
|
||||
{
|
||||
"from": "Michał Nowicki",
|
||||
"subject": "Dodatkowe zajęcia z algorytmiki",
|
||||
"date": "04.11.2026 11:03",
|
||||
"link": "1062-1",
|
||||
},
|
||||
]
|
||||
|
||||
MESSAGE_BODIES = {
|
||||
"1081-1": {
|
||||
"subject": "Wyniki próbnej matury z języka polskiego",
|
||||
"from": "Maria Wiśniewska (nauczyciel)",
|
||||
"date": "07.11.2026 14:22",
|
||||
"read": "Tak",
|
||||
"content": (
|
||||
"<p>Dzień dobry,</p>"
|
||||
"<p>wyniki próbnej matury z języka polskiego są już dostępne w dzienniku. "
|
||||
"Średnia klasy to <b>78%</b>. Gratulacje dla wszystkich, którzy przekroczyli 80%.</p>"
|
||||
"<p>Omówienie arkusza odbędzie się w <b>poniedziałek</b> na lekcji 3. Proszę przynieść "
|
||||
"zeszyty i arkusze.</p>"
|
||||
"<p>Pozdrawiam,<br>Maria Wiśniewska</p>"
|
||||
),
|
||||
"attachments": [
|
||||
{"name": "klucz_odpowiedzi.pdf", "nice": "1081-1/klucz.pdf"},
|
||||
],
|
||||
},
|
||||
"1074-1": {
|
||||
"subject": "Konsultacje przed sprawdzianem",
|
||||
"from": "Piotr Zieliński (nauczyciel)",
|
||||
"date": "06.11.2026 09:10",
|
||||
"read": "Tak",
|
||||
"content": (
|
||||
"<p>Przypominam, że w czwartek o <b>15:00</b> w sali B04 odbędą się konsultacje "
|
||||
"przed sprawdzianem z funkcji kwadratowej.</p>"
|
||||
"<p>Przygotujcie pytania do zadań z rozdziału 5.</p>"
|
||||
),
|
||||
"attachments": [],
|
||||
},
|
||||
"1069-1": {
|
||||
"subject": "Zebranie z rodzicami – 12 listopada",
|
||||
"from": "Sekretariat (administracja)",
|
||||
"date": "05.11.2026 16:45",
|
||||
"read": "Nie",
|
||||
"content": (
|
||||
"<p>Uprzejmie informujemy, że zebranie z rodzicami odbędzie się "
|
||||
"<b>12 listopada 2026 r. o godz. 17:00</b> w sali gimnastycznej.</p>"
|
||||
"<p>Po spotkaniu ogólnym zapraszamy na spotkania z wychowawcami.</p>"
|
||||
),
|
||||
"attachments": [
|
||||
{"name": "harmonogram_zebran.pdf", "nice": "1069-1/harmonogram.pdf"},
|
||||
],
|
||||
},
|
||||
"1062-1": {
|
||||
"subject": "Dodatkowe zajęcia z algorytmiki",
|
||||
"from": "Michał Nowicki (nauczyciel)",
|
||||
"date": "04.11.2026 11:03",
|
||||
"read": "Tak",
|
||||
"content": (
|
||||
"<p>Zapraszam na dodatkowe zajęcia z algorytmiki w każdą środę o 15:30 "
|
||||
"w sali INF. Pracujemy nad projektami do olimpiady informatycznej.</p>"
|
||||
),
|
||||
"attachments": [],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def build_free_days():
|
||||
today = date.today()
|
||||
return [
|
||||
{
|
||||
"Name": "Wigilia szkolna",
|
||||
"DateFrom": iso(date(today.year, 12, 23)),
|
||||
"DateTo": iso(date(today.year, 12, 31)),
|
||||
},
|
||||
{
|
||||
"Name": "Dzień Edukacji Narodowej",
|
||||
"DateFrom": iso(date(today.year, 10, 14)),
|
||||
"DateTo": iso(date(today.year, 10, 14)),
|
||||
},
|
||||
{
|
||||
"Name": "Ferie zimowe",
|
||||
"DateFrom": iso(date(today.year + 1, 1, 26)),
|
||||
"DateTo": iso(date(today.year + 1, 2, 8)),
|
||||
},
|
||||
{
|
||||
"Name": "Wielkanoc",
|
||||
"DateFrom": iso(date(today.year + 1, 3, 28)),
|
||||
"DateTo": iso(date(today.year + 1, 4, 2)),
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def build_teacher_free_days():
|
||||
today = date.today()
|
||||
return [
|
||||
{
|
||||
"Teacher": copy.deepcopy(TEACHERS["matma"]),
|
||||
"DateFrom": iso(today + timedelta(days=5)),
|
||||
"DateTo": iso(today + timedelta(days=5)),
|
||||
"TimeFrom": "10:00:00",
|
||||
"TimeTo": "14:00:00",
|
||||
},
|
||||
{
|
||||
"Teacher": copy.deepcopy(TEACHERS["angielski"]),
|
||||
"DateFrom": iso(today + timedelta(days=9)),
|
||||
"DateTo": iso(today + timedelta(days=11)),
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def build_conferences():
|
||||
today = date.today()
|
||||
return [
|
||||
{
|
||||
"Name": "Zebranie śródroczne",
|
||||
"Topic": "Wyniki w nauce i frekwencja",
|
||||
"Room": "A12",
|
||||
"Date": iso(today + timedelta(days=4)),
|
||||
"Time": "17:00:00",
|
||||
},
|
||||
{
|
||||
"Name": "Konsultacje indywidualne",
|
||||
"Topic": "Matematyka – przygotowanie do matury",
|
||||
"Room": "B04",
|
||||
"Date": iso(today + timedelta(days=11)),
|
||||
"Time": "16:30:00",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
class DemoLibrus:
|
||||
"""Drop-in replacement for librus.Librus backed by sample data."""
|
||||
|
||||
demo = True
|
||||
credentials_rejected = False
|
||||
headers = {}
|
||||
|
||||
def __init__(self):
|
||||
self._grades = build_grades()
|
||||
self._attendances = build_attendances()
|
||||
|
||||
async def mktoken(self, login, password):
|
||||
await asyncio.sleep(0.35)
|
||||
return True
|
||||
|
||||
async def activate_api_access(self):
|
||||
return True
|
||||
|
||||
async def get_me(self):
|
||||
return {
|
||||
"FirstName": "Alex",
|
||||
"LastName": "Nowak",
|
||||
"Tutor": copy.deepcopy(TEACHERS["polski"]),
|
||||
"SchoolYearStarts": "2026-09-01",
|
||||
"SchoolYearMiddles": "2027-01-31",
|
||||
"SchoolYearEnds": "2027-06-25",
|
||||
"Type": "Uczeń",
|
||||
"Class": "3 A",
|
||||
}
|
||||
|
||||
async def get_school(self):
|
||||
return {
|
||||
"Name": "I Liceum Ogólnokształcące im. Mikołaja Kopernika",
|
||||
"Street": "ul. Szkolna",
|
||||
"BuildingNumber": "12",
|
||||
"PostCode": "00-001",
|
||||
"Town": "Warszawa",
|
||||
}
|
||||
|
||||
async def get_lucky_number(self):
|
||||
return 7
|
||||
|
||||
async def get_behaviour_grade(self):
|
||||
return {
|
||||
"Grade": "bardzo dobre",
|
||||
"Teacher": copy.deepcopy(TEACHERS["polski"]),
|
||||
}
|
||||
|
||||
async def get_grades(self):
|
||||
return copy.deepcopy(self._grades)
|
||||
|
||||
async def get_timetable(self, week=0):
|
||||
return build_timetable(week)
|
||||
|
||||
async def get_exams(self):
|
||||
return build_exams()
|
||||
|
||||
async def get_attendances(self):
|
||||
return copy.deepcopy(self._attendances)
|
||||
|
||||
async def get_notifications(self, days=14):
|
||||
return {
|
||||
"grades": sum(len(v) for v in self._grades.values()),
|
||||
"exams": len(build_exams()),
|
||||
"absences": sum(1 for a in self._attendances if not a["isPresence"]),
|
||||
"conferences": len(build_conferences()),
|
||||
}
|
||||
|
||||
async def get_messages(self):
|
||||
return copy.deepcopy(MESSAGES)
|
||||
|
||||
async def get_message(self, link):
|
||||
body = copy.deepcopy(
|
||||
MESSAGE_BODIES.get(link, MESSAGE_BODIES["1081-1"])
|
||||
)
|
||||
body["attachments"] = [
|
||||
dict(
|
||||
attachment,
|
||||
source="https://synergia.librus.pl/wiadomosci/pobierz_zalacznik/"
|
||||
+ attachment["nice"],
|
||||
direct="/get",
|
||||
)
|
||||
for attachment in body["attachments"]
|
||||
]
|
||||
return body
|
||||
|
||||
async def download_file(self, link):
|
||||
return {
|
||||
"headers": {
|
||||
"Content-Type": "application/pdf",
|
||||
"Content-Disposition": 'attachment; filename="demo.pdf"',
|
||||
},
|
||||
"content": b"%PDF-1.4\n% librus-tui demo attachment\n",
|
||||
}
|
||||
|
||||
async def get_free_days(self):
|
||||
return build_free_days()
|
||||
|
||||
async def get_teacher_free_days(self):
|
||||
return build_teacher_free_days()
|
||||
|
||||
async def get_parent_teacher_conferences(self):
|
||||
return build_conferences()
|
||||
Reference in new issue
Block a user