Mon Jun 12 06:03:14 CEST 2023

This commit is contained in:
mnjx
2023-06-12 06:21:02 +02:00
parent f7c2b541b5
commit 783a37186e
16 changed files with 250 additions and 152 deletions
+8
View File
@@ -0,0 +1,8 @@
#!/bin/bash
if command -v solen > /dev/null
then
solen
else
python3 "./src/main.py"
fi
+9
View File
@@ -0,0 +1,9 @@
#!/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
Regular → Executable
+3
View File
@@ -1 +1,4 @@
*.pyc
src/lib/shadow
src/lib/data/*.csv
TODO.md
Regular → Executable
View File
Regular → Executable
+13 -2
View File
@@ -1,5 +1,16 @@
SHELL=/bin/bash
install:
pip install -r requirements.txt
python3 -m pip install -r requirements.txt
./.config/mkdirs.sh
cp ./src/main.py /bin/solen
chmod 774 /bin/solen
cp ./src/lib/*.py $(HOME)/.local/lib/python3.11/site-packages/solenlib
cp ./src/lib/shadow $(HOME)/.local/lib/solendata
cp ./src/lib/data/*.csv $(HOME)/.local/lib/solendata
run:
python3 "src/main.py"
./.config/launch.sh
Regular → Executable
+19 -8
View File
@@ -15,20 +15,31 @@ Insiration was taken from [@JakubAndrysek](https://github.com/JakubAndrysek)'s [
+ Shows all grades and their arithmetic average (not accounting for weight)
+ Works offline (when the internet has been accessed at least once before)
# Usage
# Installation
Clone the repo
**Clone the repo**
`git clone git@github.com:mnjx/sol-enhanced.git`
`git clone https://github.com/mnjx/sol-enhanced.git`
Navigate into the repo directory
**Navigate into the repo directory**
`cd sol-enhanced`
Install the requirements (required to run only once)
**Install** *(superuser privileges required)*
`make install`
`sudo make install`
Run the program
**Run the program**
`make run`
From the repo folder: `make run`
From anywhere on the computer: `solen`
# Usage
Upon startup, the user os prompted to enter their ŠkolaOnLine credentials.
If the login proccess is successfull, the preconfigured functions in `/bin/solen`
will execute. By default, the functions are: showing the schedule for this week,
showing the schedule for today and tomorrow and showing the grades. You can edit
that file if you want to change what is being displayed. Alternatively, you can
edit the `src/main.py` and then do the install step (`sudo make install`).
An option for command-line arguments will be added in the future.
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+14 -1
View File
@@ -1 +1,14 @@
Chování
AJ (Anglický jazyk),1,2,1
B (Biologie),1
ČJ (Český jazyk a literatura),1,2,1
D (Dějepis),1,1,2,3,2
F (Fyzika),1,3,1,2
Hv (Hudební výchova),1
Ch (Chemie),2,1,1
Inf (Informatika),1,1,1,1
M (Matematika),4,2,1,1,3,2,1
NJ (Německý jazyk),1,1,1,1,1,2,1,1
Tv (Tělesná výchova),1,1,1,1
Z (Zeměpis),2,2,1,2,1,2,1
Zsv (Základy společenských věd),1,1,1
1 Chování
2 AJ (Anglický jazyk),1,2,1
3 B (Biologie),1
4 ČJ (Český jazyk a literatura),1,2,1
5 D (Dějepis),1,1,2,3,2
6 F (Fyzika),1,3,1,2
7 Hv (Hudební výchova),1
8 Ch (Chemie),2,1,1
9 Inf (Informatika),1,1,1,1
10 M (Matematika),4,2,1,1,3,2,1
11 NJ (Německý jazyk),1,1,1,1,1,2,1,1
12 Tv (Tělesná výchova),1,1,1,1
13 Z (Zeměpis),2,2,1,2,1,2,1
14 Zsv (Základy společenských věd),1,1,1
+4 -1
View File
@@ -1 +1,4 @@
Po,Z,ČJ,D,M,Volno,Ch,B,F
15.5.,103-3G,103-3G,207-Dě,103-3G, - ,211-Bi,211-Bi, -
Út,Volno,AJ,M,M,NJ
16.5., - ,103-3G,205-Ma,205-Ma,103-3G
1 Po,Z,ČJ,D,M,Volno,Ch,B,F
2 15.5.,103-3G,103-3G,207-Dě,103-3G, - ,211-Bi,211-Bi, -
3 Út,Volno,AJ,M,M,NJ
4 16.5., - ,103-3G,205-Ma,205-Ma,103-3G
Regular → Executable
+10 -1
View File
@@ -1 +1,10 @@
Po,Volno,ČJ,D,ČJ,Volno,Ch
5.6., - ,103-3G,207-Dě,103-3G, - ,309-Ch
Út,ČJ,ČJ,Zsv,ČJ,Volno,NJ,AJ
6.6.,312-Fy,103-3G,103-3G,201-ČJL, - ,301-1A,305-CJ1
St,ČJ,AJ,Zsv,Zsv,M,NJ
7.6.,103-3G,305-CJ1,201-ČJL,201-ČJL,301-1A,204-CJ2
Čt,D,Zsv,Hv,Hv,Ch,ČJ
8.6.,103-3G,206-Ze,209-HV,209-HV,309-Ch,309-Ch
,Zsv,AJ,D,NJ
9.6.,103-3G,101-1G,103-3G,103-3G
1 Po,Volno,ČJ,D,ČJ,Volno,Ch
2 5.6., - ,103-3G,207-Dě,103-3G, - ,309-Ch
3 Út,ČJ,ČJ,Zsv,ČJ,Volno,NJ,AJ
4 6.6.,312-Fy,103-3G,103-3G,201-ČJL, - ,301-1A,305-CJ1
5 St,ČJ,AJ,Zsv,Zsv,M,NJ
6 7.6.,103-3G,305-CJ1,201-ČJL,201-ČJL,301-1A,204-CJ2
7 Čt,D,Zsv,Hv,Hv,Ch,ČJ
8 8.6.,103-3G,206-Ze,209-HV,209-HV,309-Ch,309-Ch
9 Pá,Zsv,AJ,D,NJ
10 9.6.,103-3G,101-1G,103-3G,103-3G
Regular → Executable
+7 -6
View File
@@ -1,5 +1,6 @@
from lib import networking as nw
from solenlib import networking as nw
from bs4 import BeautifulSoup
import os
not_login = 0
@@ -88,8 +89,8 @@ def show_grades():
print("N/A\n")
import os
if os.path.exists("src/lib/data/grades.csv"):
os.remove("src/lib/data/grades.csv")
if os.path.exists(f"{os.environ['HOME']}/.local/lib/solendata/grades.csv"):
os.remove(f"{os.environ['HOME']}/.local/lib/solendata/grades.csv")
return
for i in range(len(grades)):
@@ -111,7 +112,7 @@ def grades_to_file(grades=None): # !!! make sure the format of the grades list i
data = []
with open("src/lib/data/grades.csv", mode="w", newline="") as f:
with open(f"{os.environ['HOME']}/.local/lib/solendata/grades.csv", mode="w", newline="") as f:
for i in range(len(grades)):
temp = {}
temp["SUBJECT"] = grades[i]["SUBJECT"]
@@ -134,7 +135,7 @@ def grades_from_file() -> list:
grades = []
try:
with open("src/lib/data/grades.csv", mode="r") as f:
with open(f"{os.environ['HOME']}/.local/lib/solendata/grades.csv", mode="r") as f:
reader = csv.reader(f)
rows = []
for row in reader:
@@ -154,4 +155,4 @@ def grades_from_file() -> list:
except FileNotFoundError:
print("No grades.csv file found\n")
return grades
return grades
Regular → Executable
+87 -48
View File
@@ -1,63 +1,102 @@
import requests
import hashlib
from bs4 import BeautifulSoup
import os
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": ""
}
def _read_shadow() -> str:
result = ""
with open(f"{os.environ['HOME']}/.local/lib/solendata/shadow", "r") as f:
for row in f:
result += row+";"
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
return result
def _save_creds(user: str, pwd: str):
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:
print("No shadow file found")
def _eval_creds(creds: str) -> bool:
shadow = _read_shadow()
if creds in shadow:
return True
else:
return False
def _get_creds_hash(user: str, pwd: str) -> str:
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 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")
if _eval_creds(_get_creds_hash(user, pwd)):
return True
else:
return False
def is_connected() -> bool:
import socket
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
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"
base = "https://aplikace.skolaonline.cz"
if params is not None:
base += params
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 ""
response = session.get(base)
if response.status_code == 200:
#print("Download successful")
return response
else:
print("Download unsuccessful")
return ""
Regular → Executable
+24 -23
View File
@@ -1,5 +1,6 @@
from lib import networking as nw
from solenlib import networking as nw
from bs4 import BeautifulSoup
import os
not_login = 0
@@ -10,10 +11,10 @@ def fetch_locally() -> list:
not_login = 0
#print("Could not sign in (you may have entered invalid login credentials)")
#print("Fetching the schedule for this week locally\n")
schedule_tdy_tmr = schedule_tdy_tmr_from_file()
return schedule_tdy_tmr
schedule = schedule_from_file()
return schedule
def get_schedule_tdy_tmr(url: str):
def get_schedule(url: str):
try:
html = nw.get_html_from(url)
@@ -25,7 +26,7 @@ def get_schedule_tdy_tmr(url: str):
rows_even = table.find_all("tr", class_="RowEven")
rows = rows_odd + rows_even
schedule_tdy_tmr = []
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:
@@ -105,16 +106,16 @@ def get_schedule_tdy_tmr(url: str):
break
if F_continue == False:
schedule_tdy_tmr_row = {
schedule_row = {
"DAY": day,
"DATE": date,
"SUBJECTS": subjects,
"WHERES": wheres
}
schedule_tdy_tmr.append(schedule_tdy_tmr_row)
schedule.append(schedule_row)
return schedule_tdy_tmr
return schedule
except AttributeError:
global not_login
@@ -122,12 +123,12 @@ def get_schedule_tdy_tmr(url: str):
schedule = fetch_locally()
return schedule
def schedule_tdy_tmr_from_file_to_list():
def schedule_from_file_to_list():
schedule = []
schedule_ = []
try:
with open("src/lib/data/schedule_tdy_tmr.csv") as f:
with open(f"{os.environ['HOME']}/.local/lib/solendata/schedule_tdy_tmr.csv") as f:
import csv
reader = csv.reader(f)
for row in reader:
@@ -160,7 +161,7 @@ def schedule_tdy_tmr_from_file_to_list():
return schedule
def get_whitespace(key: str, idx=0) -> int:
schedule = schedule_tdy_tmr_from_file_to_list()
schedule = schedule_from_file_to_list()
max_len = 0
if key == "DATE":
@@ -176,27 +177,27 @@ def get_whitespace(key: str, idx=0) -> int:
return max_len
def show_schedule_tdy_tmr():
def show_schedule():
# 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_tdy_tmr("/SOL/App/Spolecne/KZZ010_RychlyPrehled.aspx")
schedule_tdy_tmr_to_file(schedule)
schedule = get_schedule("/SOL/App/Spolecne/KZZ010_RychlyPrehled.aspx")
schedule_to_file(schedule)
else:
schedule = schedule_tdy_tmr_from_file()
schedule = schedule_from_file()
print("")
print("--------------------------")
print(" Dnesni a zitrejsi rozvrh ")
print(" Dnešní a zítřejší rozvrh ")
print("--------------------------\n")
if schedule == []:
print("N/A\n")
import os
if os.path.exists("src/lib/data/schedule_tdy_tmr.csv"):
os.remove("src/lib/data/schedule_tdy_tmr.csv")
if os.path.exists(f"{os.environ['HOME']}/.local/lib/solendata/schedule_tdy_tmr.csv"):
os.remove(f"{os.environ['HOME']}/.local/lib/solendata/schedule_tdy_tmr.csv")
return
for i in range(len(schedule)):
@@ -223,16 +224,16 @@ def show_schedule_tdy_tmr():
print("")
def schedule_tdy_tmr_to_file(schedule=None):
def schedule_to_file(schedule=None):
import csv
if schedule is None:
try:
schedule = get_schedule_tdy_tmr("/SOL/App/Spolecne/KZZ010_RychlyPrehled.aspx")
schedule = get_schedule("/SOL/App/Spolecne/KZZ010_RychlyPrehled.aspx")
except Exception:
print("An error occured, you probably can't access the internet right now")
return
with open("src/lib/data/schedule_tdy_tmr.csv", mode="w", newline="") as f:
with open(f"{os.environ['HOME']}/.local/lib/solendata/schedule_tdy_tmr.csv", mode="w", newline="") as f:
data = []
for i in range(len(schedule)):
@@ -264,12 +265,12 @@ def schedule_tdy_tmr_to_file(schedule=None):
for row in data:
writer.writerow(row)
def schedule_tdy_tmr_from_file() -> list:
def schedule_from_file() -> list:
import csv
schedule = []
try:
with open("src/lib/data/schedule_tdy_tmr.csv", mode="r") as f:
with open(f"{os.environ['HOME']}/.local/lib/solendata/schedule_tdy_tmr.csv", mode="r") as f:
reader = csv.reader(f)
rows = []
for row in reader:
Regular → Executable
+38 -37
View File
@@ -1,5 +1,6 @@
from lib import networking as nw
from solenlib import networking as nw
from bs4 import BeautifulSoup
import os
not_login = 0
@@ -10,28 +11,28 @@ def fetch_locally() -> list:
not_login = 0
#print("Could not sign in (you may have entered invalid login credentials)")
#print("Fetching the schedule for this week locally\n")
schedule_week = schedule_week_from_file()
return schedule_week
schedule = schedule_from_file()
return schedule
def sort_schedule_week(schedule_week: list[dict]) -> list[dict]:
sorted_schedule_week: list[dict] = [{}, {}, {}, {}, {}]
def sort_schedule(schedule: list[dict]) -> list[dict]:
sorted_schedule: 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"] == "":
sorted_schedule_week[4] = schedule_week[i]
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"] == "":
sorted_schedule[4] = schedule[i]
return sorted_schedule_week
return sorted_schedule
def get_schedule_week(url: str):
def get_schedule(url: str):
try:
html = nw.get_html_from(url)
@@ -43,7 +44,7 @@ def get_schedule_week(url: str):
rows_even = table.find_all("tr", class_="RowEven")
rows = rows_odd + rows_even
schedule_week = []
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:
@@ -126,18 +127,18 @@ def get_schedule_week(url: str):
break
if F_continue == False:
schedule_week_row = {
schedule_row = {
"DAY": day,
"DATE": date,
"SUBJECTS": subjects,
"WHERES": wheres
}
schedule_week.append(schedule_week_row)
schedule.append(schedule_row)
sorted_schedule_week = sort_schedule_week(schedule_week)
sorted_schedule = sort_schedule(schedule)
return sorted_schedule_week
return sorted_schedule
except AttributeError:
global not_login
@@ -145,12 +146,12 @@ def get_schedule_week(url: str):
schedule = fetch_locally()
return schedule
def schedule_week_from_file_to_list():
def schedule_from_file_to_list():
schedule = []
schedule_ = []
try:
with open("src/lib/data/schedule_week.csv") as f:
with open(f"{os.environ['HOME']}/.local/lib/solendata/schedule_week.csv") as f:
import csv
reader = csv.reader(f)
for row in reader:
@@ -183,7 +184,7 @@ def schedule_week_from_file_to_list():
return schedule
def get_whitespace(key: str, idx=0) -> int:
schedule = schedule_week_from_file_to_list()
schedule = schedule_from_file_to_list()
max_len = 0
if key == "DATE":
@@ -199,14 +200,14 @@ def get_whitespace(key: str, idx=0) -> int:
return max_len
def show_schedule_week():
def show_schedule():
# 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)
schedule = get_schedule("/SOL/App/Kalendar/KZK001_KalendarTyden.aspx")
schedule_to_file(schedule)
else:
schedule = schedule_week_from_file()
schedule = schedule_from_file()
print("")
@@ -218,8 +219,8 @@ def show_schedule_week():
print("N/A\n")
import os
if os.path.exists("src/lib/data/schedule_week.csv"):
os.remove("src/lib/data/schedule_week.csv")
if os.path.exists(f"{os.environ['HOME']}/.local/lib/solendata/schedule_week.csv"):
os.remove(f"{os.environ['HOME']}/.local/lib/solendata/schedule_week.csv")
return
for i in range(len(schedule)):
@@ -246,16 +247,16 @@ def show_schedule_week():
print("")
def schedule_week_to_file(schedule=None):
def schedule_to_file(schedule=None):
import csv
if schedule is None:
try:
schedule = get_schedule_week("/SOL/App/Kalendar/KZK001_KalendarTyden.aspx")
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("src/lib/data/schedule_week.csv", mode="w", newline="") as f:
with open(f"{os.environ['HOME']}/.local/lib/solendata/schedule_week.csv", mode="w", newline="") as f:
data = []
for i in range(len(schedule)):
@@ -287,12 +288,12 @@ def schedule_week_to_file(schedule=None):
for row in data:
writer.writerow(row)
def schedule_week_from_file() -> list:
def schedule_from_file() -> list:
import csv
schedule = []
try:
with open("src/lib/data/schedule_week.csv", mode="r") as f:
with open(f"{os.environ['HOME']}/.local/lib/solendata/schedule_week.csv", mode="r") as f:
reader = csv.reader(f)
rows = []
for row in reader:
Regular → Executable
+14 -25
View File
@@ -1,30 +1,19 @@
from lib import grades as gr
from lib import networking as nw
from lib import schedule_week as sw
from lib import schedule_tdy_tmr as st
#!/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
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.schedule_week_to_file()
#sw.schedule_week_from_file()
sw.show_schedule_week()
#gr.get_grades("/SOL/App/Hodnoceni/KZH001_HodnVypisStud.aspx")
#gr.grades_to_file()
#gr.grades_from_file()
gr.show_grades()
#st.get_schedule("/SOL/App/Spolecne/KZZ010_RychlyPrehled.aspx")
#st.schedule_tdy_tmr_to_file()
#st.schedule_tdy_tmr_from_file()
st.show_schedule_tdy_tmr()
if not nw.login(user, pwd):
print("LOGIN UNSUCCESSFULL")
sys.exit(1)
else:
sw.show_schedule()
st.show_schedule()
gr.show_grades()