diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cc5a2df --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +install: + pip install -r requirements.txt + +run: + python3 "src/main.py" \ No newline at end of file diff --git a/README.md b/README.md index 88eae8c..94cc1a4 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,34 @@ # SOL Enhanced -An enhanced version of the SkolaOnLine (SOL) online school system. +An enhanced version of the ŠkolaOnLine (ŠOL) online school system. It aims to provide more readable data than the web version and -remove some of the annoyances of the mobile app. +remove some of the annoyances of the mobile app. It is intended +to be and Android app in the future, but so far it is **only for Linux** +(not tested anywhere else). Insiration was taken from [@JakubAndrysek](https://github.com/JakubAndrysek)'s [skola-online-stahovani-znamek](https://github.com/JakubAndrysek/skola-online-stahovani-znamek) project. -## Still in development! -#### It is not ready yet. +# Features + ++ Shows the schedule for the current week ++ Shows all grades and their arithmetic average (not accounting for weight) ++ Works offline (when the internet has been accessed at least once before) + +# Usage + +1. Clone the repo + +`git clone git@github.com:mnjx/sol-enhanced.git` + +2. Navigate into the repo directory + +`cd sol-enhanced` + +3. Install the requirements (required to run only once) + +`make install` + +4. Run the program + +`make run` diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..314f890 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +lxml +bs4 +requests + diff --git a/scrape_data.py b/scrape_data.py deleted file mode 100644 index 2a0246c..0000000 --- a/scrape_data.py +++ /dev/null @@ -1,510 +0,0 @@ -import requests -from bs4 import BeautifulSoup -import time - -session = requests.Session() -REMOTE_SERVER = "one.one.one.one" -not_login = 0 -F_not_anymore = 0 - -def fetch_locally(what: str) -> list: - global not_login, F_not_anymore - - if not_login == 1 and F_not_anymore == 0: - F_not_anymore = 1 - not_login = 0 - print("Could not sign in (you may have entered invalid login credentials)") - print("Fetching locally\n") - if what == "schedule": - schedule = schedule_from_file() - return schedule - elif what == "grades": - grades = grades_from_file() - return grades - -def login(user: str, pwd: str) -> bool: - if is_connected(REMOTE_SERVER) == True: - url: str = "https://aplikace.skolaonline.cz/SOL/Prihlaseni.aspx" - data = { - "__EVENTTARGET": "dnn$ctr994$SOLLogin$btnODeslat", - "__EVENTARGUMENT": "", - "__VIEWSTATE": "", - "__VIEWSTATEGENERATOR": "", - "__VIEWSTATEENCRYPTED": "", - "__PREVIOUSPAGE": "", - "__EVENTVALIDATION": "", - "dnn$dnnSearch$txtSearch": "", - "JmenoUzivatele": user, # username - "HesloUzivatele": pwd, # password - "ScrollTop": "", - "__dnnVariable": "", - "__RequestVerificationToken": "" - } - - post_login = session.post(url, data=data) - if post_login.status_code != 200: - #print("Could not sign in") - return False - else: - #print("Sign in successful") - return True - else: - #print("Could not sign in") - #print("Fetching data from local files") - return False - -def is_connected(hostname: str) -> bool: - import socket - - try: - host = socket.gethostbyname(hostname) - s = socket.create_connection((host, 80), 2) - s.close() - return True - except Exception: - pass - return False - -def get_html_from(params=None) -> str: - base = "https://aplikace.skolaonline.cz" - - if params is not None: - base += params - - response = session.get(base) - if response.status_code == 200: - #print("Download successful") - return response - else: - print("Download unsuccessful") - return "" - -def sort_calendar(cal: list[dict]) -> list[dict]: - sorted_cal: list[dict] = [{}, {}, {}, {}, {}] - - for i in range(len(cal)): - if cal[i]["DAY"] == "Po": - sorted_cal[0] = cal[i] - if cal[i]["DAY"] == "Út": - sorted_cal[1] = cal[i] - if cal[i]["DAY"] == "St": - sorted_cal[2] = cal[i] - if cal[i]["DAY"] == "Čt": - sorted_cal[3] = cal[i] - if cal[i]["DAY"] == "Pá": - sorted_cal[4] = cal[i] - - return sorted_cal - -def get_schedule(url: str): - try: - html = get_html_from(url) - - soup = BeautifulSoup(html.text, "lxml") - - table = soup.find("table", id="CCADynamicCalendarTable") - - rows_odd = table.find_all("tr", class_="RowOdd") - rows_even = table.find_all("tr", class_="RowEven") - rows = rows_odd + rows_even - - calendar = [] - - for i in range(len(rows)): - if rows[i].find("td", class_="KuvSuplovanaHodina") is not None and rows[i].find("td", class_="KuvSuplujiciHodina") is None: - continue - - subjects = [] - wheres = [] - cells = rows[i].find_all("td", attrs={"class": "DctCell"}) - for j in range(len(cells)): - if cells[j].text == "": - new_span = soup.new_tag("span", attrs={'class': 'KuvBunkaRozvrhNadpis'}) - new_span.string = "Volno" - cells[j].append(new_span) - - if rows[i].find("td", class_="KuvHeaderNadpis") is not None: - day = rows[i].find("td", class_="KuvHeaderNadpis").text - - date = rows[i].find("td", class_="KuvHeaderText").text - - subjects_ = rows[i].find_all("span", class_="KuvBunkaRozvrhNadpis") - temp = [] - for j in range(len(subjects_)): - temp.append(subjects_[j].text) - subjects = temp - - F_con = False - try: - while subjects[-1] == "Volno": - del subjects[-1] - if subjects == []: - F_con = True - except IndexError: - pass - - wheres_ = rows[i].find_all("span", class_="KuvBunkaRozvrhText") - temp = [] - for j in range(len(wheres_)): - if len(subjects[j]) < 10: - temp.append(wheres_[j].text[4:]) - else: - temp.append(" - ") - wheres = temp - - for j in range(len(cells)): - if cells[j].get("colspan") is not None: - if int(cells[j].get("colspan")) == 2: - subjects.insert(j, subjects[j]) - wheres.insert(j, wheres[j]) - for j in range(len(subjects)): - if subjects[j] == "Volno": - wheres.insert(j, " - ") - - if F_con == False: - calendar_row = { - "DAY": day, - "DATE": date, - "SUBJECTS": subjects, - "WHERES": wheres - } - - calendar.append(calendar_row) - - sorted_calendar = sort_calendar(calendar) - - return sorted_calendar - except AttributeError: - global not_login - - not_login = 1 - schedule = fetch_locally("schedule") - return schedule - -def schedule_from_file_to_list(): - schedule = [] - schedule_ = [] - - try: - with open("schedule.csv") as f: - import csv - reader = csv.reader(f) - for row in reader: - temp = [] - for col in row: - temp.append(col.strip()) - schedule_.append(temp) - - for i in range(0, len(schedule_), 2): - del schedule_[i][0] - - temp = [] - for i in range(1, len(schedule_), 2): - temp.append(schedule_[i][0]) - del schedule_[i][0] - schedule.append(temp) - - for i in range(10): - temp = [] - for j in range(10): - try: - temp.append(schedule_[j][0]) - del schedule_[j][0] - except IndexError: - pass - schedule.append(temp) - except FileNotFoundError: - print("No schedule.csv file found\n") - - return schedule - -def get_whitespace(key: str, idx=0) -> int: - schedule = schedule_from_file_to_list() - max_len = 0 - - if key == "DATE": - try: - max_len = len(max(schedule[0], key=len)) - except ValueError: - pass - elif key == "WHERES": - try: - max_len = len(max(schedule[idx], key=len)) - except ValueError: - pass - - return max_len - -def show_schedule(): - # if there is internet access, load stuff from the web - # if not, load the schedule.csv file - if is_connected(REMOTE_SERVER) == True: - schedule = get_schedule("/SOL/App/Kalendar/KZK001_KalendarTyden.aspx") - schedule_to_file(schedule) - else: - schedule = schedule_from_file() - - print("--------") - print(" Rozvrh") - print("--------\n") - - if schedule == []: - print("N/A\n") - import os - - if os.path.exists("schedule.csv"): - os.remove("schedule.csv") - return - - for i in range(len(schedule)): - max_len = get_whitespace("DATE") - - whitespace = " " * (max_len - len(schedule[i]["DAY"])) - print(schedule[i]["DAY"] + whitespace, end=" ") - - for j in range(len(schedule[i]["SUBJECTS"])): - max_len = get_whitespace("WHERES", j+1) - whitespace = " " * (max_len - len(schedule[i]["SUBJECTS"][j])) - print("| " + schedule[i]["SUBJECTS"][j] + whitespace, end=" ") - - print("") - - max_len = get_whitespace("DATE") - whitespace = " " * (max_len - len(schedule[i]["DATE"])) - print(schedule[i]["DATE"] + whitespace, end=" ") - - for j in range(len(schedule[i]["WHERES"])): - max_len = get_whitespace("WHERES", j+1) - whitespace = " " * (max_len - len(schedule[i]["WHERES"][j])) - print("| " + schedule[i]["WHERES"][j] + whitespace, end=" ") - - print("") - print("") - -def get_avg(grades: list) -> float: - if len(grades) < 1: - return "" - - sum_ = 0 - for i in grades: - sum_ += int(i) - avg = round(sum_ / len(grades), 2) - - return str(avg) - -def get_grades(url: str): - html = get_html_from(url) - - soup = BeautifulSoup(html.text, "lxml") - - rows = soup.find("table", id="G_ctl00xmainxCCADynamicUWGrid").find_all("tr") - for i in range(3): - r = soup.find("table", id="G_ctl00xmainxCCADynamicUWGrid").find("tr") - r.decompose() - - grades = [] - - for i in range(1, len(rows)): - if rows[i].find("td") is not None: - subject = rows[i].find("td").text - temp_dict = {} - temp_dict["SUBJECT"] = subject - cell = rows[i].find_all("span", class_="VHVysl") - temp = [] - for j in range(len(cell)): - temp.append(cell[j].text) - temp_dict["GRADES"] = temp - - grades.append(temp_dict) - - return grades - -def show_grades(): - if is_connected(REMOTE_SERVER) == True: - grades = get_grades("/SOL/App/Hodnoceni/KZH001_HodnVypisStud.aspx") - grades_to_file(grades) - else: - grades = grades_from_file() - - whitespace = "" - max_len_of_subject = 0 - subjects = [grades[j]["SUBJECT"] for j in range(len(grades))] - for i in subjects: - if len(i) > max_len_of_subject: - max_len_of_subject = len(i) - max_len_of_subject += 1 - - print("--------") - print(" Znamky") - print("--------\n") - - if grades == []: - print("N/A\n") - import os - - if os.path.exists("grades.csv"): - os.remove("grades.csv") - return - - for i in range(len(grades)): - whitespace = " " * (max_len_of_subject - len(grades[i]["SUBJECT"])) - print(grades[i]["SUBJECT"] + whitespace + "|", end=" ") - print("".join([grades[i]["GRADES"][j]+" " for j in range(len(grades[i]["GRADES"]))]), end=" ") - print("|", get_avg(grades[i]["GRADES"])) - print("") - print("") - -def schedule_to_file(schedule=None): - import csv - if schedule is None: - try: - schedule = get_schedule("/SOL/App/Kalendar/KZK001_KalendarTyden.aspx") - except Exception: - print("An error occured, you probably can't access the internet right now") - return - - with open("schedule.csv", mode="w", newline="") as f: - data = [] - - for i in range(len(schedule)): - temp = [] - try: - temp.append(schedule[i]["DAY"]) - for j in range(len(schedule[i]["SUBJECTS"])): - temp.append(schedule[i]["SUBJECTS"][j]) - data.append(temp) - - temp = [] - temp.append(schedule[i]["DATE"]) - for j in range(len(schedule[i]["WHERES"])): - temp.append(schedule[i]["WHERES"][j]) - data.append(temp) - - temp = [] - for j in range(len(schedule[i]["WHOS"])): - temp.append(schedule[i]["WHOS"][j]) - data.append(temp) - except KeyError: - pass - - writer = csv.writer(f) - for row in data: - writer.writerow(row) - -def schedule_from_file() -> list: - import csv - schedule = [] - - try: - with open("schedule.csv", mode="r") as f: - reader = csv.reader(f) - rows = [] - for row in reader: - rows.append(row) - - for row in range(0, len(rows), 3): - temp = {} - - temp["DAY"] = rows[row][0] - - try: - temp["DATE"] = rows[row+1][0] - except IndexError: - pass - - subjects = [] - for i in range(1, len(rows[row])): - subjects.append(rows[row][i]) - temp["SUBJECTS"] = subjects - - wheres = [] - try: - for i in range(1, len(rows[row+1])): - wheres.append(rows[row+1][i]) - except IndexError: - pass - temp["WHERES"] = wheres - - whos = [] - try: - for i in range(len(rows[row+2])): - whos.append(rows[row+2][i]) - except IndexError: - pass - temp["WHOS"] = whos - - schedule.append(temp) - except FileNotFoundError: - print("No schedule.csv file found\n") - - return schedule - -def grades_to_file(grades=None): # !!! make sure the format of the grades list is saved correctly !!! - import csv - if grades is None: - try: - grades = get_grades("/SOL/App/Hodnoceni/KZH001_HodnVypisStud.aspx") - except Exception: - print("An error occured, you probably can't access the internet right now") - return - - data = [] - - with open("grades.csv", mode="w", newline="") as f: - for i in range(len(grades)): - temp = {} - temp["SUBJECT"] = grades[i]["SUBJECT"] - temp_grades = [] - for j in range(len(grades[i]["GRADES"])): - temp_grades.append(grades[i]["GRADES"][j]) - temp["GRADES"] = temp_grades - data.append(temp) - - writer = csv.writer(f) - for row in data: - _row = [] - _row.append(row["SUBJECT"]) - for i in row["GRADES"]: - _row.append(i) - writer.writerow(_row) - -def grades_from_file() -> list: - import csv - grades = [] - - try: - with open("grades.csv", mode="r") as f: - reader = csv.reader(f) - rows = [] - for row in reader: - rows.append(row) - - for row in range(len(rows)): - temp = {} - - temp["SUBJECT"] = rows[row][0] - - temp_lst = [] - for i in range(1, len(rows[row])): - temp_lst.append(rows[row][i]) - temp["GRADES"] = temp_lst - - grades.append(temp) - except FileNotFoundError: - print("No grades.csv file found\n") - - return grades - -if __name__ == "__main__": - user = str(input("Zadejte prihlasovaci jmeno: ")) - pwd = str(input("Zadejte heslo: ")) - - if is_connected(REMOTE_SERVER) == True: - login(user, pwd) - #get_schedule("/SOL/App/Kalendar/KZK001_KalendarTyden.aspx") - show_schedule() - #get_grades("/SOL/App/Hodnoceni/KZH001_HodnVypisStud.aspx") - show_grades() - #schedule_to_file() - #grades_to_file() - #schedule_from_file() diff --git a/src/lib/__init__.py b/src/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/__pycache__/__init__.cpython-311.pyc b/src/lib/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..422999a Binary files /dev/null and b/src/lib/__pycache__/__init__.cpython-311.pyc differ diff --git a/src/lib/__pycache__/grades.cpython-311.pyc b/src/lib/__pycache__/grades.cpython-311.pyc new file mode 100644 index 0000000..3a689d7 Binary files /dev/null and b/src/lib/__pycache__/grades.cpython-311.pyc differ diff --git a/src/lib/__pycache__/networking.cpython-311.pyc b/src/lib/__pycache__/networking.cpython-311.pyc new file mode 100644 index 0000000..a0ed49b Binary files /dev/null and b/src/lib/__pycache__/networking.cpython-311.pyc differ diff --git a/src/lib/__pycache__/schedule_week.cpython-311.pyc b/src/lib/__pycache__/schedule_week.cpython-311.pyc new file mode 100644 index 0000000..80485a7 Binary files /dev/null and b/src/lib/__pycache__/schedule_week.cpython-311.pyc differ diff --git a/src/lib/grades.py b/src/lib/grades.py new file mode 100644 index 0000000..1776652 --- /dev/null +++ b/src/lib/grades.py @@ -0,0 +1,151 @@ +from lib import networking as nw +from bs4 import BeautifulSoup + +not_login = 0 +F_not_anymore = 0 + +def fetch_locally() -> list: + global not_login, F_not_anymore + + if not_login == 1 and F_not_anymore == 0: + F_not_anymore = 1 + not_login = 0 + print("Could not sign in (you may have entered invalid login credentials)") + print("Fetching locally\n") + grades = grades_from_file() + return grades + + +def get_avg(grades: list) -> str: + if len(grades) < 1: + return "" + + sum_ = 0 + for i in grades: + sum_ += int(i) + avg = round(sum_ / len(grades), 2) + + avg = str(avg) + if len(avg) == 3: + avg += "0" + + return avg + +def get_grades(url: str): + html = nw.get_html_from(url) + + soup = BeautifulSoup(html.text, "lxml") + + rows = soup.find("table", id="G_ctl00xmainxCCADynamicUWGrid").find_all("tr") + for i in range(3): + r = soup.find("table", id="G_ctl00xmainxCCADynamicUWGrid").find("tr") + r.decompose() + + grades = [] + + for i in range(1, len(rows)): + if rows[i].find("td") is not None: + subject = rows[i].find("td").text + temp_dict = {} + temp_dict["SUBJECT"] = subject + cell = rows[i].find_all("span", class_="VHVysl") + temp = [] + for j in range(len(cell)): + temp.append(cell[j].text) + temp_dict["GRADES"] = temp + + grades.append(temp_dict) + + return grades + +def show_grades(): + if nw.is_connected() == True: + grades = get_grades("/SOL/App/Hodnoceni/KZH001_HodnVypisStud.aspx") + grades_to_file(grades) + else: + grades = grades_from_file() + + whitespace = "" + max_len_of_subject = 0 + subjects = [grades[j]["SUBJECT"] for j in range(len(grades))] + for i in subjects: + if len(i) > max_len_of_subject: + max_len_of_subject = len(i) + max_len_of_subject += 1 + + print("--------") + print(" Známky ") + print("--------\n") + + if grades == []: + print("N/A\n") + import os + + if os.path.exists("src/lib/data/grades.csv"): + os.remove("src/lib/data/grades.csv") + return + + for i in range(len(grades)): + if grades[i]["GRADES"] != []: + whitespace = " " * (max_len_of_subject - len(grades[i]["SUBJECT"])) + print(grades[i]["SUBJECT"] + whitespace + "|", end=" ") + print(get_avg(grades[i]["GRADES"]), "|", end=" ") + print("".join([grades[i]["GRADES"][j]+" " for j in range(len(grades[i]["GRADES"]))]), end=" ") + print("") + print("") + +def grades_to_file(grades=None): # !!! make sure the format of the grades list is saved correctly !!! + import csv + if grades is None: + try: + grades = get_grades("/SOL/App/Hodnoceni/KZH001_HodnVypisStud.aspx") + except Exception: + print("An error occured, you probably can't access the internet right now") + return + + data = [] + + with open("src/lib/data/grades.csv", mode="w", newline="") as f: + for i in range(len(grades)): + temp = {} + temp["SUBJECT"] = grades[i]["SUBJECT"] + temp_grades = [] + for j in range(len(grades[i]["GRADES"])): + temp_grades.append(grades[i]["GRADES"][j]) + temp["GRADES"] = temp_grades + data.append(temp) + + writer = csv.writer(f) + for row in data: + _row = [] + _row.append(row["SUBJECT"]) + for i in row["GRADES"]: + _row.append(i) + writer.writerow(_row) + +def grades_from_file() -> list: + import csv + grades = [] + + try: + with open("src/lib/data/grades.csv", mode="r") as f: + reader = csv.reader(f) + rows = [] + for row in reader: + rows.append(row) + + for row in range(len(rows)): + temp = {} + + temp["SUBJECT"] = rows[row][0] + + temp_lst = [] + for i in range(1, len(rows[row])): + temp_lst.append(rows[row][i]) + temp["GRADES"] = temp_lst + + grades.append(temp) + except FileNotFoundError: + print("No grades.csv file found\n") + + return grades \ No newline at end of file diff --git a/src/lib/networking.py b/src/lib/networking.py new file mode 100644 index 0000000..068392d --- /dev/null +++ b/src/lib/networking.py @@ -0,0 +1,63 @@ +import requests +from bs4 import BeautifulSoup + +not_login = 0 +F_not_anymore = 0 +session = requests.Session() + +def login(user: str, pwd: str) -> bool: + if is_connected() == True: + url: str = "https://aplikace.skolaonline.cz/SOL/Prihlaseni.aspx" + data = { + "__EVENTTARGET": "dnn$ctr994$SOLLogin$btnODeslat", + "__EVENTARGUMENT": "", + "__VIEWSTATE": "", + "__VIEWSTATEGENERATOR": "", + "__VIEWSTATEENCRYPTED": "", + "__PREVIOUSPAGE": "", + "__EVENTVALIDATION": "", + "dnn$dnnSearch$txtSearch": "", + "JmenoUzivatele": user, # username + "HesloUzivatele": pwd, # password + "ScrollTop": "", + "__dnnVariable": "", + "__RequestVerificationToken": "" + } + + post_login = session.post(url, data=data) + if post_login.status_code != 200: + #print("Could not sign in") + return False + else: + #print("Sign in successful") + return True + else: + #print("Could not sign in") + #print("Fetching data from local files") + return False + +def is_connected() -> bool: + import socket + + try: + host = socket.gethostbyname("one.one.one.one") + s = socket.create_connection((host, 80), 2) + s.close() + return True + except Exception: + pass + return False + +def get_html_from(params=None) -> str: + base = "https://aplikace.skolaonline.cz" + + if params is not None: + base += params + + response = session.get(base) + if response.status_code == 200: + #print("Download successful") + return response + else: + print("Download unsuccessful") + return "" diff --git a/src/lib/schedule_week.py b/src/lib/schedule_week.py new file mode 100644 index 0000000..bfc1644 --- /dev/null +++ b/src/lib/schedule_week.py @@ -0,0 +1,304 @@ +from lib import networking as nw +from bs4 import BeautifulSoup + +not_login = 0 +F_not_anymore = 0 + +def fetch_locally() -> list: + global not_login, F_not_anymore + + if not_login == 1 and F_not_anymore == 0: + F_not_anymore = 1 + not_login = 0 + print("Could not sign in (you may have entered invalid login credentials)") + print("Fetching locally\n") + schedule_week = schedule_week_from_file() + return schedule_week + + +def sort_schedule_week(schedule_week: list[dict]) -> list[dict]: + sorted_schedule_week: list[dict] = [{}, {}, {}, {}, {}] + + for i in range(len(schedule_week)): + if schedule_week[i]["DAY"] == "Po": + sorted_schedule_week[0] = schedule_week[i] + if schedule_week[i]["DAY"] == "Út": + sorted_schedule_week[1] = schedule_week[i] + if schedule_week[i]["DAY"] == "St": + sorted_schedule_week[2] = schedule_week[i] + if schedule_week[i]["DAY"] == "Čt": + sorted_schedule_week[3] = schedule_week[i] + if schedule_week[i]["DAY"] == "Pá": + sorted_schedule_week[4] = schedule_week[i] + + return sorted_schedule_week + +def get_schedule_week(url: str): + try: + html = nw.get_html_from(url) + + soup = BeautifulSoup(html.text, "lxml") + + table = soup.find("table", id="CCADynamicCalendarTable") + + rows_odd = table.find_all("tr", class_="RowOdd") + rows_even = table.find_all("tr", class_="RowEven") + rows = rows_odd + rows_even + + schedule_week = [] + + for i in range(len(rows)): + if rows[i].find("td", class_="KuvSuplovanaHodina") is not None and rows[i].find("td", class_="KuvSuplujiciHodina") is None: + continue + + subjects = [] + wheres = [] + cells = rows[i].find_all("td", attrs={"class": "DctCell"}) + for j in range(len(cells)): + if cells[j].text == "": + new_span = soup.new_tag("span", attrs={'class': 'KuvBunkaRozvrhNadpis'}) + new_span.string = "Volno" + cells[j].append(new_span) + + if rows[i].find("td", class_="KuvHeaderNadpis") is not None: + day = rows[i].find("td", class_="KuvHeaderNadpis").text + + date = rows[i].find("td", class_="KuvHeaderText").text + + subjects_ = rows[i].find_all("span", class_="KuvBunkaRozvrhNadpis") + temp = [] + for j in range(len(subjects_)): + temp.append(subjects_[j].text) + subjects = temp + + F_con = False + try: + while subjects[-1] == "Volno": + del subjects[-1] + if subjects == []: + F_con = True + except IndexError: + pass + + wheres_ = rows[i].find_all("span", class_="KuvBunkaRozvrhText") + temp = [] + for j in range(len(wheres_)): + if len(subjects[j]) < 10: + temp.append(wheres_[j].text[4:]) + else: + temp.append(" - ") + wheres = temp + + for j in range(len(cells)): + if cells[j].get("colspan") is not None: + if int(cells[j].get("colspan")) == 2: + subjects.insert(j, subjects[j]) + wheres.insert(j, wheres[j]) + for j in range(len(subjects)): + if subjects[j] == "Volno": + wheres.insert(j, " - ") + + if F_con == False: + schedule_week_row = { + "DAY": day, + "DATE": date, + "SUBJECTS": subjects, + "WHERES": wheres + } + + schedule_week.append(schedule_week_row) + + sorted_schedule_week = sort_schedule_week(schedule_week) + + return sorted_schedule_week + except AttributeError: + global not_login + + not_login = 1 + schedule = fetch_locally() + return schedule + +def schedule_week_from_file_to_list(): + schedule = [] + schedule_ = [] + + try: + with open("src/lib/data/schedule_week.csv") as f: + import csv + reader = csv.reader(f) + for row in reader: + temp = [] + for col in row: + temp.append(col.strip()) + schedule_.append(temp) + + for i in range(0, len(schedule_), 2): + del schedule_[i][0] + + temp = [] + for i in range(1, len(schedule_), 2): + temp.append(schedule_[i][0]) + del schedule_[i][0] + schedule.append(temp) + + for i in range(10): + temp = [] + for j in range(10): + try: + temp.append(schedule_[j][0]) + del schedule_[j][0] + except IndexError: + pass + schedule.append(temp) + except FileNotFoundError: + print("No schedule_week.csv file found\n") + + return schedule + +def get_whitespace(key: str, idx=0) -> int: + schedule = schedule_week_from_file_to_list() + max_len = 0 + + if key == "DATE": + try: + max_len = len(max(schedule[0], key=len)) + except ValueError: + pass + elif key == "WHERES": + try: + max_len = len(max(schedule[idx], key=len)) + except ValueError: + pass + + return max_len + +def show_schedule_week(): + # if there is internet access, load stuff from the web + # if not, load the schedule.csv file + if nw.is_connected() == True: + schedule = get_schedule_week("/SOL/App/Kalendar/KZK001_KalendarTyden.aspx") + schedule_week_to_file(schedule) + else: + schedule = schedule_week_from_file() + + print("----------------") + print(" Týdenní rozvrh ") + print("----------------\n") + + if schedule == []: + print("N/A\n") + import os + + if os.path.exists("src/lib/data/schedule_week.csv"): + os.remove("src/lib/data/schedule_week.csv") + return + + for i in range(len(schedule)): + max_len = get_whitespace("DATE") + + whitespace = " " * (max_len - len(schedule[i]["DAY"])) + print(schedule[i]["DAY"] + whitespace, end=" ") + + for j in range(len(schedule[i]["SUBJECTS"])): + max_len = get_whitespace("WHERES", j+1) + whitespace = " " * (max_len - len(schedule[i]["SUBJECTS"][j])) + print("| " + schedule[i]["SUBJECTS"][j] + whitespace, end=" ") + + print("") + + max_len = get_whitespace("DATE") + whitespace = " " * (max_len - len(schedule[i]["DATE"])) + print(schedule[i]["DATE"] + whitespace, end=" ") + + for j in range(len(schedule[i]["WHERES"])): + max_len = get_whitespace("WHERES", j+1) + whitespace = " " * (max_len - len(schedule[i]["WHERES"][j])) + print("| " + schedule[i]["WHERES"][j] + whitespace, end=" ") + + print("") + print("") + +def schedule_week_to_file(schedule=None): + import csv + if schedule is None: + try: + schedule = get_schedule_week("/SOL/App/Kalendar/KZK001_KalendarTyden.aspx") + except Exception: + print("An error occured, you probably can't access the internet right now") + return + + with open("src/lib/data/schedule_week.csv", mode="w", newline="") as f: + data = [] + + for i in range(len(schedule)): + temp = [] + try: + temp.append(schedule[i]["DAY"]) + for j in range(len(schedule[i]["SUBJECTS"])): + temp.append(schedule[i]["SUBJECTS"][j]) + data.append(temp) + + temp = [] + temp.append(schedule[i]["DATE"]) + for j in range(len(schedule[i]["WHERES"])): + temp.append(schedule[i]["WHERES"][j]) + data.append(temp) + + temp = [] + for j in range(len(schedule[i]["WHOS"])): + temp.append(schedule[i]["WHOS"][j]) + data.append(temp) + except KeyError: + pass + + writer = csv.writer(f) + for row in data: + writer.writerow(row) + +def schedule_week_from_file() -> list: + import csv + schedule = [] + + try: + with open("src/lib/data/schedule_week.csv", mode="r") as f: + reader = csv.reader(f) + rows = [] + for row in reader: + rows.append(row) + + for row in range(0, len(rows), 3): + temp = {} + + temp["DAY"] = rows[row][0] + + try: + temp["DATE"] = rows[row+1][0] + except IndexError: + pass + + subjects = [] + for i in range(1, len(rows[row])): + subjects.append(rows[row][i]) + temp["SUBJECTS"] = subjects + + wheres = [] + try: + for i in range(1, len(rows[row+1])): + wheres.append(rows[row+1][i]) + except IndexError: + pass + temp["WHERES"] = wheres + + whos = [] + try: + for i in range(len(rows[row+2])): + whos.append(rows[row+2][i]) + except IndexError: + pass + temp["WHOS"] = whos + + schedule.append(temp) + except FileNotFoundError: + print("No schedule_week.csv file found\n") + + return schedule diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..f44ff38 --- /dev/null +++ b/src/main.py @@ -0,0 +1,17 @@ +from lib import grades as gr +from lib import networking as nw +from lib import schedule_week as sw + +if __name__ == "__main__": + user = str(input("Zadejte přihlašovací jméno: ")) + pwd = str(input("Zadejte heslo: ")) + + if nw.is_connected() == True: + nw.login(user, pwd) + #sw.get_schedule_week("/SOL/App/Kalendar/KZK001_KalendarTyden.aspx") + sw.show_schedule_week() + #gr.get_grades("/SOL/App/Hodnoceni/KZH001_HodnVypisStud.aspx") + gr.show_grades() + #sw.schedule_week_to_file() + #gr.grades_to_file() + #sw.schedule_week_from_file()