RAPLA-POC, LOGIN-Flow

This commit is contained in:
2023-11-29 11:10:01 +01:00
parent b07b25cf47
commit c373fa1428
10 changed files with 356 additions and 36 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ set/
VIRTUAL_ENV/
calendars/
.idea/
calendars/list.json

66
app.py
View File

@ -5,12 +5,13 @@ from flask_login import login_user, login_required, current_user, LoginManager,
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
import hashlib
import time
import dualisauth
import requesthelpers
from fetchRAPLA import *
from get_mysql import get_mysql
import time
from parseICAL import getWeek
def create():
@ -55,23 +56,42 @@ class Dualis(db.Model):
@app.route("/")
def index():
return render_template('index.html', headermessage='Header', message='DualHub')
return redirect(url_for("login"))
@app.route("/welcome")
@login_required
def welcome():
d = Dualis.query.filter_by(uid=current_user.id).first()
if not current_user.kurs:
kurs = dualisauth.getKurs(d.token, d.cookie)
current_user.kurs = kurs
db.session.commit()
else:
kurs = current_user.kurs
name = current_user.name
return render_template('index.html', headermessage='DualHub', message="Hallo, "
+ name + " (" + kurs + ")")
@app.route("/backendpoc/set-up")
@login_required
def getKurs():
d = Dualis.query.filter_by(uid=current_user.id).first()
if d:
e = False
if not current_user.kurs:
kurs = dualisauth.getKurs(d.token, d.cookie)
if kurs != 0:
current_user.kurs = kurs
db.session.commit()
else:
e = True
else:
kurs = current_user.kurs
current_user.kurs = kurs
db.session.commit()
else:
e = True
kurs = ""
return render_template('kurs.html', detected=(kurs, e))
@app.route("/backendpoc/error<int:ecode>")
def error(ecode):
if ecode == 900:
@ -91,7 +111,7 @@ def chooseRaplas():
@login_required
@app.route("/backendpoc/plan", methods=["POST"])
@app.route("/backendpoc/rapla", methods=["POST"])
def getRapla():
file = str(request.form.get("file"))
url = str(request.form.get("url"))
@ -100,16 +120,25 @@ def getRapla():
if file != "None":
User.query.filter_by(id=current_user.id).first().kurs = file[5:-5]
db.session.commit()
return send_file("calendars/" + file)
#return send_file("calendars/" + file)
elif url != "None":
file = getNewRapla(url)
if type(file) is not int:
User.query.filter_by(id=current_user.id).first().kurs = file[5:-5]
db.session.commit()
return send_file("calendars/" + file)
#return send_file("calendars/" + file)
else:
return redirect(url_for("error", ecode=file + 900))
return render_template("index.html")
return redirect(url_for("welcome"))
@login_required
@app.route("/backendpoc/plan", methods=["GET"])
def displayRapla():
samstag = request.args.get("samstag")
if not samstag:
samstag = False
events = getWeek("today", "rapla"+current_user.kurs+".ical", samstag)
return render_template("plan.html", events=events[0], eventdays=events[1])
@app.route("/backendpoc/log-in")
@ -127,21 +156,19 @@ def login_post():
if n:
success = redirect(n)
else:
success = redirect(url_for("welcome"))
success = redirect(url_for("getKurs"))
user = User.query.filter_by(email=email).first()
if user:
dualis = Dualis.query.filter_by(uid=user.id).first()
if check_password_hash(user.password, password):
if not dualisauth.checkLifetime(dualis.token_created):
if not dualis.token or not dualisauth.checkLifetime(dualis.token_created):
new_token = dualisauth.checkUser(email, password)
dualis.token = new_token[0]
dualis.cookie = requesthelpers.getCookie(new_token[1].cookies)
dualis.token_created = time.time()
db.session.commit()
login_user(user)
return success
else:
t = dualisauth.checkUser(email, password)
if t[0] == -2:
@ -153,6 +180,8 @@ def login_post():
dualis.token_created = time.time()
db.session.commit()
login_user(user)
if user.kurs:
success = redirect(url_for("welcome"))
return success
t = dualisauth.checkUser(email, password)
@ -180,6 +209,11 @@ def login_post():
@app.route("/backendpoc/log-out")
def logout():
dualis = Dualis.query.filter_by(uid=current_user.id).first()
dualisauth.logOut(dualis.token, dualis.cookie)
dualis.cookie = None
dualis.token = None
db.session.commit()
logout_user()
return redirect(url_for("login", code=1))

View File

@ -29,22 +29,33 @@ def checkUser(email: str, password: str):
return token, s
def getKurs(token: str, cookie: int):
headers["Cookie"] = "cnsc=" + str(cookie)
def getKurs(token: int, cookie: str):
try:
headers["Cookie"] = "cnsc=" + cookie
token = str(token)
response = requests.request("GET",
url + "?APPNAME=CampusNet&PRGNAME=COURSERESULTS&ARGUMENTS=-N" + token + ",-N000307,",
headers=headers, data={})
html = BeautifulSoup(response.text, 'lxml')
link = html.body.find('a', attrs={'id': "Popup_details0001"})['href']
response = requests.request("GET", url+link[21:], headers=headers, data={})
response = requests.request("GET", url + link[21:], headers=headers, data={})
html = BeautifulSoup(response.text, 'lxml')
content = html.body.find('td', attrs={'class': 'level02'}).text
start = content.find(" ")+4
start = content.find(" ") + 4
end = start + (content[start:].find(" "))
kurs = content[start:end]
except:
kurs = 0
return kurs
def logOut(token: int, cookie: str):
headers["Cookie"] = "cnsc=" + cookie
response = requests.request("GET", url + "?APPNAME=CampusNet&PRGNAME=LOGOUT&ARGUMENTS=-N" + str(token) + ", -N001",
headers=headers, data={})
def checkLifetime(timecode: float):
if time.time() - timecode > 1800:
return False

View File

@ -2,6 +2,7 @@ import urllib.error
from urllib.request import urlretrieve
import icalendar
import json
import recurring_ical_events
def parseURL(url: str):
@ -37,9 +38,6 @@ def getNewRapla(url: str):
except urllib.error.URLError:
return -1
with open("calendars/rapla" + kurs + ".ical") as f:
calendar = icalendar.Calendar.from_ical(f.read())
# events = calendar.walk("VEVENT")
file = open("calendars/list.json", "r+")
jsoncal = json.load(file)
jsoncal.update({kurs: "rapla" + kurs + ".ical"})

62
parseICAL.py Normal file
View File

@ -0,0 +1,62 @@
import icalendar
import datetime
import recurring_ical_events
def getWeek(weekstart: datetime, file: str, showsat: bool):
if weekstart == "today":
start_date = datetime.date.today()
else:
start_date = weekstart
start_date -= datetime.timedelta(days=start_date.weekday() % 7)
end_date = start_date + datetime.timedelta(days=7)
with open("calendars/" + file) as f:
calendar = icalendar.Calendar.from_ical(f.read())
events = recurring_ical_events.of(calendar).between(start_date, end_date)
eventl = []
for event in events:
estart = event["DTSTART"].dt
formstart = str(estart.hour) + ":" + str(estart.minute)
eend = event["DTEND"].dt
formend = str(eend.hour) + ":" + str(eend.minute)
forml = [formstart, formend]
for i in range(2):
if len(forml[i]) != 5:
if forml[i][-2] == ":":
forml[i] = forml[i] + "0"
if forml[i][1] == ":":
forml[i] = "0" + forml[i]
formstart = forml[0]
formend = forml[1]
eventdict = {
"start": formstart,
"end": formend,
"dur": str(event["DTEND"].dt - event["DTSTART"].dt)[:-3],
"name": event["SUMMARY"],
"room": event["LOCATION"],
"weekday": estart.weekday(),
"day": estart.day
}
eventl += [eventdict]
return eventl, daylist(start_date, showsat)
shortnames = ["mon", "tue", "wed", "thu", "fri", "sat"]
longnames = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"]
def daylist(weekstart: datetime, showsat: bool):
weekday = weekstart
dayl = []
if showsat:
r = 6
else:
r = 5
for i in range(r):
dayl += [{
"day": weekday.day,
"short": shortnames[i],
"long": longnames[i],
}]
weekday += datetime.timedelta(days=1)
return dayl

8
requirements.txt Normal file
View File

@ -0,0 +1,8 @@
beautifulsoup4==4.10.0
Flask==3.0.0
Flask_Login==0.6.3
flask_sqlalchemy==3.1.1
icalendar==5.0.11
recurring_ical_events==2.1.1
Requests==2.31.0
Werkzeug==3.0.1

133
static/cal.scss Normal file
View File

@ -0,0 +1,133 @@
:root {
--numDays: 5;
--numHours: 10;
--timeHeight: 60px;
--calBgColor: #fff1f8;
--eventBorderColor: #f2d3d8;
--eventColor1: #ffd6d1;
--eventColor2: #fafaa3;
--eventColor3: #e2f8ff;
--eventColor4: #d1ffe6;
}
.calendar {
display: grid;
gap: 10px;
grid-template-columns: auto 1fr;
margin: 2rem;
}
.timeline {
display: grid;
grid-template-rows: repeat(var(--numHours), var(--timeHeight));
}
.days {
display: grid;
grid-column: 2;
gap: 5px;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.events {
display: grid;
grid-template-rows: repeat(var(--numHours), var(--timeHeight));
border-radius: 5px;
background: var(--calBgColor);
}
// Place on Timeline
.start-1000 {
grid-row-start: 2;
}
.start-1200 {
grid-row-start: 4;
}
.start-1300 {
grid-row-start: 5;
}
.start-1400 {
grid-row-start: 6;
}
.end-1200 {
grid-row-end: 4;
}
.end-1300 {
grid-row-end: 5;
}
.end-1500 {
grid-row-end: 7;
}
.end-1600 {
grid-row-end: 8;
}
.end-1700 {
grid-row-end: 9;
}
// Events
.title {
font-weight: 600;
margin-bottom: 0.25rem;
}
.event {
border: 1px solid var(--eventBorderColor);
border-radius: 5px;
padding: 0.5rem;
margin: 0 0.5rem;
background: white;
}
.space,
.date {
height: 60px
}
// Global / Etc
body {
font-family: system-ui, sans-serif;
}
.corp-fi {
background: var(--eventColor1);
}
.ent-law {
background: var(--eventColor2);
}
.writing {
background: var(--eventColor3);
}
.securities {
background: var(--eventColor4);
}
.date {
display: flex;
gap: 1em;
}
.date-num {
font-size: 3rem;
font-weight: 600;
display: inline;
}
.date-day {
display: inline;
font-size: 3rem;
font-weight: 100;
}

View File

@ -10,7 +10,7 @@ body
}
input {
width: 100px;
width: 150px;
height: 50px
}

22
templates/kurs.html Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Kurs wählen</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
<script async src="https://analytics.paulmartin.cloud/script.js" data-website-id="459fa66e-e255-4393-8e89-ead8b1572d0d"></script>
</head>
<body>
{% if not detected[1] %}
<h1>Wir haben {{ detected[0] }} als deinen Kurs ermittelt. Falls er nicht stimmt, kannst du ihn unten auswählen.</h1>
<form action={{ url_for("welcome") }}>
<input type="submit" value="Der Kurs stimmt!">
</form>
{% else %}
<h1>Dein Kurs konnte leider nicht ermittelt werden. Klicke den Button, um direkt zur Auswahl zu kommen.</h1>
{% endif %}
<form action={{ url_for("chooseRaplas") }}>
<input type="submit" value="Manuell auswählen!">
</form>
</body>
</html>

51
templates/plan.html Normal file
View File

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Vorlesungsplan</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='cal.css') }}">
</head>
<body>
<div class="calendar">
<div class="timeline">
<div class="spacer"></div>
<div class="time-marker">08</div>
<div class="time-marker">09</div>
<div class="time-marker">10</div>
<div class="time-marker">11</div>
<div class="time-marker">12</div>
<div class="time-marker">13</div>
<div class="time-marker">14</div>
<div class="time-marker">15</div>
<div class="time-marker">16</div>
<div class="time-marker">17</div>
<div class="time-marker">18</div>
<div class="time-marker">19</div>
</div>
<div class="days">
{% for e in range (eventdays|length) %}
<div class="day {{ eventdays[e]["short"] }}">
<div class="date">
<p class="date-num">{{ eventdays[e]["day"] }}</p>
<p class="date-day">{{ eventdays[e]["long"] }}</p>
</div>
<div class="events">
{% for i in events %}
{% if i["weekday"] == e %}
<div class="event start-{{ i["start"][:2]+i["start"][3:] }} end-{{ i["end"][:2]+i["end"][3:]}}">
<p class="title">{{ i["name"] }}</p>
<p class="room">{{ i["room"] }}</p>
<p class="duration">{{ i["dur"] }}</p>
<p class="time"> {{ i["start"] }} - {{ i["end"] }}</p>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</body>
</html>