Skip to content

Instantly share code, notes, and snippets.

@bm371613
Last active January 27, 2016 17:51
Show Gist options
  • Save bm371613/930066fd2b5ec91bb6bb to your computer and use it in GitHub Desktop.
Save bm371613/930066fd2b5ec91bb6bb to your computer and use it in GitHub Desktop.
import email.mime.text
import json
import os
import smtplib
import sys
import urllib.parse
import bs4
import requests
URL = "https://logowanie.aps.edu.pl/cas/login?service=https://usosweb.aps.edu.pl/kontroler.php?_action=dla_stud/studia/oceny/index&locale=pl"
USERNAME = os.environ.get("USERNAME")
PASSWORD = os.environ.get("PASSWORD")
DATA_FILE = "data.json"
EMAIL = os.environ.get("EMAIL")
def usage():
print("""
Usage:
%s <cmd>
Available commands:
print download and print grades
init download and save grades
check download grades, compare with saved, email about changes, save
""" % sys.argv[0])
sys.exit(1)
def fetch_grades_page():
s = requests.Session()
login_page = bs4.BeautifulSoup(s.get(URL).content, 'html.parser')
login_form = login_page.form
form_data = {i["name"]: i["value"] for i in login_form.find_all('input')}
form_data["username"] = USERNAME
form_data["password"] = PASSWORD
grades_response = s.request(
login_form['method'],
urllib.parse.urljoin(URL, login_form['action']),
data=form_data,
)
return bs4.BeautifulSoup(grades_response.content, 'html.parser')
def parse_grades(grades_page):
result = []
tbodys = grades_page.find_all('tbody')
for header_tbody, group_tbody in zip(tbodys[::2], tbodys[1::2]):
group_name = header_tbody.text.split("-")[0].strip()
for grade_tr in group_tbody.find_all('tr'):
name = grade_tr.a.text
grade = " ".join(
s.text for s in grade_tr.find_all('td')[2].find_all('span')
)
result.append((group_name, name, grade))
return result
def extract_changed(old_grades, grades):
old_dict = {
(g[0], g[1]): g[2]
for g in old_grades
}
return list(filter(lambda g: old_dict.get((g[0], g[1])) != g[2], grades))
def notify(changed_grades):
content = "Changed grades:\n\n" + "\n".join(
g[1] + ": " + g[2] for g in changed_grades
)
print("SENDING NOTIFICATION")
print(content)
msg = email.mime.text.MIMEText(content, "plain", "utf-8")
msg['Subject'] = "Your grades have changed!"
msg['From'] = "usos_grades_check"
msg['To'] = EMAIL
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()
def print_():
grades = parse_grades(fetch_grades_page())
print(json.dumps(grades, indent=4))
def init():
grades = parse_grades(fetch_grades_page())
with open(DATA_FILE, 'w') as f:
json.dump(grades, f, indent=4)
def check():
with open(DATA_FILE) as f:
old_grades = json.load(f)
grades = parse_grades(fetch_grades_page())
if not grades:
print("FAILED TO FETCH GRADES")
sys.exit(2)
changed = extract_changed(old_grades, grades)
if changed:
notify(changed)
with open(DATA_FILE, 'w') as f:
json.dump(grades, f, indent=4)
if __name__ == '__main__':
if len(sys.argv) < 2:
usage()
cmd = sys.argv[1]
if cmd == "print":
print_()
elif cmd == "init":
init()
elif cmd == "check":
check()
else:
usage()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment