diff --git a/.gitignore b/.gitignore index ddc0c93..c18b0ff 100644 --- a/.gitignore +++ b/.gitignore @@ -364,6 +364,13 @@ FodyWeavers.xsd # Wirtualne środowisko pythona FlaskWebProject/env +.venv # Wersja pythona -FlaskWebProject/FlaskWebProject.pyproj \ No newline at end of file +FlaskWebProject/FlaskWebProject.pyproj + +# Baza sqlite +FlaskWebProject/FlaskWebProject/instance + +# Poufne dane +config.toml \ No newline at end of file diff --git a/FlaskWebProject/FlaskWebProject/__init__.py b/FlaskWebProject/FlaskWebProject/__init__.py deleted file mode 100644 index 24c3a4e..0000000 --- a/FlaskWebProject/FlaskWebProject/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -from flask import Flask, render_template -from .lewy_globals import * - -app = Flask(__name__) - -@app.route('/') -def index(): - stats = { - 'goals': 38, - 'assists': 12, - 'matches': 45, - 'matches_list': [ - {'date': '2024-10-12', 'opponent': 'Real Madrid', 'goals': 2, 'assists': 1, 'minutes': 90}, - {'date': '2024-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85}, - # Możesz dodać więcej meczów... - ] - } - return render_template('index.html', goals=stats['goals'], assists=stats['assists'], - matches=stats['matches'], matches_list=stats['matches_list'], - commit_in_html=lewy_globals.getCommitInFormattedHTML()) - -@app.route('/mecze') -def mecze(): - # Możesz dostarczyć szczegóły dotyczące meczów - matches = [ - {'date': '2024-10-12', 'opponent': 'Real Madrid', 'goals': 2, 'assists': 1, 'minutes': 90}, - {'date': '2024-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85}, - ] - return render_template('matches.html', matches=matches) - -@app.route('/statystyki') -def statystyki(): - stats = { - 'goals': 38, - 'assists': 12, - 'matches': 45, - } - return render_template('stats.html', stats=stats) - -if __name__ == '__main__': - app.run(debug=True) \ No newline at end of file diff --git a/FlaskWebProject/FlaskWebProject/config.example.toml b/FlaskWebProject/FlaskWebProject/config.example.toml new file mode 100644 index 0000000..e4caaa7 --- /dev/null +++ b/FlaskWebProject/FlaskWebProject/config.example.toml @@ -0,0 +1,12 @@ +[general] +db_path_url = "postgresql+psycopg2://user:password@hostname/database_name" +db_prefix = "" # What (if any) prefix will be appended to table names. +is_proxied = false # Will ignore discrepancies between retrieved IP and public-facing URL. +public_facing_url = "http://127.0.0.1:5000/" # Used for URL rewriting. Note the trailing forward slash /. + +[api] +# Leave empty to automatically generate API key every launch (insecure). +api_key = "" + +[scraper] +user-agent = "" # Leave empty for default (Firefox ESR). diff --git a/FlaskWebProject/FlaskWebProject/fs_scraper.py b/FlaskWebProject/FlaskWebProject/fs_scraper.py new file mode 100644 index 0000000..401781e --- /dev/null +++ b/FlaskWebProject/FlaskWebProject/fs_scraper.py @@ -0,0 +1,15 @@ +import requests +import json + +class scraper: + + headers = { + 'x-fsign': 'SW9D1eZo' + } + + def __init__: + pass + + def pobierzDaneNajlepszegoSportowcaNaSwiecie() -> dict: + response = requests.get('https://3.flashscore.ninja/3/x/feed/plm_MVC8zHZD_0', headers=headers) + return json.loads(response.text) diff --git a/FlaskWebProject/FlaskWebProject/lewy.py b/FlaskWebProject/FlaskWebProject/lewy.py new file mode 100644 index 0000000..ecc5ccd --- /dev/null +++ b/FlaskWebProject/FlaskWebProject/lewy.py @@ -0,0 +1,168 @@ +from argparse import ArgumentParser +from flask import Flask, Response, render_template +from flask_apscheduler import APScheduler +from lewy_globals import colors as c +import lewy_api +import lewy_db +import lewy_globals +import lewy_routes +import os +import time + +app = Flask(__name__) +app_host = "None" +app_port = "None" + +def setup(): + # sanity check: make sure config is set + # required to make `flask --app lewy run --debug` work + global config, app_host, app_port + try: + if not config['general']: + lewy_globals.setConfig(lewy_globals.configfile) + config = lewy_globals.config + except: + lewy_globals.setConfig(lewy_globals.configfile) + config = lewy_globals.config + + # setting all the variables + lewy_globals.starttime = int(time.time()) + lewy_globals.realUptime = 0 + lewy_globals.apiRequests = 0 + lewy_globals.apiFailedRequests = 0 + lewy_globals.isProxied = config['general']['is_proxied'] + lewy_globals.outsideApiHits = 0 + + are_we_sure_of_host_and_port = True + if app_host == "None": + app_host = "127.0.0.1" + are_we_sure_of_host_and_port = False + if app_port == "None": + app_port = "5000" + are_we_sure_of_host_and_port = False + + public_facing_url = config['general']['public_facing_url'] + if len(public_facing_url) >= 4 and public_facing_url[0:5].lower() == "https": + https_str = f"{c.OKNLUE}INFO: {c.ENDC} You're trying to run this web server on HTTPS, but currently it's not possible to do that!\n" + https_str += f" Please consider running this service behind a reverse proxy if you need HTTPS.\n" + print(https_str) + rewrite_sanity_check = public_facing_url.replace(f"{app_host}:{app_port}", "") + if not config['general']['is_proxied'] and public_facing_url == rewrite_sanity_check: + sanity_string = f"{c.OKBLUE}INFO:{c.ENDC} Public facing URL does not match the IP and port the server is running on.\n" + sanity_string += f" Expected: {c.OKCYAN}{config['general']['public_facing_url']}{c.ENDC}, but" + if not are_we_sure_of_host_and_port: sanity_string += " (assuming it's)" + sanity_string += f" running on: {c.OKCYAN}{app_host}:{app_port}{c.ENDC}.\n" + sanity_string += f" This is just a sanity check and may not neccessarily mean bad configuration.\n" + sanity_string += f" If you're running a reverse proxy, set {c.OKCYAN}is_proxied{c.ENDC} to true to silence this message.\n" + print(sanity_string) + + app.config['SQLALCHEMY_DATABASE_URI'] = f"{config['general']['db_path_url']}" + app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + + # Widoki widoczne dla "normalnego" użytkownika: + app.add_url_rule('/', view_func=lewy_routes.index) + app.add_url_rule('/index.html', view_func=lewy_routes.index) + app.add_url_rule('/mecze', view_func=lewy_routes.mecze) + app.add_url_rule('/statystyki', view_func=lewy_routes.statystyki) + app.add_url_rule('/toggle_dark_mode', view_func=lewy_routes.toggle_dark_mode) + + # API: + app.add_url_rule('/api/', view_func=lewy_api.api_greeting) + app.add_url_rule('/api/', view_func=lewy_api.api_global_catchall) + + db = lewy_db.initDB(app, config) + + with app.app_context(): + db.create_all() + + # job scheduler for repetetive tasks + scheduler = APScheduler() + scheduler.add_job(func=every5seconds, trigger='interval', id='5sec', seconds=5) + scheduler.add_job(func=every2hours, trigger='interval', id='2hr', hours=2) + scheduler.start() + +# gets called every 5 seconds +def every5seconds(): + # update the "real" uptime counter + lewy_globals.realUptime += 5 + +def every2hours(): + # zaktualizuj bazę danych scrapując FS + # ... + return + +@app.route('/', methods=['GET']) +def blank(val): + return Response(f"{val}: not implemented in lewangoalski {lewy_globals.getCommitWithFailsafe()}", mimetype="text/plain") + +def main(args): + print(f"{c.BOLD + c.HEADER}Witaj w webaplikacji 'lewangoalski' ({lewy_globals.getCommitWithFailsafe()})!{c.ENDC}") + print(f"Aby uruchomić w trybie deweloperskim (aby włączyć automatyczne przeładowanie zmian), użyj: {c.OKCYAN}flask --app lewy run --debug{c.ENDC}.") + print( "Aby uruchomić lokalnie, użyj adresu IP 127.0.0.1. Aby uruchomić na każdym z interfejsów, użyj 0.0.0.0.\n") + + global config, app_host, app_port + try: + # if specified, use custom config file + lewy_globals.configfile = args.config + lewy_globals.setConfig(lewy_globals.configfile) + + except: + # if not, try using the default "config.toml" + if os.path.exists("config.toml"): + lewy_globals.configfile = "config.toml" + else: + # unless it's not there, if that's the case then use the dummy file + lewy_globals.configfile = "" + # but try to set the API secret if provided by the user + if args.secret: + lewy_globals.randomly_generated_passcode = args.secret + lewy_globals.setConfig(lewy_globals.configfile) + + config = lewy_globals.config + + try: + host = args.ip + port = args.port + if not host or not port: + raise Exception + except: + config_ip, config_port = lewy_globals.extractIpAndPortFromPublicUrl() + print(f"Wpisz nazwę_hosta:port, na których należy uruchomić serwer Flask [domyślnie: {config_ip}:{config_port}]:") + try: + host_port = input('> ').split(':') + if host_port == ['']: + host_port = [config_ip, config_port] # defaults + + except KeyboardInterrupt: + print(" ...wychodzę z programu."), quit() # handle Ctrl+C + + host = host_port[0] + port = host_port[1] + + print() + + app_host = host + app_port = port + + setup() + app.run(host=host, port=int(port)) + + +if __name__ == "__main__": + #app.run(host="127.0.0.1", port=5000) + #app.run(host="0.0.0.0", port=5000) + parser = ArgumentParser(description='Aplikacja webowa do śledzenia statystyk Roberta Lewandowskiego.') + + parser.add_argument("-i", "--ip", dest="ip", help="ip address/interface to bind to") + parser.add_argument("-p", "--port", dest="port", help="port on which the flask web backend should be ran") + parser.add_argument("-c", "--config", dest="config", help="path to TOML config file") + parser.add_argument("-s", "--secret", dest="secret", help="API key for resource access") # NOT tested + + args = parser.parse_args() + + main(args) + +else: + app_host = os.getenv("FLASK_RUN_HOST", "None") + app_port = os.getenv("FLASK_RUN_PORT", "None") + setup() \ No newline at end of file diff --git a/FlaskWebProject/FlaskWebProject/lewy_api.py b/FlaskWebProject/FlaskWebProject/lewy_api.py new file mode 100644 index 0000000..d718cdb --- /dev/null +++ b/FlaskWebProject/FlaskWebProject/lewy_api.py @@ -0,0 +1,43 @@ +from flask import Response, request +from lewy_globals import colors as c +from markupsafe import escape +import json +import lewy_globals +import lewy_api_v1 +import requests +import time +import traceback + +def api_greeting(): + string = {'status': 200, 'msg': f"ok (lewangoalski {lewy_globals.version})", 'latest_api': f"v{lewy_globals.apiVersion}"} + string = json.dumps(string) + return Response(string, mimetype='application/json') + +def api_global_catchall(received_request): + lewy_globals.apiRequests += 1 + if request.environ['REMOTE_ADDR'] != "127.0.0.1" or (lewy_globals.isProxied and request.environ['X-Forwarded-For'] != "127.0.0.1"): + lewy_globals.outsideApiHits += 1 + + request_list = received_request.split('/') + api_version = request_list[0] + if request_list[0] == 'v1': + # use v1 api + del request_list[0] + # if list is empty, aka /api/v1/, or /api/v1 + if request_list == [''] or request_list == []: + resp = api_greeting() + try: + status, received, data = lewy_api_v1.lookup(request_list) + except Exception as e: + lewy_globals.apiFailedRequests += 1 + stripped_filename = __file__[max(__file__.rfind("/"), __file__.rfind("\\")) + 1:] + print(f"\n{c.FAIL}Error! /api/{received_request} -> {stripped_filename}:L{e.__traceback__.tb_lineno} -> {type(e).__name__}{c.ENDC}:") + print(traceback.format_exc()) + status, received, data = 500, f"internal server error: call ended in failure: {e} ({stripped_filename}:L{e.__traceback__.tb_lineno})", [] + resp = Response(json.dumps({'status': status, 'msg': received, 'data': data}), mimetype='application/json', status=status) + else: + lewy_globals.apiFailedRequests += 1 + status, received, data = 405, f'error: unsupported api version: "{request_list[0]}". try: "v{lewy_globals.apiVersion}".', [] + resp = Response(json.dumps({'status': status, 'msg': received, 'data': data}), mimetype='application/json', status=status) + + return resp \ No newline at end of file diff --git a/FlaskWebProject/FlaskWebProject/lewy_api_v1.py b/FlaskWebProject/FlaskWebProject/lewy_api_v1.py new file mode 100644 index 0000000..01754e6 --- /dev/null +++ b/FlaskWebProject/FlaskWebProject/lewy_api_v1.py @@ -0,0 +1,44 @@ +# API is expected to return: +# - HTTP status code, +# - human-readable status message, +# - json with appropriate data +import flask, json, time +import lewy_globals + +def incrementBadRequests(): + lewy_globals.apiFailedRequests += 1 + +def notImplemented(data): + # TODO: change list to string -> data, not data[0] + return 501, f"not recognised/implemented: {data[0]}", [] + +def stub_hello(): + return 200, 'hello from v1! stats are at /api/v1/stats', [] + +def stats(): + data_to_send = { + "start_time": lewy_globals.starttime, + "uptime": lewy_globals.getUptime(), + "real_uptime": lewy_globals.realUptime, + "total_api_requests": lewy_globals.apiRequests, + "failed_api_requests": lewy_globals.apiFailedRequests, + "outside_api_requests": lewy_globals.outsideApiHits, + "local_api_requests": lewy_globals.apiRequests - lewy_globals.outsideApiHits + } + return 200, "OK", data_to_send + + + +def lookup(data): + if data == []: + return stub_hello() + match data[0].lower(): + case 'stats' | '': + return stats() + case 'user': + return stub_hello() + case 'info': + return stub_hello() + case _: + incrementBadRequests() + return notImplemented(data) \ No newline at end of file diff --git a/FlaskWebProject/FlaskWebProject/lewy_db.py b/FlaskWebProject/FlaskWebProject/lewy_db.py new file mode 100644 index 0000000..05356a9 --- /dev/null +++ b/FlaskWebProject/FlaskWebProject/lewy_db.py @@ -0,0 +1,86 @@ +from flask_sqlalchemy import SQLAlchemy +import toml + +global db + +def initDB(app, config): + tablenameprefix = config['general']['db_prefix'] + "_lewangoalski_" + + db = SQLAlchemy(app) + + class sportowcy(db.Model): + __tablename__ = tablenameprefix + "sportowcy" + id_zawodnika = db.Column(db.Integer, primary_key=True) + data_urodzenia = db.Column(db.String(10)) + czy_aktywny = db.Column(db.Boolean) + klub = db.Column(db.String(63)) + narodowosc = db.Column(db.String(3)) + ilosc_trofeow = db.Column(db.Integer) + ostatnie_trofeum = db.Column(db.Integer) + pierwszy_mecz = db.Column(db.Integer) + # ostatni_mecz = db.Column(db.Integer) # statystyki_sportowcow już to przechowuje + wycena = db.Column(db.BigInteger) + ostatni_gol_dla = db.Column(db.String(3)) + statystyka = db.Column(db.Integer) + + class trofea(db.Model): + __tablename__ = tablenameprefix + "trofea" + id_trofeum = db.Column(db.Integer, primary_key=True) + id_zawodnika = db.Column(db.Integer) # != None + nazwa = db.Column(db.String(127)) + sezon = db.Column(db.String(9)) + rok = db.Column(db.String(4)) + + class sportowcy_w_meczach(db.Model): + __tablename__ = tablenameprefix + "sportowcy_w_meczach" + id_rekordu = db.Column(db.Integer, primary_key=True) + id_zawodnika = db.Column(db.Integer) # != None + zewnetrzne_id_meczu = db.Column(db.Integer) # != None + czas_gry = db.Column(db.Integer) + goli = db.Column(db.Integer) + asyst = db.Column(db.Integer) + interwencje_bramkarza = db.Column(db.Integer) + suma_interwencji_na_bramke = db.Column(db.Integer) + zolte_kartki = db.Column(db.Integer) + czerwone_kartki = db.Column(db.Integer) + wygrana = db.Column(db.Integer) + wynik = db.Column(db.Float) + + class statystyki_sportowcow(db.Model): + __tablename__ = tablenameprefix + "statystyki_sportowcow" + id_statystyki = db.Column(db.Integer, primary_key=True) + ostatni_mecz = db.Column(db.Integer) + ilosc_wystapien = db.Column(db.Integer) + minut_gry = db.Column(db.BigInteger) + gier_sum = db.Column(db.Integer) + goli_sum = db.Column(db.Integer) + asyst_sum = db.Column(db.Integer) + interwencji_sum = db.Column(db.Integer) + nieobronionych_interwencji_sum = db.Column(db.Integer) + zoltych_kartek_sum = db.Column(db.Integer) + czerwonych_kartek_sum = db.Column(db.Integer) + wygranych_sum = db.Column(db.Integer) + wynik_sum = db.Column(db.Integer) + meczow_do_wynikow_sum = db.Column(db.Integer) + + class kluby(db.Model): + __tablename__ = tablenameprefix + "kluby" + id_klubu = db.Column(db.String(63), primary_key=True) + pelna_nazwa = db.Column(db.String(63)) + skrocona_nazwa = db.Column(db.String(3)) + + class mecze(db.Model): + __tablename__ = tablenameprefix + "mecze" + id_meczu = db.Column(db.Integer, primary_key=True) + zewnetrzne_id_meczu = db.Column(db.String(15)) # != None + data = db.Column(db.DateTime) + gospodarze = db.Column(db.String(3)) + goscie = db.Column(db.String(3)) + gosp_wynik = db.Column(db.Integer) + gosc_wynik = db.Column(db.Integer) + sezon = db.Column(db.String(9)) + nazwa_turnieju = db.Column(db.String(127)) + skrocona_nazwa_turnieju = db.Column(db.String(15)) + flaga = db.Column(db.Integer) + + return db \ No newline at end of file diff --git a/FlaskWebProject/FlaskWebProject/lewy_globals.py b/FlaskWebProject/FlaskWebProject/lewy_globals.py index 66fe5a8..07edd4e 100644 --- a/FlaskWebProject/FlaskWebProject/lewy_globals.py +++ b/FlaskWebProject/FlaskWebProject/lewy_globals.py @@ -1,9 +1,37 @@ from git import Repo # hash ostatniego commitu +import os +import time +import toml + +global config, randomly_generated_passcode + +class colors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKCYAN = '\033[96m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + ENDL = '\n' + +def safeTraverse(obj: dict, path: list, default=None): + result = obj + try: + for x in path: + result = result[x] + except KeyError: + result = default + # print(f"error reading: {' -> '.join(path)} - returning: {default}") + finally: + return result def getCommit(): try: return Repo(search_parent_directories=True).head.object.hexsha - except: + except Exception as e: return None def getCommitInFormattedHTML(): @@ -13,4 +41,85 @@ def getCommitInFormattedHTML(): if commit is not None: repo = f"

