got rid of the pc (kinda debug) version
This commit is contained in:
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if command -v solen > /dev/null
|
|
||||||
then
|
|
||||||
solen
|
|
||||||
else
|
|
||||||
python3 "./src/main.py"
|
|
||||||
fi
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [ ! -d "$HOME/.local/lib/python3.11/site-packages/solenlib" ]; then
|
|
||||||
sudo mkdir --parents "$HOME/.local/lib/python3.11/site-packages/solenlib"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d "$HOME/.local/lib/solendata" ]; then
|
|
||||||
sudo mkdir --parents "$HOME/.local/lib/solendata"
|
|
||||||
fi
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
SHELL=/bin/bash
|
|
||||||
|
|
||||||
install:
|
|
||||||
python -m pip install -r requirements.txt
|
|
||||||
|
|
||||||
./.config/mkdirs.sh
|
|
||||||
|
|
||||||
sudo cp ./src/main.py /bin/solen
|
|
||||||
sudo chown $(USER) /bin/solen
|
|
||||||
|
|
||||||
sudo cp ./src/lib/*.py $(HOME)/.local/lib/python3.10/site-packages/solenlib
|
|
||||||
|
|
||||||
run:
|
|
||||||
./.config/launch.sh
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
lxml
|
|
||||||
bs4
|
|
||||||
requests
|
|
||||||
cryptography
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
"""
|
|
||||||
Cryptography related stuff - mostly
|
|
||||||
encrypting and decrypting user data.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from cryptography.hazmat.backends import default_backend
|
|
||||||
from cryptography.hazmat.primitives import hashes
|
|
||||||
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
|
||||||
from cryptography.fernet import Fernet
|
|
||||||
import base64
|
|
||||||
import os
|
|
||||||
|
|
||||||
def get_key(password: str) -> bytes:
|
|
||||||
"""
|
|
||||||
Derives a bytes key
|
|
||||||
from a given password.
|
|
||||||
|
|
||||||
Useful when you want
|
|
||||||
to generate the same
|
|
||||||
key over and over again.
|
|
||||||
E.g. to encrypt/decrypt
|
|
||||||
locally stored user data.
|
|
||||||
"""
|
|
||||||
|
|
||||||
password = password.encode()
|
|
||||||
|
|
||||||
salt = b'?\x0f\xa1\x97otT\xe48\xc9O\xb4\x1f\xef\xf5\xea'
|
|
||||||
|
|
||||||
kdf = PBKDF2HMAC(
|
|
||||||
algorithm=hashes.SHA256,
|
|
||||||
length=32,
|
|
||||||
salt=salt,
|
|
||||||
iterations=100000,
|
|
||||||
backend=default_backend()
|
|
||||||
)
|
|
||||||
|
|
||||||
key = base64.urlsafe_b64encode(kdf.derive(password))
|
|
||||||
return key
|
|
||||||
|
|
||||||
def encrypt_and_write_to_file(password: str, strdata: str, file_path: str) -> bool:
|
|
||||||
"""
|
|
||||||
Encrypts the given string data
|
|
||||||
and stores them in a file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
key = get_key(password)
|
|
||||||
|
|
||||||
f = Fernet(key)
|
|
||||||
|
|
||||||
encrypted = f.encrypt(strdata.encode())
|
|
||||||
if os.path.exists(file_path):
|
|
||||||
with open(file_path, "wb") as ef:
|
|
||||||
ef.write(encrypted)
|
|
||||||
else:
|
|
||||||
os.system(f"touch {file_path}")
|
|
||||||
with open(file_path, "wb") as ef:
|
|
||||||
ef.write(encrypted)
|
|
||||||
|
|
||||||
return 0
|
|
||||||
except:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def read_from_file_and_decrypt(password: str, file_path: str) -> str:
|
|
||||||
"""
|
|
||||||
Reads contents of an encrypted file
|
|
||||||
and decrypts them.
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
key = get_key(password)
|
|
||||||
|
|
||||||
f = Fernet(key)
|
|
||||||
|
|
||||||
if os.path.exists(file_path):
|
|
||||||
with open(file_path, "rb") as ef:
|
|
||||||
decrypted = f.decrypt(ef.read())
|
|
||||||
else:
|
|
||||||
os.system(f"touch {file_path}")
|
|
||||||
with open(file_path, "rb") as ef:
|
|
||||||
decrypted = f.decrypt(ef.read())
|
|
||||||
|
|
||||||
return decrypted.decode()
|
|
||||||
except:
|
|
||||||
return ""
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
"""
|
|
||||||
Functions for grades related stuff.
|
|
||||||
Like 1, 2, 3, 4 and 5, in what subject,
|
|
||||||
what is the average of a subject, ...
|
|
||||||
"""
|
|
||||||
|
|
||||||
from solenlib import networking as nw
|
|
||||||
from solenlib import crypto as cr
|
|
||||||
from cryptography.fernet import Fernet
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
import os
|
|
||||||
|
|
||||||
not_login = 0
|
|
||||||
|
|
||||||
def fetch_locally(password, username) -> list:
|
|
||||||
"""
|
|
||||||
Helper function for exctracting
|
|
||||||
data from local files.
|
|
||||||
"""
|
|
||||||
|
|
||||||
global not_login
|
|
||||||
|
|
||||||
if not_login == 1:
|
|
||||||
not_login = 0
|
|
||||||
#print("Could not sign in (you may have entered invalid login credentials)")
|
|
||||||
#print("Fetching grades locally\n")
|
|
||||||
grades = grades_from_file(password, username)
|
|
||||||
return grades
|
|
||||||
|
|
||||||
def get_grades(password, url: str) -> list:
|
|
||||||
"""
|
|
||||||
Extracts the grades from the HTML soup
|
|
||||||
and returns them in a list of dictionaries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
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
|
|
||||||
cells = rows[i].find_all("span", class_="VHVysl")
|
|
||||||
temp = []
|
|
||||||
for j in range(len(cells)):
|
|
||||||
if cells[j].parent.has_attr("class"):
|
|
||||||
if "VHUzaverka" not in cells[j].parent["class"]:
|
|
||||||
temp.append(cells[j].text)
|
|
||||||
else:
|
|
||||||
temp.append(cells[j].text)
|
|
||||||
temp_dict["FINAL"] = rows[i].find("td", class_="VHUzaverka CCATooltip").text.replace(" ", "")
|
|
||||||
|
|
||||||
avg = rows[i].find("td", class_="VHCelkPrumer").text.replace(",", ".")
|
|
||||||
temp_dict["AVG"] = avg
|
|
||||||
|
|
||||||
temp_dict["GRADES"] = temp
|
|
||||||
|
|
||||||
grades.append(temp_dict)
|
|
||||||
|
|
||||||
return grades
|
|
||||||
except AttributeError:
|
|
||||||
global not_login
|
|
||||||
|
|
||||||
not_login = 1
|
|
||||||
grades = fetch_locally(password, username)
|
|
||||||
return grades
|
|
||||||
|
|
||||||
def show_grades(password, username, local=False):
|
|
||||||
"""
|
|
||||||
Shows the grades in the terminal
|
|
||||||
in a pretty way.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if local == False:
|
|
||||||
if nw.is_connected() == True:
|
|
||||||
grades = get_grades(password, "/SOL/App/Hodnoceni/KZH001_HodnVypisStud.aspx")
|
|
||||||
grades_to_file(password, username, grades)
|
|
||||||
else:
|
|
||||||
grades = grades_from_file(password, username)
|
|
||||||
else:
|
|
||||||
grades = grades_from_file(password, username)
|
|
||||||
|
|
||||||
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("--------")
|
|
||||||
print(" Známky ")
|
|
||||||
print("--------\n")
|
|
||||||
|
|
||||||
if grades == []:
|
|
||||||
print("N/A\n")
|
|
||||||
|
|
||||||
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(grades[i]["FINAL"], "|", end=" ")
|
|
||||||
print(grades[i]["AVG"], "|", end=" ")
|
|
||||||
print("".join([grades[i]["GRADES"][j]+" " for j in range(len(grades[i]["GRADES"]))]))
|
|
||||||
else:
|
|
||||||
if grades[i]["FINAL"] is not None:
|
|
||||||
whitespace = " " * (max_len_of_subject - len(grades[i]["SUBJECT"]))
|
|
||||||
print(grades[i]["SUBJECT"] + whitespace + "|", end=" ")
|
|
||||||
print(grades[i]["FINAL"], "|")
|
|
||||||
|
|
||||||
def grades_to_file(password, username, grades=None):
|
|
||||||
"""
|
|
||||||
Writes the grades to a local file
|
|
||||||
for later use and extraction.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if grades is None:
|
|
||||||
try:
|
|
||||||
grades = get_grades(password, username, "/SOL/App/Hodnoceni/KZH001_HodnVypisStud.aspx")
|
|
||||||
except Exception:
|
|
||||||
print("An error occured, you probably can't access the internet right now")
|
|
||||||
return
|
|
||||||
|
|
||||||
data = []
|
|
||||||
lstrdata = []
|
|
||||||
|
|
||||||
for i in range(len(grades)):
|
|
||||||
temp = {}
|
|
||||||
temp["SUBJECT"] = grades[i]["SUBJECT"]
|
|
||||||
temp["FINAL"] = grades[i]["FINAL"]
|
|
||||||
temp["AVG"] = grades[i]["AVG"]
|
|
||||||
temp_grades = []
|
|
||||||
for j in range(len(grades[i]["GRADES"])):
|
|
||||||
temp_grades.append(grades[i]["GRADES"][j])
|
|
||||||
temp["GRADES"] = temp_grades
|
|
||||||
data.append(temp)
|
|
||||||
|
|
||||||
for row in data:
|
|
||||||
lstrdata.append(row["SUBJECT"])
|
|
||||||
lstrdata.append(",")
|
|
||||||
lstrdata.append(row["FINAL"])
|
|
||||||
lstrdata.append(",")
|
|
||||||
lstrdata.append(row["AVG"])
|
|
||||||
lstrdata.append(",")
|
|
||||||
for i in row["GRADES"]:
|
|
||||||
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)}-grades")
|
|
||||||
|
|
||||||
def grades_from_file(password, username) -> list:
|
|
||||||
"""
|
|
||||||
Extracts the grades from the local
|
|
||||||
file and returns them in a better
|
|
||||||
format.
|
|
||||||
"""
|
|
||||||
import csv
|
|
||||||
from io import StringIO
|
|
||||||
try:
|
|
||||||
strdata = cr.read_from_file_and_decrypt(password, f"{os.environ['HOME']}/.local/lib/solendata/{nw.get_user_hash(username)}-grades")
|
|
||||||
except:
|
|
||||||
print("Could not read the file")
|
|
||||||
return
|
|
||||||
f = StringIO(strdata)
|
|
||||||
reader = csv.reader(f, delimiter=",")
|
|
||||||
grades = []
|
|
||||||
rows = []
|
|
||||||
for row in reader:
|
|
||||||
rows.append(row)
|
|
||||||
|
|
||||||
for row in range(len(rows)):
|
|
||||||
temp = {}
|
|
||||||
|
|
||||||
temp["SUBJECT"] = rows[row][0]
|
|
||||||
temp["FINAL"] = rows[row][1]
|
|
||||||
temp["AVG"] = rows[row][2]
|
|
||||||
|
|
||||||
temp_lst = []
|
|
||||||
for i in range(3, len(rows[row])):
|
|
||||||
temp_lst.append(rows[row][i])
|
|
||||||
temp["GRADES"] = temp_lst
|
|
||||||
|
|
||||||
grades.append(temp)
|
|
||||||
|
|
||||||
return grades
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
"""
|
|
||||||
Functions for network related stuff.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import requests
|
|
||||||
import hashlib
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
import os
|
|
||||||
|
|
||||||
not_login = 0
|
|
||||||
F_not_anymore = 0
|
|
||||||
session = requests.Session()
|
|
||||||
|
|
||||||
def _read_shadow() -> str:
|
|
||||||
"""
|
|
||||||
Reads the shadow file and returns it in
|
|
||||||
a suitable format for other functions.
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = ""
|
|
||||||
try:
|
|
||||||
with open(f"{os.environ['HOME']}/.local/lib/solendata/shadow", "r") as f:
|
|
||||||
for row in f:
|
|
||||||
result += row+";"
|
|
||||||
except FileNotFoundError:
|
|
||||||
os.system(f"touch {os.environ['HOME']}/.local/lib/solendata/shadow")
|
|
||||||
with open(f"{os.environ['HOME']}/.local/lib/solendata/shadow", "r") as f:
|
|
||||||
for row in f:
|
|
||||||
result += row+";"
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _save_creds(user: str, pwd: str):
|
|
||||||
"""
|
|
||||||
Saves credentials into the shadow file
|
|
||||||
by appending them.
|
|
||||||
"""
|
|
||||||
|
|
||||||
creds = ";" + _get_creds_hash(user, pwd)
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(f"{os.environ['HOME']}/.local/lib/solendata/shadow", "a+") as f:
|
|
||||||
if not creds in _read_shadow():
|
|
||||||
f.write(creds)
|
|
||||||
except FileNotFoundError:
|
|
||||||
os.system(f"touch {os.environ['HOME']}/.local/lib/solendata/shadow")
|
|
||||||
with open(f"{os.environ['HOME']}/.local/lib/solendata/shadow", "a+") as f:
|
|
||||||
if not creds in _read_shadow():
|
|
||||||
f.write(creds)
|
|
||||||
|
|
||||||
def _eval_creds(creds: str) -> bool:
|
|
||||||
"""
|
|
||||||
Evaluates the credentials for if
|
|
||||||
they are in the shadow file or not.
|
|
||||||
"""
|
|
||||||
|
|
||||||
shadow = _read_shadow()
|
|
||||||
|
|
||||||
if creds in shadow:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _get_creds_hash(user: str, pwd: str) -> str:
|
|
||||||
"""
|
|
||||||
Creates a sha512 hash from the username
|
|
||||||
and password.
|
|
||||||
"""
|
|
||||||
|
|
||||||
user_hash = hashlib.sha512(bytes(user, 'utf-8')).hexdigest()
|
|
||||||
pwd_hash = hashlib.sha512(bytes(pwd, 'utf-8')).hexdigest()
|
|
||||||
creds = user_hash+":"+pwd_hash
|
|
||||||
|
|
||||||
return creds
|
|
||||||
|
|
||||||
def get_user_hash(user: str) -> str:
|
|
||||||
return str(hashlib.sha512(bytes(user, 'utf-8')).hexdigest())
|
|
||||||
|
|
||||||
def login(user: str, pwd: str) -> bool:
|
|
||||||
"""
|
|
||||||
Tries to send a request to the SOL
|
|
||||||
servers in order to log in.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if is_connected():
|
|
||||||
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:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
if _eval_creds(_get_creds_hash(user, pwd)):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_connected() -> bool:
|
|
||||||
"""
|
|
||||||
Checks whether there is internet
|
|
||||||
access present.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import socket
|
|
||||||
|
|
||||||
try:
|
|
||||||
host = socket.gethostbyname("one.one.one.one")
|
|
||||||
s = socket.create_connection((host, 80), 2)
|
|
||||||
s.close()
|
|
||||||
return True
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_html_from(params=None) -> str:
|
|
||||||
"""
|
|
||||||
Fetches the HTML markup of
|
|
||||||
a specified subsite of SOL.
|
|
||||||
"""
|
|
||||||
|
|
||||||
base = "https://aplikace.skolaonline.cz"
|
|
||||||
|
|
||||||
if params is not None:
|
|
||||||
base += params
|
|
||||||
|
|
||||||
response = session.get(base)
|
|
||||||
if response.status_code == 200:
|
|
||||||
return response
|
|
||||||
else:
|
|
||||||
return ""
|
|
||||||
@@ -1,345 +0,0 @@
|
|||||||
"""
|
|
||||||
Functions related to today's
|
|
||||||
and tomorrow'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 exctracting
|
|
||||||
data from a local file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
global not_login
|
|
||||||
|
|
||||||
if not_login == 1:
|
|
||||||
not_login = 0
|
|
||||||
|
|
||||||
schedule = schedule_from_file(password, username)
|
|
||||||
return 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="ctl00_main_boxKalendar_ctl00_ctl04")
|
|
||||||
|
|
||||||
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_)):
|
|
||||||
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(" - ")
|
|
||||||
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)
|
|
||||||
|
|
||||||
return schedule
|
|
||||||
except AttributeError:
|
|
||||||
global not_login
|
|
||||||
|
|
||||||
not_login = 1
|
|
||||||
return fetch_locally(password, username)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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_tdy_tmr")
|
|
||||||
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/Spolecne/KZZ010_RychlyPrehled.aspx")
|
|
||||||
schedule_to_file(password, username, schedule)
|
|
||||||
else:
|
|
||||||
schedule = schedule_from_file(password, username)
|
|
||||||
else:
|
|
||||||
schedule = schedule_from_file(password, username)
|
|
||||||
|
|
||||||
print("")
|
|
||||||
|
|
||||||
print("--------------------------")
|
|
||||||
print(" Dnešní a zítřejší 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/Spolecne/KZZ010_RychlyPrehled.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"])
|
|
||||||
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_tdy_tmr")
|
|
||||||
|
|
||||||
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_tdy_tmr")
|
|
||||||
except:
|
|
||||||
print("Could not read the file")
|
|
||||||
return
|
|
||||||
f = StringIO(strdata)
|
|
||||||
reader = csv.reader(f, delimiter=",")
|
|
||||||
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)
|
|
||||||
|
|
||||||
return schedule
|
|
||||||
@@ -1,376 +0,0 @@
|
|||||||
"""
|
|
||||||
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
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
#!/bin/python3
|
|
||||||
|
|
||||||
from solenlib import grades as gr
|
|
||||||
from solenlib import networking as nw
|
|
||||||
from solenlib import schedule_week as sw
|
|
||||||
from solenlib import schedule_tdy_tmr as st
|
|
||||||
import sys
|
|
||||||
import getpass
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
parser = argparse.ArgumentParser(prog="solen", description="solen, an enhanced version of the ŠkolaOnLine online school system")
|
|
||||||
|
|
||||||
parser.add_argument("-t", "--today-tomorrow", action="store_true", help="show the schedule for today and tomorrow")
|
|
||||||
parser.add_argument("-w", "--week", action="store_true", help="show the schedule for this week")
|
|
||||||
parser.add_argument("-g", "--grades", action="store_true", help="show the grades")
|
|
||||||
parser.add_argument("-u", "--username", action="store", default="", help="provide the username for login")
|
|
||||||
parser.add_argument("-p", "--password", action="store", default="", help="provide the password for login")
|
|
||||||
parser.add_argument("-l", "--local", action="store_true", help="only fetch local files, don't connect to the internet")
|
|
||||||
parser.add_argument("-d", "--delete-local-files", action="store_true", help="delete all local user data, including schedules, grades and user credentials")
|
|
||||||
|
|
||||||
parser.add_argument("-b", "--backup", action="store_true", help="back up all user data and store them in a .tar.gz archive")
|
|
||||||
parser.add_argument("-R", "--backup-restore", action="store", nargs=1, metavar="PATH", help="specify the path to a .tar.gz archive that was previously created with Solen")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if args.delete_local_files:
|
|
||||||
try:
|
|
||||||
print("Removing all schedules and grades ...", end=" ")
|
|
||||||
os.system(f"rm -rf {os.environ['HOME']}/.local/lib/solendata/*")
|
|
||||||
print("done")
|
|
||||||
print("Removing all user credentials ...", end=" ")
|
|
||||||
os.system(f"rm -rf {os.environ['HOME']}/.local/lib/solendata/shadow")
|
|
||||||
print("done")
|
|
||||||
print("All user data removed successfully")
|
|
||||||
except:
|
|
||||||
print("Could not remove user data")
|
|
||||||
|
|
||||||
elif args.backup:
|
|
||||||
try:
|
|
||||||
nowtime = str(datetime.now().strftime("%Y-%m-%d_%H-%M-%S"))
|
|
||||||
try:
|
|
||||||
print("Creating the backup archive ...", end=" ")
|
|
||||||
os.system(f"tar cf solen-backup-{nowtime}.tar {os.getcwd()}")
|
|
||||||
print("done")
|
|
||||||
print("Compressing the archive ...", end=" ")
|
|
||||||
os.system(f"gzip {os.getcwd()}/solen-backup-{nowtime}.tar")
|
|
||||||
print("done")
|
|
||||||
print("Backup archive created successfully")
|
|
||||||
except:
|
|
||||||
print("The 'tar' utility or the 'gzip' utility is not installed")
|
|
||||||
except:
|
|
||||||
print("Could not backup user data")
|
|
||||||
elif args.backup_restore:
|
|
||||||
try:
|
|
||||||
backup_path = args.backup_restore
|
|
||||||
print("Preparing ...", end=" ")
|
|
||||||
os.system(f"mkdir {os.getcwd()}/.solentmp")
|
|
||||||
print("done")
|
|
||||||
print("Uncompressing the archive ...", end=" ")
|
|
||||||
os.system(f"gunzip {backup_path}")
|
|
||||||
print("done")
|
|
||||||
print("Unpacking the archive ...", end=" ")
|
|
||||||
os.system(f"tar xzjf {backup_path} {os.getcwd()}/.solentmp")
|
|
||||||
print("done")
|
|
||||||
print("Moving the files ...", end=" ")
|
|
||||||
os.system(f"mv {os.getcwd()}/.solentmp/* {os.environ['HOME']}/.local/lib/solendata")
|
|
||||||
print("done")
|
|
||||||
print("Cleaning up ...", end=" ")
|
|
||||||
os.system(f"rm -rf {os.getcwd()}/.solentmp")
|
|
||||||
print("done")
|
|
||||||
print("Backup restored successfully")
|
|
||||||
except:
|
|
||||||
print("Could not restore the backup")
|
|
||||||
else:
|
|
||||||
if args.username:
|
|
||||||
user = str(args.username)
|
|
||||||
else:
|
|
||||||
user = str(input("Zadejte přihlašovací jméno: "))
|
|
||||||
|
|
||||||
if args.password:
|
|
||||||
pwd = str(args.password)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
pwd = str(getpass.getpass("Zadejte heslo: "))
|
|
||||||
except:
|
|
||||||
pwd = str(input("Zadejte heslo: "))
|
|
||||||
|
|
||||||
if not nw.login(user, pwd):
|
|
||||||
print("Login unsuccessful")
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
if args.week:
|
|
||||||
if args.local:
|
|
||||||
sw.show_schedule(pwd, user, local=True)
|
|
||||||
else:
|
|
||||||
sw.show_schedule(pwd, user)
|
|
||||||
if args.today_tomorrow:
|
|
||||||
if args.local:
|
|
||||||
st.show_schedule(pwd, user, local=True)
|
|
||||||
else:
|
|
||||||
st.show_schedule(pwd, user)
|
|
||||||
if args.grades:
|
|
||||||
if args.local:
|
|
||||||
gr.show_grades(pwd, user, local=True)
|
|
||||||
else:
|
|
||||||
gr.show_grades(pwd, user)
|
|
||||||
|
|
||||||
if not args.grades and not args.today_tomorrow and not args.week:
|
|
||||||
if args.local:
|
|
||||||
sw.show_schedule(pwd, user, local=True)
|
|
||||||
st.show_schedule(pwd, user, local=True)
|
|
||||||
gr.show_grades(pwd, user, local=True)
|
|
||||||
else:
|
|
||||||
sw.show_schedule(pwd, user)
|
|
||||||
st.show_schedule(pwd, user)
|
|
||||||
gr.show_grades(pwd, user)
|
|
||||||
except:
|
|
||||||
print("Could not execute")
|
|
||||||
Reference in New Issue
Block a user