Upozornění:
Veškerý zde vystavený kód je mým autorským dílem a je zveřejněn výhradně za účelem ukázky stylu mé práce.
Kód slouží pouze k nahlédnutí – jakékoliv kopírování, šíření, úpravy či jiné využití bez mého výslovného souhlasu nejsou povoleny.
Zůstává mým duševním vlastnictvím ve smyslu autorského zákona.
Děkuji za pochopení.
← Zpět na seznam

App DZSR.cz (Python)


from flask import Flask, request, jsonify, send_from_directory
from datetime import datetime
import sqlite3
import os
import json
import secrets
import smtplib
from email.message import EmailMessage
from dotenv import load_dotenv
import bcrypt
import csv


load_dotenv()

app = Flask(__name__)
DB_NAME = "zaznamy.db"

def init_db():
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute('''
            CREATE TABLE IF NOT EXISTS zaznamy (
                id TEXT PRIMARY KEY,
                typ TEXT,
                kod INTEGER,
                cas_nalozeni TEXT,
                mesto_nalozeni TEXT,
                poznamka TEXT,
                cas_vylozeni TEXT,
                mesto_vylozeni TEXT,
                tachometr TEXT,
                smena TEXT,
                datum TEXT,
                ridic TEXT,
                vozidlo TEXT,
                rodne_cislo TEXT,
                pojistovna TEXT
                ulozeno TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        c.execute('''
            CREATE TABLE IF NOT EXISTS karta_vozidla (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                datum TEXT,
                poradove_cislo INTEGER,
                vozidlo TEXT,
                smena TEXT,
                ujeto_km INTEGER,
                konec_km INTEGER,
                natankovano_l REAL,
                stav_v_nadrzi_l REAL,
                poznamka TEXT,
                ridic TEXT,
                zapsano TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        c.execute('''
            CREATE TABLE IF NOT EXISTS uzivatele (
                username TEXT PRIMARY KEY,
                heslo TEXT,
                ridic TEXT,
                vozidlo TEXT,
                role TEXT DEFAULT 'ridic'
            )
        ''')
        c.execute('''
            CREATE TABLE IF NOT EXISTS vozidla (
                spz TEXT PRIMARY KEY,
                spotreba REAL,
                stav TEXT DEFAULT 'volne'
            )
        ''')

        c.execute("""
            CREATE TABLE IF NOT EXISTS dovolena (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                ridic TEXT NOT NULL,
                rok INTEGER NOT NULL,
                mesic INTEGER NOT NULL,
                tyden INTEGER NOT NULL,
                stav TEXT NOT NULL
            )
        """)
        conn.commit()


SMENY = [
    "D1", "D7", "D5+HDS", "PG", "-", "-", "-", 
    "D7", "D2", "5.00 - 15.00 K1", "D3", "7.00 - 15.30 K2", "-", "-", 
    "D5+HDS", "PG", "-", "4.40 - 15.00 K1", "D2", "6.30 - 18.30 R1", "PG", 
    "-", "4.40 - 15.00 K1", "D3", "7.00 - 15.30 K2", "D4", "-", "6.30 - 18.30 R1", 
    "18.30 - 06.30 NR", "-", "D1", "6.30 - 18.30 R2", "D6", "-", "-", 
    "7.00 - 15.30 K2", "6.30 - 18.30 R2", "D4", "D2", "7.00 - 15.30 OS + HDS", "-", "-", 
    "6.30 - 18.30 R1", "18.30 - 06.30 NR", "-", "D1", "D3", "HDS", "-",
    "6.30 - 18.30 R2", "7.00 - 15.30 OS + HDS", "D6", "D5+HDS", "PG", "PG", "18.30 - 06.30 NR",
    "-", "6.30 - 18.30 R1", "18.30 - 06.30 NR", "-", "5.00 - 15.00 K1", "-", "-", 
    "D3", "D1", "7.00 - 15.30 OS + HDS", "D7", "D5+HDS", "-", "-", 
    "D2", "D3", "6.30 - 18.30 R1", "18.30 - 06.30 NR", "-", "-", "-", 
    "PG", "-", "6.30 - 18.30 R2", "D4", "D1", "-", "-",
    "7.00 - 15.30 OS + HDS", "D4", "7.00 - 15.30 K2", "D6", "D7", "-", "-",
    "5.00 - 15.00 K1", "D6", "-", "6.30 - 18.30 R1", "18.30 - 06.30 NR", "18.30 - 06.30 NR", "-", 
    "D4", "D5+HDS", "PG", "-", "6.30 - 18.30 R2", "OHDS", "-", 
    "D6", "7.00 - 15.30 K2", "D2", "7.00 - 15.30 OS + HDS", "6.30 - 18.30 R1", "-", "-"
]

BASE_START_DATE = datetime(2025, 3, 31)

def hash_hesla(heslo):
    return bcrypt.hashpw(heslo.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

def over_heslo(heslo, hash_z_db):
    return bcrypt.checkpw(heslo.encode('utf-8'), hash_z_db.encode('utf-8'))

def zaloguj_udalost(typ, uzivatel, ip_adresa):
    zaznam = {
        "typ": typ,
        "uzivatel": uzivatel,
        "cas": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "ip": ip_adresa
    }
    file_exists = os.path.exists("logs.csv")
    with open("logs.csv", mode="a", newline="", encoding="utf-8") as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=["typ", "uzivatel", "cas", "ip"], delimiter=";")
        if not file_exists:
            writer.writeheader()
        writer.writerow(zaznam)

def get_posun_z_db(kod):
    conn = sqlite3.connect(DB_NAME)
    cur = conn.cursor()
    cur.execute("SELECT posun FROM uzivatele WHERE kod = ?", (kod,))
    row = cur.fetchone()
    conn.close()
    return row[0] if row else 0

def get_smena(date: datetime, kod: str) -> str:
    posun = get_posun_z_db(kod)
    rozdil_dni = (date - BASE_START_DATE).days
    if rozdil_dni < 0:
        return "-"
    index = (rozdil_dni - posun) % len(SMENY)
    return SMENY[index]

def get_smena_a_km(vozidlo):
    from zoneinfo import ZoneInfo
    today = datetime.now(ZoneInfo("Europe/Prague")).strftime("%d.%m.%Y")
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT konec_km FROM karta_vozidla WHERE vozidlo = ? ORDER BY datum DESC, id DESC LIMIT 1", (vozidlo,))
        result = c.fetchone()
        start_km = result[0] if result and result[0] else 0
    return {"datum": today, "start_km": start_km}

# === Funkce pro odeslání e-mailu s volitelnými přílohami ===
def odesli_email(prijemce, predmet, zprava, prilohy=None):
    SMTP_SERVER = "smtp.gmail.com"
    SMTP_PORT = 587
    SMTP_USER = os.getenv("SMTP_USER")
    SMTP_PASSWORD = os.getenv("SMTP_PASSWORD")

    try:
        msg = EmailMessage()
        msg['Subject'] = predmet
        msg['From'] = SMTP_USER
        msg['To'] = prijemce
        msg.set_content(zprava)

        if prilohy:
            for pril in prilohy:
                with open(pril, 'rb') as f:
                    file_data = f.read()
                    file_name = os.path.basename(pril)
                    msg.add_attachment(file_data, maintype='application', subtype='octet-stream', filename=file_name)

        with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
            server.starttls()
            server.login(SMTP_USER, SMTP_PASSWORD)
            server.send_message(msg)

        print(f"[EMAIL] E-mail odeslán na {prijemce}")
        return True
    except Exception as e:
        print(f"[EMAIL] Chyba při odesílání na {prijemce}: {e}")
        return False

@app.route("/api/vozidla/")
def get_spotreba_vozidla(spz):
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT spotreba FROM vozidla WHERE spz = ?", (spz,))
        row = c.fetchone()
        if row:
            return jsonify({"spotreba": row[0]})
        else:
            return jsonify({"error": "Vozidlo nenalezeno"}), 404

@app.route("/api/login", methods=["POST"])
def login():
    data = request.get_json()
    username = data.get("username")
    password = data.get("password")
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT heslo, ridic, vozidlo, role, kod FROM uzivatele WHERE username = ?", (username,))
        row = c.fetchone()
    if not row:
        return jsonify({"success": False, "msg": "Uživatel nenalezen"}), 401
    heslo_db, ridic, vozidlo, role, kod = row
    if not over_heslo(password, heslo_db):
        return jsonify({"success": False, "msg": "Neplatné heslo"}), 401

    from datetime import timedelta
    today = datetime.utcnow() + timedelta(hours=2)  # ruční posun na ČR čas
    smena_auto = get_smena(today, kod)
    smena_info = get_smena_a_km(vozidlo)
    ip = request.headers.get('X-Forwarded-For', request.remote_addr)
    zaloguj_udalost("prihlaseni", username, ip)
    return jsonify({
        "success": True,
        "ridic": ridic,
        "vozidlo": vozidlo,
        "smena_navrzena": smena_auto,
        "datum": smena_info["datum"],
        "start_km": smena_info["start_km"],
        "role": role or "ridic"
    })

@app.route("/api/zaznamy", methods=["POST"])
def prijmi_zaznamy():
    data = request.get_json()
    if not isinstance(data, list):
        return jsonify({"error": "Data musí být seznam záznamů"}), 400
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        for z in data:
            try:
                c.execute('''
                    INSERT INTO zaznamy (
                        id, typ, kod, cas_nalozeni, mesto_nalozeni, poznamka,
                        cas_vylozeni, mesto_vylozeni, tachometr, smena, datum,
                        ridic, vozidlo, rodne_cislo, pojistovna
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', (
                        z.get("id"), z.get("typ"), z.get("kod"), z.get("cas_nalozeni"),
                        z.get("mesto_nalozeni"), z.get("poznamka"), z.get("cas_vylozeni"),
                        z.get("mesto_vylozeni"), z.get("tachometr"), z.get("smena"),
                        z.get("datum"), z.get("ridic"), z.get("vozidlo"),
                        z.get("rodne_cislo"), z.get("pojistovna")))
            except sqlite3.IntegrityError:
                pass
        conn.commit()
    return jsonify({"status": "OK", "count": len(data)})

@app.route("/api/karta", methods=["POST"])
def uloz_kartu():
    z = request.get_json()
    if not isinstance(z, dict):
        return jsonify({"error": "Chybná data"}), 400
    datum = z.get("datum")
    vozidlo = z.get("vozidlo")
    month_prefix = datum[:7]
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT COUNT(*) FROM karta_vozidla WHERE vozidlo = ? AND datum LIKE ?", (vozidlo, f"{month_prefix}%"))
        poradove = c.fetchone()[0] + 1
        c.execute('''
            INSERT INTO karta_vozidla (
                datum, poradove_cislo, vozidlo, smena, ujeto_km, konec_km,
                natankovano_l, stav_v_nadrzi_l, poznamka, ridic
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', (
                datum, poradove, vozidlo, z.get("smena"), z.get("ujeto_km"),
                z.get("konec_km"), z.get("natankovano_l"), z.get("stav_v_nadrzi_l"),
                z.get("poznamka"), z.get("ridic")))
        conn.commit()
    return jsonify({"status": "Karta uložena", "poradove": poradove}), 200

@app.route("/tabulky")
def get_tabulky():
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'")
        tabulky = [row[0] for row in c.fetchall()]
    return jsonify(tabulky)

@app.route("/filtry")
def get_filtry():
    tabulka = request.args.get("tabulka")
    if tabulka not in ["zaznamy", "karta_vozidla", "uzivatele", "vozidla"]:
        return jsonify({"error": "Neznámá tabulka"}), 400
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        try:
            c.execute(f"SELECT DISTINCT ridic FROM {tabulka} WHERE ridic IS NOT NULL")
            jmena = sorted(set(row[0] for row in c.fetchall() if row[0]))
        except sqlite3.OperationalError:
            jmena = []
        try:
            if tabulka == "vozidla":
                c.execute("SELECT spz FROM vozidla WHERE stav = 'volne'")
                spz = sorted(set(row[0] for row in c.fetchall()))
            else:
                c.execute(f"SELECT DISTINCT vozidlo FROM {tabulka} WHERE vozidlo IS NOT NULL")
                spz = sorted(set(str(row[0]) for row in c.fetchall() if row[0]))
        except sqlite3.OperationalError:
            spz = []
    return jsonify({"spz": spz, "jmeno": jmena})

@app.route("/api/stav_vozidla")
def stav_vozidla():
    spz = request.args.get("spz")
    if not spz:
        return jsonify({"error": "Chybí parametr SPZ"}), 400
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT stav FROM vozidla WHERE spz = ?", (spz,))
        row = c.fetchone()
        if not row:
            return jsonify({"error": "Vozidlo neexistuje"}), 404
        return jsonify({"stav": row[0]})

@app.route("/api/rezervuj_vozidlo", methods=["POST"])
def rezervuj_vozidlo():
    data = request.get_json()
    spz = data.get("vozidlo")
    if not spz:
        return jsonify({"error": "Chybí parametr vozidlo"}), 400
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT stav FROM vozidla WHERE spz = ?", (spz,))
        row = c.fetchone()
        if not row:
            return jsonify({"error": "Vozidlo neexistuje"}), 404
        if row[0] == "obsazene":
            return jsonify({"error": "Vozidlo je již obsazeno"}), 409
        c.execute("UPDATE vozidla SET stav = 'obsazene' WHERE spz = ?", (spz,))
        conn.commit()
    return jsonify({"ok": True})

@app.route("/api/uvolni_vozidlo", methods=["POST"])
def uvolni_vozidlo():
    data = request.get_json()
    spz = data.get("vozidlo")
    if not spz:
        return jsonify({"error": "Chybí parametr vozidlo"}), 400
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT stav FROM vozidla WHERE spz = ?", (spz,))
        row = c.fetchone()
        if not row:
            return jsonify({"error": "Vozidlo neexistuje"}), 404
        if row[0] == "volne":
            return jsonify({"ok": True, "msg": "Vozidlo je již volné"})
        c.execute("UPDATE vozidla SET stav = 'volne' WHERE spz = ?", (spz,))
        conn.commit()
    return jsonify({"ok": True, "msg": "Vozidlo bylo uvolněno"})

@app.route("/data")
def get_data():
    tabulka = request.args.get("tabulka")
    spz = request.args.get("spz")
    jmeno = request.args.get("jmeno")
    datum = request.args.get("datum")
    if tabulka not in ["zaznamy", "karta_vozidla", "uzivatele", "vozidla"]:
        return jsonify([])
    filters = []
    params = []
    if jmeno:
        filters.append("ridic = ?")
        params.append(jmeno)
    spz_sloupec = "vozidlo" if tabulka in ["karta_vozidla", "zaznamy"] else "spz"
    if spz and spz_sloupec:
        filters.append(f"{spz_sloupec} = ?")
        params.append(spz)
    if datum:
        filters.append("datum = ?")
        params.append(datum)
    where_clause = " WHERE " + " AND ".join(filters) if filters else ""
    order_clause = " ORDER BY datum DESC, id DESC" if tabulka == "karta_vozidla" else ""
    with sqlite3.connect(DB_NAME) as conn:
        conn.row_factory = sqlite3.Row
        c = conn.cursor()
        c.execute(f"SELECT * FROM {tabulka}{where_clause}{order_clause}", params)
        rows = [dict(row) for row in c.fetchall()]
    return jsonify(rows)

@app.route("/update", methods=["PUT"])
def update_zaznam():
    tabulka = request.args.get("tabulka")
    data = request.get_json()
    if tabulka not in ["zaznamy", "karta_vozidla"]:
        return jsonify({"error": "Nepovolená tabulka"}), 400
    if not data:
        return jsonify({"error": "Chybí data"}), 400

    keys = list(data.keys())
    if "id" in data:
        where = "id = ?"
        where_value = data["id"]
    elif "poradove_cislo" in data and "datum" in data:
        where = "poradove_cislo = ? AND datum = ?"
        where_value = (data["poradove_cislo"], data["datum"])
    else:
        return jsonify({"error": "Nelze určit unikátní záznam"}), 400

    fields = [f"{k} = ?" for k in keys if k not in ["id", "poradove_cislo", "datum"]]
    values = [data[k] for k in keys if k not in ["id", "poradove_cislo", "datum"]]
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        if isinstance(where_value, tuple):
            c.execute(f"UPDATE {tabulka} SET {', '.join(fields)} WHERE {where}", (*values, *where_value))
        else:
            c.execute(f"UPDATE {tabulka} SET {', '.join(fields)} WHERE {where}", (*values, where_value))
        conn.commit()
    return jsonify({"status": "upraveno"})

@app.route("/delete", methods=["DELETE"])
def delete_zaznam():
    tabulka = request.args.get("tabulka")
    data = request.get_json()
    if tabulka not in ["zaznamy", "karta_vozidla"]:
        return jsonify({"error": "Nepovolená tabulka"}), 400
    if not data:
        return jsonify({"error": "Chybí data"}), 400

    if "id" in data:
        where = "id = ?"
        params = (data["id"],)
    elif "poradove_cislo" in data and "datum" in data:
        where = "poradove_cislo = ? AND datum = ?"
        params = (data["poradove_cislo"], data["datum"])
    else:
        return jsonify({"error": "Nelze určit záznam pro smazání"}), 400

    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute(f"DELETE FROM {tabulka} WHERE {where}", params)
        conn.commit()
    return jsonify({"status": "smazano"})

@app.route("/api/dovolena", methods=["GET", "POST"])
def dovolena_api():
    file_path = "2025_dovolena.json"
    if request.method == "GET":
        if os.path.exists(file_path):
            with open(file_path, "r", encoding="utf-8") as f:
                data = json.load(f)
        else:
            data = {}
        return jsonify(data)
    elif request.method == "POST":
        data = request.get_json()
        if not isinstance(data, dict):
            return jsonify({"error": "Data musí být objekt"}), 400
        with open(file_path, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        return jsonify({"status": "uloženo"})
    
@app.route("/api/ridici")
def ridici():
    con = sqlite3.connect("zaznamy.db")
    cur = con.cursor()
    cur.execute("SELECT ridic FROM uzivatele WHERE role = 'ridic' AND ridic IS NOT NULL")
    data = [row[0] for row in cur.fetchall()]
    con.close()
    return jsonify(data)

@app.route("/api/ztracene_smeny", methods=["POST"])
def ztracene_smeny():
    data = request.get_json()
    ridic = data.get("ridic")
    datumy = data.get("datumy", [])
    if not ridic or not datumy:
        return jsonify({"error": "Chybí ridic nebo datumy"}), 400

    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT kod FROM uzivatele WHERE ridic = ?", (ridic,))
        row = c.fetchone()
        if not row:
            return jsonify({"error": "Řidič nenalezen"}), 404
        kod = row[0]

    vysledky = []
    for datum_str in datumy:
        try:
            datum = datetime.strptime(datum_str, "%Y-%m-%d")
            smena = get_smena(datum, kod)
            if smena and smena != "-":
                vysledky.append({"datum": datum_str, "smena": smena})
        except Exception as e:
            continue

    return jsonify(vysledky)

@app.route("/api/zapomenute-heslo", methods=["POST"])
def zapomenute_heslo():
    data = request.get_json()
    email = data.get("email")
    if not email:
        return jsonify({"success": False, "msg": "Chybí e-mail"}), 400

    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT username FROM uzivatele WHERE email = ?", (email,))
        row = c.fetchone()

    if not row:
        # Neprozrazujeme, zda e-mail existuje – vždy vracíme success
        return jsonify({"success": True})

    nove_heslo = secrets.token_hex(4)  # např. 8 znaků dlouhé heslo
    hashed = hash_hesla(nove_heslo)

    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("UPDATE uzivatele SET heslo = ? WHERE email = ?", (hashed, email))
        conn.commit()

    predmet = "Obnova hesla - Sanitka systém"
    zprava = f"Bylo vám vygenerováno nové dočasné heslo: {nove_heslo}\nPo přihlášení si ho prosím změňte."
    odesli_email(email, predmet, zprava)
    ip = request.headers.get('X-Forwarded-For', request.remote_addr)
    zaloguj_udalost("obnova_hesla", row[0] if row else "neznámý", ip) #zaloguje obnovu hesla
    return jsonify({"success": True})

@app.route("/api/zmenit-heslo", methods=["POST"])
def zmenit_heslo():
    data = request.get_json()
    ridic = data.get("username")  # teď bereme jméno řidiče
    stare_heslo = data.get("stare_heslo")
    nove_heslo = data.get("nove_heslo")

    if not all([ridic, stare_heslo, nove_heslo]):
        return jsonify({"success": False, "msg": "Chybí údaje"}), 400

    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("SELECT heslo FROM uzivatele WHERE ridic = ?", (ridic,))
        row = c.fetchone()

    if not row:
        return jsonify({"success": False, "msg": "Uživatel nenalezen"}), 404

    stary_hash = row[0]
    if not over_heslo(stare_heslo, stary_hash):
        return jsonify({"success": False, "msg": "Špatné staré heslo"}), 401

    novy_hash = hash_hesla(nove_heslo)
    with sqlite3.connect(DB_NAME) as conn:
        c = conn.cursor()
        c.execute("UPDATE uzivatele SET heslo = ? WHERE ridic = ?", (novy_hash, ridic))
        conn.commit()

    return jsonify({"success": True, "msg": "Heslo změněno."})

@app.route("/api/odeslat-ics", methods=["POST"])
def odeslat_ics():
    data = request.get_json()
    smeny = data.get("smeny")
    jmeno = data.get("jmeno")
    mesic = data.get("mesic")

    if not smeny or not jmeno or not mesic:
        return jsonify({"zprava": "Neplatná data"}), 400

    # Získání e-mailu z tabulky 'uzivatele', sloupec 'ridic' obsahuje celé jméno
    conn = sqlite3.connect("zaznamy.db")
    cursor = conn.cursor()
    cursor.execute("SELECT email FROM uzivatele WHERE ridic = ? COLLATE NOCASE", (jmeno.strip(),))
    row = cursor.fetchone()
    conn.close()

    if not row:
        return jsonify({"zprava": "E-mail nenalezen"}), 404
    email = row[0]

    ics = "BEGIN:VCALENDAR\nVERSION:2.0\nCALSCALE:GREGORIAN\n"
    for zaznam in smeny:
        datum, smena = zaznam
        if not smena or smena == "-":
            continue
        try:
            dt = datetime.strptime(datum, "%Y-%m-%d")
        except ValueError:
            continue
        start = datetime(dt.year, dt.month, dt.day, 8, 0)
        end = datetime(dt.year, dt.month, dt.day, 16, 0)
        dt_start = start.strftime("%Y%m%dT%H%M%SZ")
        dt_end = end.strftime("%Y%m%dT%H%M%SZ")
        ics += f"BEGIN:VEVENT\nSUMMARY:{smena}\nDTSTART:{dt_start}\nDTEND:{dt_end}\nEND:VEVENT\n"
    ics += "END:VCALENDAR"

    # Ulož ICS do dočasného souboru
    filename = f"{mesic}.ics"
    with open(filename, "w", encoding="utf-8") as f:
        f.write(ics)

    # Odešli e-mail
    predmet = f"Rozpis směn - {mesic}"
    zprava = f"V příloze naleznete směny pro měsíc {mesic}."
    uspesne = odesli_email(email, predmet, zprava, prilohy=[filename])

    os.remove(filename)

    if uspesne:
        return jsonify({"zprava": "E-mail úspěšně odeslán."})
    else:
        return jsonify({"zprava": "Chyba při odesílání."}), 500

@app.route("/")
def index():
    return send_from_directory('.', 'index.html')

@app.route("/robots.txt")
def robots():
    return "User-agent: *\nDisallow: /\n", 200, {'Content-Type': 'text/plain'}

if __name__ == "__main__":
    init_db()
    app.run(host="0.0.0.0", port=8090, debug=True)
← Zpět na seznam