377 lines
11 KiB
Python
Executable File
377 lines
11 KiB
Python
Executable File
"""
|
|
Functions related to this
|
|
week's schedule.
|
|
"""
|
|
|
|
from solenlib import networking as nw
|
|
from solenlib import crypto as cr
|
|
from bs4 import BeautifulSoup
|
|
import os
|
|
|
|
not_login = 0
|
|
|
|
def fetch_locally(password, username) -> list:
|
|
"""
|
|
Helper function for extracting
|
|
data from a local file.
|
|
"""
|
|
|
|
global not_login
|
|
|
|
if not_login == 1:
|
|
not_login = 0
|
|
|
|
schedule = schedule_from_file(password, username)
|
|
return schedule
|
|
|
|
|
|
def sort_schedule(schedule: list[dict]) -> list[dict]:
|
|
"""
|
|
Helper function for sorting
|
|
the schedule correctly.
|
|
"""
|
|
|
|
sorted_schedule: list[dict] = [{}, {}, {}, {}, {}]
|
|
|
|
for i in range(len(schedule)):
|
|
if schedule[i]["DAY"] == "Po":
|
|
sorted_schedule[0] = schedule[i]
|
|
if schedule[i]["DAY"] == "Út":
|
|
sorted_schedule[1] = schedule[i]
|
|
if schedule[i]["DAY"] == "St":
|
|
sorted_schedule[2] = schedule[i]
|
|
if schedule[i]["DAY"] == "Čt":
|
|
sorted_schedule[3] = schedule[i]
|
|
if schedule[i]["DAY"] == "Pá":
|
|
sorted_schedule[4] = schedule[i]
|
|
|
|
return sorted_schedule
|
|
|
|
def get_schedule(password, url: str) -> list:
|
|
"""
|
|
Filters & extracts the schedule from
|
|
the HTML soup.
|
|
"""
|
|
|
|
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 = []
|
|
|
|
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 and rows[i].find("td", class_="KuvSkolniAkceHodina") is None and rows[i].find("td", class_="DctInnerTableType10DataTD") is None:
|
|
continue
|
|
|
|
subjects = []
|
|
wheres = []
|
|
cells = rows[i].find_all("td", attrs={"class": "DctCell"})
|
|
|
|
header_ = table.find("tr").find_all("td", class_="KuvHeaderNadpis")
|
|
header = []
|
|
for val in header_:
|
|
header.append(val.text)
|
|
|
|
for j in range(len(cells)):
|
|
if cells[j].text == "" and header[j] != " - ":
|
|
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_)):
|
|
if "KuvSuplovanaHodina" not in subjects_[j].parent["class"]:
|
|
temp.append(subjects_[j].text)
|
|
else:
|
|
temp.append("Volno")
|
|
subjects = temp
|
|
|
|
F_continue = False
|
|
try:
|
|
while subjects[-1] == "Volno":
|
|
del subjects[-1]
|
|
if subjects == []:
|
|
F_continue = True
|
|
except IndexError:
|
|
pass
|
|
|
|
if subjects == []:
|
|
F_continue = True
|
|
|
|
wheres_ = rows[i].find_all("span", class_="KuvBunkaRozvrhText")
|
|
temp = []
|
|
for j in range(len(wheres_)):
|
|
try:
|
|
if len(subjects[j]) < 10:
|
|
if len(wheres_[j].text[4:]) > 10:
|
|
temp.append(" - ")
|
|
elif "KuvSuplovanaHodina" not in wheres_[j].parent["class"]:
|
|
temp.append(wheres_[j].text[4:])
|
|
else:
|
|
temp.append(" - ")
|
|
except IndexError:
|
|
pass
|
|
wheres = temp
|
|
|
|
for j in range(len(cells)):
|
|
if cells[j].get("colspan") is not None:
|
|
if int(cells[j].get("colspan")) == 2:
|
|
try:
|
|
subjects.insert(j, subjects[j])
|
|
wheres.insert(j, wheres[j])
|
|
except IndexError:
|
|
pass
|
|
for j in range(len(subjects)):
|
|
if subjects[j] == "Volno":
|
|
wheres.insert(j, " - ")
|
|
|
|
while True:
|
|
if len(subjects) > len(wheres):
|
|
del subjects[-1]
|
|
elif len(subjects) < len(wheres):
|
|
del wheres[-1]
|
|
else:
|
|
break
|
|
|
|
if F_continue == False:
|
|
schedule_row = {
|
|
"DAY": day,
|
|
"DATE": date,
|
|
"SUBJECTS": subjects,
|
|
"WHERES": wheres
|
|
}
|
|
|
|
schedule.append(schedule_row)
|
|
|
|
sorted_schedule = sort_schedule(schedule)
|
|
|
|
return sorted_schedule
|
|
except AttributeError:
|
|
global not_login
|
|
|
|
not_login = 1
|
|
schedule = fetch_locally()
|
|
return schedule
|
|
|
|
def schedule_from_file_to_list(password, username, strdata):
|
|
"""
|
|
Extracts the schedule from
|
|
a local file and returns
|
|
it in a list, which is better
|
|
for the get_whitespace() function.
|
|
"""
|
|
|
|
schedule = []
|
|
schedule_ = []
|
|
|
|
import csv
|
|
from io import StringIO
|
|
f = StringIO(strdata)
|
|
reader = csv.reader(f, delimiter=",")
|
|
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)
|
|
|
|
return schedule
|
|
|
|
def get_whitespace(password, username, strdata, key: str, idx=0) -> int:
|
|
"""
|
|
Helper function that calculates
|
|
how much whitespaces are needed
|
|
in order to display the table grid
|
|
correctly.
|
|
"""
|
|
|
|
schedule = schedule_from_file_to_list(password, username, strdata)
|
|
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
|
|
|
|
print(max_len)
|
|
return max_len
|
|
|
|
def show_schedule(password, username, local=False):
|
|
"""
|
|
Shows the schedule on the
|
|
terminal in a pretty way.
|
|
"""
|
|
|
|
try:
|
|
strdata = cr.read_from_file_and_decrypt(password, f"{os.environ['HOME']}/.local/lib/solendata/{nw.get_user_hash(username)}-schedule_week")
|
|
except:
|
|
print("Could not read the file")
|
|
return
|
|
|
|
if local == False:
|
|
# 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(password, "/SOL/App/Kalendar/KZK001_KalendarTyden.aspx")
|
|
schedule_to_file(password, username, schedule)
|
|
else:
|
|
schedule = schedule_from_file(password, username)
|
|
else:
|
|
schedule = schedule_from_file(password, username)
|
|
|
|
print("")
|
|
|
|
print("----------------")
|
|
print(" Týdenní rozvrh ")
|
|
print("----------------\n")
|
|
|
|
if schedule == []:
|
|
print("N/A\n")
|
|
|
|
return
|
|
|
|
for i in range(len(schedule)):
|
|
max_len = get_whitespace(password, username, strdata, "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(password, username, strdata, "WHERES", j+1)
|
|
whitespace = " " * (max_len - len(schedule[i]["SUBJECTS"][j]))
|
|
print("| " + schedule[i]["SUBJECTS"][j] + whitespace, end=" ")
|
|
|
|
print("")
|
|
|
|
max_len = get_whitespace(password, username, strdata, "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(password, username, strdata, "WHERES", j+1)
|
|
whitespace = " " * (max_len - len(schedule[i]["WHERES"][j]))
|
|
print("| " + schedule[i]["WHERES"][j] + whitespace, end=" ")
|
|
|
|
print("")
|
|
|
|
def schedule_to_file(password, username, schedule=None):
|
|
"""
|
|
Writes the schedule to
|
|
a local file for later
|
|
use.
|
|
"""
|
|
|
|
if schedule is None:
|
|
try:
|
|
schedule = get_schedule(password, "/SOL/App/Kalendar/KZK001_KalendarTyden.aspx")
|
|
except:
|
|
print("An error occured, you probably can't access the internet right now")
|
|
return
|
|
|
|
lstrdata = []
|
|
|
|
for row in schedule:
|
|
lstrdata.append(row["DAY"])
|
|
lstrdata.append(",")
|
|
for i in row["SUBJECTS"]:
|
|
lstrdata.append(i)
|
|
lstrdata.append(",")
|
|
del lstrdata[-1]
|
|
lstrdata.append("\n")
|
|
|
|
lstrdata.append(row["DATE"])
|
|
lstrdata.append(",")
|
|
for i in row["WHERES"]:
|
|
lstrdata.append(i)
|
|
lstrdata.append(",")
|
|
del lstrdata[-1]
|
|
lstrdata.append("\n")
|
|
|
|
strdata = "".join(lstrdata)
|
|
|
|
cr.encrypt_and_write_to_file(password, strdata, f"{os.environ['HOME']}/.local/lib/solendata/{nw.get_user_hash(username)}-schedule_week")
|
|
|
|
def schedule_from_file(password, username) -> list:
|
|
"""
|
|
Fetches schedule data from a file.
|
|
"""
|
|
|
|
import csv
|
|
from io import StringIO
|
|
schedule = []
|
|
|
|
try:
|
|
strdata = cr.read_from_file_and_decrypt(password, f"{os.environ['HOME']}/.local/lib/solendata/{nw.get_user_hash(username)}-schedule_week")
|
|
except:
|
|
print("Could not read the file")
|
|
return
|
|
f = StringIO(strdata)
|
|
reader = csv.reader(f)
|
|
rows = []
|
|
for row in reader:
|
|
rows.append(row)
|
|
|
|
for row in range(0, len(rows), 2):
|
|
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
|
|
|
|
schedule.append(temp)
|
|
print(schedule)
|
|
return schedule
|