Commit c5892627 authored by Gabriel Dengler's avatar Gabriel Dengler
Browse files

Added support for multiple university courses

parent cb50f30d
......@@ -8,7 +8,7 @@ from log import print_info, print_warn
from urllib.parse import urlparse
from colorama import init as colorama_init, Fore, Style
from lxml.html import fromstring
from urllib.parse import unquote
from urllib.parse import unquote, urlencode
headers = {
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
......@@ -22,11 +22,8 @@ url_exams_page = 'https://www.campus.uni-erlangen.de/qisserver/rds?' \
'state=template&template=pruefungen'
AUTH_STATE_URL = 'https://www.campus.uni-erlangen.de/Shibboleth.sso/Login'
#AUTH_STATE_URL = 'https://www.studon.fau.de/studon/saml.php?target=ilias_app_oauth2'
OAUTH_URL = 'https://www.sso.uni-erlangen.de/simplesaml/module.php/core/loginuserpass.php?'
#SAML_URL = 'https://www.studon.fau.de/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp'
SAML_URL = 'https://www.campus.uni-erlangen.de/Shibboleth.sso/SAML2/POST'
#SAML_URL = 'https://www.campus.uni-erlangen.de/Shibboleth.sso/Login'
class Connection:
......@@ -60,9 +57,13 @@ class Connection:
def __exit__(self, type, value, traceback):
self._stack.__exit__(type, value, traceback)
def __get(self, url):
def __get(self, url, data=None):
print_info(f"get {urlparse(url).netloc}")
r = self.s.get(url, headers=headers, timeout=5)
if data is None:
r = self.s.get(url, headers=headers, timeout=10)
else:
payload_str = urlencode(data)
r = self.s.get(url, params=payload_str, headers=headers, timeout=10)
r.raise_for_status()
return r
......@@ -84,16 +85,10 @@ class Connection:
return False
r = self.__get(url_exams_page)
url_overview_page = find_overview_page_url(r.content)
if not url_overview_page:
return False
r = self.__get(url_overview_page)
self.url_exam_results = find_exam_results_url(r.content)
if self.url_exam_results:
return True
return self.url_exam_results is not None
else:
while True:
print_info(f'logging in as {self.username}')
......@@ -101,12 +96,6 @@ class Connection:
self.__post(url_login_form, self.form_data)
r = self.__get(url_exams_page)
url_overview_page = find_overview_page_url(r.content)
if not url_overview_page:
return False
r = self.__get(url_overview_page)
self.url_exam_results = find_exam_results_url(r.content)
if self.url_exam_results:
......@@ -142,7 +131,7 @@ class Connection:
saml_rq = self.s.post(SAML_URL, data=payload)
return True
def __get_grades_page(self):
def __get_grades_overview_page(self):
while True:
try:
return self.__get(self.url_exam_results).content
......@@ -155,12 +144,26 @@ class Connection:
print_warn(e)
time.sleep(1)
def get_grades(self):
def __get_course_page(self, base_url, node_id, payload):
while True:
try:
return self.__get(base_url,
data={'nodeID': node_id, **payload}).content
except Exception as e:
print(e)
print_warn('connection lost, reconnecting:')
try:
while not self.__connect():
pass
except Exception as e:
print_warn(e)
time.sleep(1)
def __get_grades_for_course(self, course_html):
rows = None
while not rows:
try:
grades_html = self.__get_grades_page()
rows = BeautifulSoup(grades_html, 'html5lib') \
rows = BeautifulSoup(course_html, 'html5lib') \
.find('table', attrs={'id': 'notenspiegel'}) \
.find('tbody').find_all('tr')
except Exception as e:
......@@ -187,7 +190,36 @@ class Connection:
return modules
def find_overview_page_url(page):
def get_grades(self):
# Case 1: No overview page, overview page is results page
overview_page = self.__get_grades_overview_page()
if 'selectStg' not in str(overview_page):
return self.__get_grades_for_course(overview_page)
# Case 2: Multiple pages
base_url = BeautifulSoup(overview_page, 'html5lib') \
.find('form', attrs={'id': 'selectStg'}) \
.get('action')
courses = [ele.get('value') for ele in \
BeautifulSoup(overview_page, 'html5lib') \
.find('form', attrs={'id': 'selectStg'}) \
.findAll('input', attrs={'name': 'nodeID'})]
payload = {ele.get('name'): ele.get('value') for ele in \
BeautifulSoup(overview_page, 'html5lib') \
.find('form', attrs={'id': 'selectStg'}) \
.findAll('input', attrs={'type': 'hidden'})}
modules = []
for course in courses:
course_html = self.__get_course_page(base_url, course, payload)
modules += self.__get_grades_for_course(course_html)
return modules
def find_exam_results_url(page):
try:
return BeautifulSoup(page, 'html5lib') \
.find('a', attrs={'id': 'notenspiegelStudent'}) \
......@@ -197,12 +229,6 @@ def find_overview_page_url(page):
return None
def find_exam_results_url(page):
return BeautifulSoup(page, 'html5lib') \
.find('meta', attrs={'http-equiv': 'refresh'}) \
.get('content')[6:]
if __name__ == '__main__':
with Connection() as c:
grades = c.get_grades()
......
......@@ -333,7 +333,7 @@ def cc_on_request(args):
global request_queue
if len(args) > 2:
print("$> Usage: request [process]")
print("$> Usage: requests [process]")
return
request_lock.acquire()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment