From b7174f353c4612cadbb055274a594986841ba648 Mon Sep 17 00:00:00 2001 From: paulmart-n Date: Thu, 30 Nov 2023 22:40:03 +0100 Subject: [PATCH] Dont store cookies + iCal refresh --- app.py | 109 ++++++++++++------------- parseICAL.py => calendar_generation.py | 38 ++++++++- fetchRAPLA.py | 29 ++++++- init.py | 65 +++++++++++++++ requirements.txt | 2 + templates/plan-anon.html | 57 +++++++++++++ templates/plan.html | 2 +- 7 files changed, 237 insertions(+), 65 deletions(-) rename parseICAL.py => calendar_generation.py (69%) create mode 100644 init.py create mode 100644 templates/plan-anon.html diff --git a/app.py b/app.py index 65ce79b..8b36ccd 100644 --- a/app.py +++ b/app.py @@ -1,59 +1,21 @@ #!/usr/bin/env python3.6 -from flask import Flask +from flask import Flask, make_response from flask import render_template, url_for, send_from_directory, redirect, request, send_file -from flask_login import login_user, login_required, current_user, LoginManager, UserMixin, logout_user +from flask_login import login_user, login_required, current_user, LoginManager, UserMixin, logout_user, login_manager from flask_sqlalchemy import SQLAlchemy from werkzeug.security import generate_password_hash, check_password_hash from talisman import Talisman import hashlib +import datetime import time import dualisauth +import fetchRAPLA import requesthelpers from fetchRAPLA import * from get_mysql import get_mysql -from parseICAL import getWeek - - -def create(): - app = Flask(__name__) - dbpw = get_mysql()[1] - dbun = get_mysql()[0] - - app.config['SECRET_KEY'] = 'SECRET_KEY_GOES_HERE' - app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://' + dbun + ':' + dbpw + '@localhost/paulmrtn_DUALHUB' - db.init_app(app) - - login_manager = LoginManager() - login_manager.init_app(app) - login_manager.login_view = "login" - - @login_manager.user_loader - def load_user(uid: int): - return User.query.filter_by(id=uid).first() - - return app - - -db = SQLAlchemy() -app = create() -Talisman(app) - - -class User(UserMixin, db.Model): - id = db.Column(db.Integer, primary_key=True) - email = db.Column(db.String(255), unique=True) - password = db.Column(db.String(255)) - name = db.Column(db.String(255)) - kurs = db.Column(db.String(15)) - - -class Dualis(db.Model): - token = db.Column(db.String(255), unique=True) - uid = db.Column(db.Integer, primary_key=True) - token_created = db.Column(db.Integer) - result_lists = db.Column(db.String(255)) - cookie = db.Column(db.String(255)) +from calendar_generation import getWeek +from init import * @app.route("/") @@ -77,7 +39,8 @@ def getKurs(): if d: e = False if not current_user.kurs: - kurs = dualisauth.getKurs(d.token, d.cookie) + cookie = request.cookies.get("cnsc") + kurs = dualisauth.getKurs(d.token, cookie) if kurs != 0: current_user.kurs = kurs db.session.commit() @@ -136,13 +99,40 @@ def getRapla(): @login_required @app.route("/backendpoc/plan", methods=["GET"]) def displayRapla(): + week = request.args.get("week") + if week: + week = datetime.datetime.strptime(week, "%Y-%m-%d") + else: + week = "today" samstag = request.args.get("samstag") if not samstag: samstag = False - events = getWeek("today", "rapla"+current_user.kurs+".ical", samstag) + events = getWeek(week, fetchRAPLA.getIcal(current_user.kurs), samstag) return render_template("plan.html", events=events[0], eventdays=events[1]) +@app.route("/backendpoc/plan/") +def displayPlan(kurs): + week = request.args.get("week") + if week: + week = datetime.datetime.strptime(week, "%Y-%m-%d") + else: + week = "today" + try: + if current_user.kurs == kurs.upper(): + return redirect(url_for("displayRapla")) + except AttributeError: + pass + plan = fetchRAPLA.getIcal(kurs.upper()) + if plan: + samstag = request.args.get("samstag") + if not samstag: + samstag = False + events = getWeek(week, plan, samstag) + return render_template("plan-anon.html", events=events[0], eventdays=events[1]) + else: + return redirect(url_for("login")) + @app.route("/backendpoc/log-in") def login(code: int = None): if code: @@ -156,19 +146,19 @@ def login_post(): password = request.form.get("password") n = request.args.get("next") if n: - success = redirect(n) + success = make_response(redirect(n)) else: - success = redirect(url_for("getKurs")) + success = make_response(redirect(url_for("getKurs"))) user = User.query.filter_by(email=email).first() - + newcookie = "" if user: dualis = Dualis.query.filter_by(uid=user.id).first() if check_password_hash(user.password, password): 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) + newcookie = requesthelpers.getCookie(new_token[1].cookies) dualis.token_created = time.time() db.session.commit() else: @@ -178,12 +168,13 @@ def login_post(): else: user.password = generate_password_hash(password, method="pbkdf2:sha256") dualis.token = t[0] - dualis.cookie = requesthelpers.getCookie(t[1].cookies) + newcookie = requesthelpers.getCookie(t[1].cookies) dualis.token_created = time.time() db.session.commit() login_user(user) if user.kurs: - success = redirect(url_for("welcome")) + success = make_response(redirect(url_for("welcome"))) + success.set_cookie("cnsc", newcookie) return success t = dualisauth.checkUser(email, password) @@ -201,23 +192,27 @@ def login_post(): cookie = requesthelpers.getCookie(t[1].cookies) - new_dualis = Dualis(uid=hashid, token=t[0], token_created=int(time.time()), cookie=cookie) - + new_dualis = Dualis(uid=hashid, token=t[0], token_created=int(time.time())) db.session.add(new_dualis) db.session.commit() login_user(new_user) + newcookie = cookie + success.set_cookie("cnsc", newcookie) return success @app.route("/backendpoc/log-out") def logout(): + cookie = request.cookies.get("cnsc") dualis = Dualis.query.filter_by(uid=current_user.id).first() - dualisauth.logOut(dualis.token, dualis.cookie) - dualis.cookie = None + dualisauth.logOut(dualis.token, cookie) dualis.token = None db.session.commit() logout_user() - return redirect(url_for("login", code=1)) + red = make_response(redirect(url_for("login", code=1))) + red.set_cookie("cnsc", "Logged out! Your temporary token " + "on our server and the cookie on your device have been deleted.") + return red if __name__ == "__main__": diff --git a/parseICAL.py b/calendar_generation.py similarity index 69% rename from parseICAL.py rename to calendar_generation.py index fc1e48b..faab5d9 100644 --- a/parseICAL.py +++ b/calendar_generation.py @@ -1,8 +1,11 @@ +import time import icalendar import datetime import requests import recurring_ical_events import json +from init import app, db, Meals + def getWeek(weekstart: datetime, file: str, showsat: bool): @@ -67,20 +70,49 @@ def daylist(weekstart: datetime, showsat: bool): def getMeals(day: datetime): + print (day) if day.day < 10: tag = "0" + str(day.day) else: tag = str(day.day) day = str(day.year) + "-" + str(day.month) + "-" + tag + essen = [] + query = Meals.query.filter_by(date=day).all() + + if len(query) != 0: + for i in query: + essen += [i.name] + return essen + url = "https://dh-api.paulmartin.cloud/plans/" + day + "?canteens=erzberger" response = requests.request("GET", url) response = response.content jres = json.loads(response.decode("utf-8")) - essen = [] + try: num = len(jres["data"][0]["lines"]) for i in range(num): - essen += [jres["data"][0]["lines"][i]["meals"][0]["name"]] + try: + jsmeal = jres["data"][0]["lines"][i]["meals"][0] + except IndexError: + return ["Essen nicht (mehr) verfügbar"] + name = jsmeal["name"] + vegan = jsmeal["classifiers"].count("VG") == 1 + schwein = jsmeal["classifiers"].count("S") == 1 + if vegan: + veget = True + else: + veget = jsmeal["classifiers"].count("VEG") == 1 + if veget: + if name.count("Reibekäse") > 0: + vegan = True + + if name != "Tagesdessert": + essen += [name] + mid = int(time.time()*1000) % 100000 + neu = Meals(date=day, name=name, id=mid, vegan=vegan, vegetarian=veget, schwein=schwein) + db.session.add(neu) + db.session.commit() except KeyError: - essen = ["Tag nicht (mehr) verfügbar"] + essen = ["Essen nicht (mehr) verfügbar"] return essen diff --git a/fetchRAPLA.py b/fetchRAPLA.py index 6f7eb81..b1310a8 100644 --- a/fetchRAPLA.py +++ b/fetchRAPLA.py @@ -3,6 +3,7 @@ from urllib.request import urlretrieve import icalendar import json import recurring_ical_events +from init import scheduler def parseURL(url: str): @@ -40,11 +41,20 @@ def getNewRapla(url: str): file = open("calendars/list.json", "r+") jsoncal = json.load(file) - jsoncal.update({kurs: "rapla" + kurs + ".ical"}) + jsoncal.update({kurs: ["rapla" + kurs + ".ical", url]}) file.close() file = open("calendars/list.json", "w") json.dump(jsoncal, file, indent=4) - return "rapla"+kurs+".ical" + return "rapla" + kurs + ".ical" + + +def getIcal(kurs: str): + file = open("calendars/list.json", "r") + jf = json.load(file) + try: + return jf[kurs] + except KeyError: + return None def getRaplas(): @@ -52,7 +62,18 @@ def getRaplas(): jsonf = json.load(file) kursl = [] filel = [] + urll = [] for i in jsonf: kursl += [i] - filel += [jsonf[i]] - return sorted(kursl), sorted(filel) + filel += [jsonf[i][0]] + urll += [jsonf[i][1]] + return sorted(kursl), sorted(filel), sorted(urll) + + +@scheduler.task("interval", id="refreshRapla", minutes=30) +def refreshRapla(): + filel = getRaplas()[1] + urll = getRaplas()[2] + for i in range(len(filel)): + urlretrieve(urll[i], "calendars/"+filel[i]) + print("Update die Kalender...") diff --git a/init.py b/init.py new file mode 100644 index 0000000..c6d0fca --- /dev/null +++ b/init.py @@ -0,0 +1,65 @@ +from flask import Flask +from flask_login import LoginManager, UserMixin +from flask_sqlalchemy import SQLAlchemy +from talisman import Talisman +from get_mysql import get_mysql +import atexit +from flask_apscheduler import APScheduler + + +def create(): + app = Flask(__name__) + dbpw = get_mysql()[1] + dbun = get_mysql()[0] + + app.config['SECRET_KEY'] = 'SECRET_KEY_GOES_HERE' + app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://' + dbun + ':' + dbpw + '@localhost/paulmrtn_DUALHUB' + db.init_app(app) + + login_manager = LoginManager() + login_manager.init_app(app) + login_manager.login_view = "login" + + # Shut down the scheduler when exiting the app + atexit.register(lambda: scheduler.shutdown()) + + @login_manager.user_loader + def load_user(uid: int): + return User.query.filter_by(id=uid).first() + + return app + + +db = SQLAlchemy() + + +class User(UserMixin, db.Model): + id = db.Column(db.Integer, primary_key=True) + email = db.Column(db.String(255), unique=True) + password = db.Column(db.String(255)) + name = db.Column(db.String(255)) + kurs = db.Column(db.String(15)) + + +class Dualis(db.Model): + token = db.Column(db.String(255), unique=True) + uid = db.Column(db.Integer, primary_key=True) + token_created = db.Column(db.Integer) + result_lists = db.Column(db.String(255)) + + +class Meals(db.Model): + id = db.Column(db.Integer, primary_key=True) + date = db.Column(db.Date) + name = db.Column(db.String(100)) + vegetarian = db.Column(db.Boolean) + vegan = db.Column(db.Boolean) + schwein = db.Column(db.Boolean) + + +scheduler = APScheduler() +app = create() +Talisman(app) +scheduler.init_app(app) +scheduler.start() +scheduler.api_enabled = True diff --git a/requirements.txt b/requirements.txt index 8b4e38f..2e58c0c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ beautifulsoup4 Flask +Flask_APScheduler Flask_Login flask_sqlalchemy icalendar @@ -7,3 +8,4 @@ recurring_ical_events Requests talisman Werkzeug +lxml diff --git a/templates/plan-anon.html b/templates/plan-anon.html new file mode 100644 index 0000000..a40d4d8 --- /dev/null +++ b/templates/plan-anon.html @@ -0,0 +1,57 @@ + + + + + Vorlesungsplan + + + +
+
+
+
08
+
09
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
+
+ {% for e in range (eventdays|length) %} +
+
+

{{ eventdays[e]["day"] }}

+

{{ eventdays[e]["long"] }}

+
+ {% for n in eventdays [e]["mensa"] %} +

{{ n }}

+ {% endfor %} +
+
+
+ {% for i in events %} + {% if i["weekday"] == e %} +
+

{{ i["name"] }}

+

{{ i["room"] }}

+

{{ i["dur"] }}

+

{{ i["start"] }} - {{ i["end"] }}

+
+ {% endif %} + {% endfor %} +
+
+ {% endfor %} +
+
+ + + Einloggen, um alle Features zu nutzen! + + \ No newline at end of file diff --git a/templates/plan.html b/templates/plan.html index 25a8ba2..5052bdf 100644 --- a/templates/plan.html +++ b/templates/plan.html @@ -41,7 +41,7 @@

{{ i["name"] }}

{{ i["room"] }}

{{ i["dur"] }}

-

{{ i["start"] }} - {{ i["end"] }}

+

{{ i["start"] }} - {{ i["end"] }}

{% endif %} {% endfor %}