Commit: {commit[:11]}

" - return repo \ No newline at end of file + return repo + +def getCommitWithFailsafe(): + commit = getCommit() + + if commit is None: + commit = "(unknown commit)" + else: + commit = "#" + commit + + return commit[:12] + +def ensureRandomlyGeneratedPassword(): + global randomly_generated_passcode + + # iff the passcode is 0, as we manually set it elsewhere! + if randomly_generated_passcode == 0: + # generate a pseudorandom one and use it in the temporary config + randomly_generated_passcode = str(int(time.time() * 1337 % 899_999 + 100_000)) + + print(f"{colors.WARNING}WARNING{colors.ENDC}: Default config populated with one-time, insecure pseudorandom API key: {colors.OKCYAN}{randomly_generated_passcode}{colors.ENDC}.\n" + f" The API key is not the Flask debugger PIN. You need to provide a config file for persistence!{colors.ENDL}") + +def getConfig(configfile): + global randomly_generated_passcode + + if not os.path.exists(configfile): + dummy_config = {'general': {'db_path_url': 'sqlite:///lewangoalski.sqlite', 'is_proxied': False, 'public_facing_url': 'http://127.0.0.1:5000/', db_prefix: 'lewy_sqlite'}, 'api': {'api_key': 'CHANGEME'}, 'scraper': {'user-agent': ''}} + # if a passcode has not been provided by the user (config file doesn't exist, and user didn't specify it using an argument) + print(f"{colors.WARNING}WARNING{colors.ENDC}: Using default, baked in config data. {colors.ENDL}" + f" Consider copying and editing the provided example file ({colors.OKCYAN}config.example.toml{colors.ENDC}).") + + ensureRandomlyGeneratedPassword() + + dummy_config['api']['api_key'] = str(randomly_generated_passcode) + return dummy_config + + else: + return toml.load(configfile) + +def setConfig(configfile): + global config + config = getConfig(configfile) + + if safeTraverse(config['api']['api_key'], []) is None or not config['api']['api_key']: + ensureRandomlyGeneratedPassword() + config['api']['api_key'] = str(randomly_generated_passcode) + + +def getHeaders(): + # NOTE: use ESR user-agent + # user_agent = 'Mozilla/5.0 (Windows NT 10.0; rv:130.0) Gecko/20100101 Firefox/130.0' + user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0' + + if safeTraverse(config[scraper]['user-agent'], []) is not None: + user_agent = config[scraper]['user-agent'] + + return user_agent + +def getUptime(): + return int(time.time()) - starttime + +def extractIpAndPortFromPublicUrl() -> tuple: + + ip, port = "127.0.0.1", "5000" + + try: + url = config['general']['public_facing_url'].replace(":/", "") + url_parts = url.split('/') + ip_and_port = url_parts[1] + ip, port = ip_and_port.split(':') + except: + pass + + return ip, port + +# Please leave at the bottom of this file. +config = {} +configfile = "config.toml" +version = getCommitWithFailsafe() +apiVersion = "1" +randomly_generated_passcode = 0 \ No newline at end of file diff --git a/FlaskWebProject/FlaskWebProject/lewy_routes.py b/FlaskWebProject/FlaskWebProject/lewy_routes.py new file mode 100644 index 0000000..dbae515 --- /dev/null +++ b/FlaskWebProject/FlaskWebProject/lewy_routes.py @@ -0,0 +1,43 @@ +from flask import render_template, request, make_response +import lewy_globals + +def index(): + dark_mode = request.cookies.get('darkMode', 'disabled') + stats = { + 'goals': 38, + 'assists': 12, + 'matches': 45, + 'matches_list': [ + {'date': '2024-10-12', 'opponent': 'Real Madrid', 'goals': 2, 'assists': 1, 'minutes': 90}, + {'date': '2024-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85}, + # Możesz dodać więcej meczów... + ] + } + return render_template('index.html', goals=stats['goals'], assists=stats['assists'], + matches=stats['matches'], matches_list=stats['matches_list'], + commit_in_html=lewy_globals.getCommitInFormattedHTML(), + dark_mode=dark_mode) + +def mecze(): + # Możesz dostarczyć szczegóły dotyczące meczów + matches = [ + {'date': '2024-10-12', 'opponent': 'Real Madrid', 'goals': 2, 'assists': 1, 'minutes': 90}, + {'date': '2024-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85}, + ] + return render_template('matches.html', matches=matches) + +def statystyki(): + stats = { + 'goals': 38, + 'assists': 12, + 'matches': 45, + } + return render_template('stats.html', stats=stats) + +def toggle_dark_mode(): + # Przełącz tryb i zapisz w ciasteczku + dark_mode = request.cookies.get('darkMode', 'disabled') + new_mode = 'enabled' if dark_mode == 'disabled' else 'disabled' + response = make_response("OK") + response.set_cookie('darkMode', new_mode, max_age=31536000) # Ustawienie ciasteczka na 1 rok + return response diff --git a/FlaskWebProject/FlaskWebProject/routes.py b/FlaskWebProject/FlaskWebProject/routes.py deleted file mode 100644 index b6a478d..0000000 --- a/FlaskWebProject/FlaskWebProject/routes.py +++ /dev/null @@ -1,17 +0,0 @@ -from flask import render_template, request, make_response -from FlaskWebProject import app - -@app.route('/') -def index(): - # Odczyt ciasteczka "darkMode" – domyślnie "disabled" - dark_mode = request.cookies.get('darkMode', 'disabled') - return render_template('index.html', dark_mode=dark_mode) - -@app.route('/toggle_dark_mode') -def toggle_dark_mode(): - # Przełącz tryb i zapisz w ciasteczku - dark_mode = request.cookies.get('darkMode', 'disabled') - new_mode = 'enabled' if dark_mode == 'disabled' else 'disabled' - response = make_response("OK") - response.set_cookie('darkMode', new_mode, max_age=31536000) # Ustawienie ciasteczka na 1 rok - return response diff --git a/FlaskWebProject/runserver.py b/FlaskWebProject/runserver.py index 8ffef65..a789283 100644 --- a/FlaskWebProject/runserver.py +++ b/FlaskWebProject/runserver.py @@ -1,14 +1,5 @@ """ -This script runs the FlaskWebProject application using a development server. +Please see README.md for more tips on how to get your server running. """ -from os import environ -from FlaskWebProject import app - -if __name__ == '__main__': - HOST = environ.get('SERVER_HOST', 'localhost') - try: - PORT = int(environ.get('SERVER_PORT', '5555')) - except ValueError: - PORT = 5555 - app.run(HOST, PORT) +print("runserver.py is obsolete. Please run your server with lewy.py.") \ No newline at end of file