diff --git a/.idea/Medevio.iml b/.idea/Medevio.iml index 3cd7809..b51fc52 100644 --- a/.idea/Medevio.iml +++ b/.idea/Medevio.iml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 7a3c570..35161d5 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py b/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py index cbabdcf..755cb6c 100644 --- a/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py +++ b/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py @@ -8,6 +8,18 @@ from datetime import datetime, timezone import time from dateutil import parser +# Force UTF-8 output even under Windows Task Scheduler +import sys +try: + sys.stdout.reconfigure(encoding='utf-8') + sys.stderr.reconfigure(encoding='utf-8') +except AttributeError: + # Python < 3.7 fallback (not needed for you, but safe) + import io + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') + + # ================================ # 🔧 CONFIGURATION # ================================ diff --git a/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py b/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py index f7d4590..aefb18b 100644 --- a/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py +++ b/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py @@ -6,13 +6,41 @@ import requests from pathlib import Path from datetime import datetime from dateutil import parser +import sys + +# Force UTF-8 output even under Windows Task Scheduler +import sys +try: + sys.stdout.reconfigure(encoding='utf-8') + sys.stderr.reconfigure(encoding='utf-8') +except AttributeError: + # Python < 3.7 fallback (not needed for you, but safe) + import io + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') + +# ================================ +# 🛡 SAFE PRINT FOR CP1250 / Emoji +# ================================ +def safe_print(text: str): + enc = sys.stdout.encoding or "" + if not enc.lower().startswith("utf"): + # strip emoji + characters outside BMP + text = ''.join(ch for ch in text if ord(ch) < 65536) + try: + print(text) + except UnicodeEncodeError: + # final fallback to ASCII only + text = ''.join(ch for ch in text if ord(ch) < 128) + print(text) + # ================================ # 🔧 CONFIGURATION # ================================ TOKEN_PATH = Path("token.txt") CLINIC_SLUG = "mudr-buzalkova" -LIMIT = 300 # stáhneme posledních 300 ukončených požadavků +LIMIT = 300 DB_CONFIG = { "host": "192.168.1.76", @@ -24,7 +52,7 @@ DB_CONFIG = { "cursorclass": pymysql.cursors.DictCursor, } -# ⭐ Ověřený dotaz s lastMessage +# ⭐ GraphQL query GRAPHQL_QUERY = r""" query ClinicRequestList2( $clinicSlug: String!, @@ -71,33 +99,31 @@ def read_token(path: Path) -> str: return tok.split(" ", 1)[1] return tok + # ================================ -# DATETIME PARSER (UTC → MySQL) +# DATETIME PARSER # ================================ def to_mysql_dt(iso_str): if not iso_str: return None try: - dt = parser.isoparse(iso_str) # ISO8601 → aware datetime (UTC) - dt = dt.astimezone() # převede na lokální čas (CET/CEST) + dt = parser.isoparse(iso_str) + dt = dt.astimezone() return dt.strftime("%Y-%m-%d %H:%M:%S") except: return None + # ================================ -# UPSERT WITH MERGED UPDATED TIME +# UPSERT # ================================ def upsert(conn, r): p = r.get("extendedPatient") or {} - # API pole api_updated = to_mysql_dt(r.get("updatedAt")) - - # poslední zpráva last_msg = r.get("lastMessage") or {} msg_at = to_mysql_dt(last_msg.get("createdAt")) - # vybereme novější čas def max_dt(a, b): if a and b: return max(a, b) @@ -137,6 +163,7 @@ def upsert(conn, r): conn.commit() + # ================================ # FETCH LAST 300 DONE REQUESTS # ================================ @@ -162,6 +189,7 @@ def fetch_done(headers): data = r.json()["data"]["requestsResponse"] return data.get("patientRequests", []) + # ================================ # MAIN # ================================ @@ -175,17 +203,18 @@ def main(): conn = pymysql.connect(**DB_CONFIG) - print(f"\n=== Downloading last {LIMIT} DONE requests @ {datetime.now():%Y-%m-%d %H:%M:%S} ===") + safe_print(f"\n=== Downloading last {LIMIT} DONE requests @ {datetime.now():%Y-%m-%d %H:%M:%S} ===") requests_list = fetch_done(headers) - print(f"📌 Requests returned: {len(requests_list)}") + safe_print(f"📌 Requests returned: {len(requests_list)}") for r in requests_list: upsert(conn, r) conn.close() - print("\n✅ DONE - latest closed requests synced.\n") + safe_print("\n\u2705 DONE - latest closed requests synced.\n") +# ================================ if __name__ == "__main__": main() diff --git a/10ReadPozadavky/PRAVIDELNE_2_ReadPoznamky.py b/10ReadPozadavky/PRAVIDELNE_2_ReadPoznamky.py index b742f2f..db18fe9 100644 --- a/10ReadPozadavky/PRAVIDELNE_2_ReadPoznamky.py +++ b/10ReadPozadavky/PRAVIDELNE_2_ReadPoznamky.py @@ -12,6 +12,35 @@ import pymysql from datetime import datetime from pathlib import Path import time +import sys + +# Force UTF-8 output even under Windows Task Scheduler +import sys +try: + sys.stdout.reconfigure(encoding='utf-8') + sys.stderr.reconfigure(encoding='utf-8') +except AttributeError: + # Python < 3.7 fallback (not needed for you, but safe) + import io + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') + + +# ============================== +# 🛡 SAFE PRINT FOR CP1250 / EMOJI +# ============================== +def safe_print(text: str): + enc = sys.stdout.encoding or "" + if not enc.lower().startswith("utf"): + # strip emoji + anything above BMP + text = ''.join(ch for ch in text if ord(ch) < 65536) + try: + print(text) + except UnicodeEncodeError: + # final ASCII fallback + text = ''.join(ch for ch in text if ord(ch) < 128) + print(text) + # ============================== # 🔧 CONFIGURATION @@ -31,29 +60,30 @@ DB_CONFIG = { } -from datetime import datetime - +# ============================== +# 🕒 DATETIME FIXER +# ============================== def fix_datetime(dt_str): """Convert ISO 8601 string with 'Z' or ms into MySQL DATETIME format.""" if not dt_str: return None try: - # Remove trailing Z and parse flexible ISO format return datetime.fromisoformat(dt_str.replace("Z", "").replace("+00:00", "")) except Exception: return None -# ✅ Optional: limit which requests to process -CREATED_AFTER = "2025-01-01" # set "" to disable + +# Optional filter +CREATED_AFTER = "2025-01-01" + # ============================== # 🧮 HELPERS # ============================== def read_token(p: Path) -> str: - """Read Bearer token from file.""" tok = p.read_text(encoding="utf-8").strip() if tok.startswith("Bearer "): - tok = tok.split(" ", 1)[1] + return tok.split(" ", 1)[1] return tok @@ -101,7 +131,7 @@ def fetch_questionnaire(headers, request_id, clinic_slug): } r = requests.post(GRAPHQL_URL, json=payload, headers=headers, timeout=40) if r.status_code != 200: - print(f"❌ HTTP {r.status_code} for {request_id}: {r.text}") + safe_print(f"❌ HTTP {r.status_code} for {request_id}: {r.text}") return None return r.json().get("data", {}).get("request") @@ -118,23 +148,24 @@ def insert_questionnaire(cur, req): updated_at = fix_datetime(req.get("updatedAt")) cur.execute(""" -INSERT INTO medevio_questionnaires ( - request_id, created_at, updated_at, user_note, ecrf_json -) -VALUES (%s,%s,%s,%s,%s) + INSERT INTO medevio_questionnaires ( + request_id, created_at, updated_at, user_note, ecrf_json + ) + VALUES (%s,%s,%s,%s,%s) ON DUPLICATE KEY UPDATE updated_at = VALUES(updated_at), user_note = VALUES(user_note), ecrf_json = VALUES(ecrf_json), updated_local = NOW() """, ( - req.get("id"), - created_at, - updated_at, - req.get("userNote"), - json.dumps(ecrf_data, ensure_ascii=False), -)) - print(f" 💾 Stored questionnaire for {patient.get('surname','')} {patient.get('name','')}") + req.get("id"), + created_at, + updated_at, + req.get("userNote"), + json.dumps(ecrf_data, ensure_ascii=False), + )) + + safe_print(f" 💾 Stored questionnaire for {patient.get('surname','')} {patient.get('name','')}") # ============================== @@ -149,6 +180,8 @@ def main(): } conn = pymysql.connect(**DB_CONFIG) + + # load list of requests with conn.cursor() as cur: sql = """ SELECT id, pacient_jmeno, pacient_prijmeni, createdAt, updatedAt, questionnaireprocessed @@ -163,26 +196,30 @@ def main(): rows = cur.fetchall() - print(f"📋 Found {len(rows)} requests needing questionnaire check.") + safe_print(f"📋 Found {len(rows)} requests needing questionnaire check.") + # process each one for i, row in enumerate(rows, 1): req_id = row["id"] - print(f"\n[{i}/{len(rows)}] 🔍 Fetching questionnaire for {req_id} ...") + safe_print(f"\n[{i}/{len(rows)}] 🔍 Fetching questionnaire for {req_id} ...") req = fetch_questionnaire(headers, req_id, CLINIC_SLUG) if not req: - print(" ⚠️ No questionnaire data found.") + safe_print(" ⚠️ No questionnaire data found.") continue with conn.cursor() as cur: insert_questionnaire(cur, req) - cur.execute("UPDATE pozadavky SET questionnaireprocessed = NOW() WHERE id = %s", (req_id,)) + cur.execute( + "UPDATE pozadavky SET questionnaireprocessed = NOW() WHERE id = %s", + (req_id,) + ) conn.commit() - time.sleep(0.6) # polite pacing + time.sleep(0.6) conn.close() - print("\n✅ Done! All questionnaires stored in MySQL table `medevio_questionnaires`.") + safe_print("\n✅ Done! All questionnaires stored in MySQL table `medevio_questionnaires`.") # ============================== diff --git a/10ReadPozadavky/PRAVIDELNE_3_StahniKomunikaci.py b/10ReadPozadavky/PRAVIDELNE_3_StahniKomunikaci.py index 2b05def..daceb2a 100644 --- a/10ReadPozadavky/PRAVIDELNE_3_StahniKomunikaci.py +++ b/10ReadPozadavky/PRAVIDELNE_3_StahniKomunikaci.py @@ -15,6 +15,34 @@ import pymysql from pathlib import Path from datetime import datetime import time +import sys + +# Force UTF-8 output even under Windows Task Scheduler +import sys +try: + sys.stdout.reconfigure(encoding='utf-8') + sys.stderr.reconfigure(encoding='utf-8') +except AttributeError: + # Python < 3.7 fallback (not needed for you, but safe) + import io + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') + +# ============================== +# 🛡 SAFE PRINT FOR CP1250 / EMOJI +# ============================== +def safe_print(text: str): + enc = sys.stdout.encoding or "" + if not enc or not enc.lower().startswith("utf"): + # strip emoji + characters outside BMP for Task Scheduler (CP1250) + text = ''.join(ch for ch in text if ord(ch) < 65536) + try: + print(text) + except UnicodeEncodeError: + # fallback pure ASCII + text = ''.join(ch for ch in text if ord(ch) < 128) + print(text) + # ============================== # 🔧 CONFIGURATION @@ -94,7 +122,7 @@ def fetch_messages(headers, request_id): r = requests.post("https://api.medevio.cz/graphql", json=payload, headers=headers, timeout=30) if r.status_code != 200: - print("❌ HTTP", r.status_code, "for request", request_id) + safe_print(f"❌ HTTP {r.status_code} for request {request_id}") return [] return r.json().get("data", {}).get("messages", []) or [] @@ -158,7 +186,7 @@ def insert_download(cur, req_id, msg, existing_ids): return if attachment_id in existing_ids: - return # skip duplicates + return url = mr.get("downloadUrl") or mr.get("url") if not url: @@ -169,7 +197,7 @@ def insert_download(cur, req_id, msg, existing_ids): r.raise_for_status() data = r.content except Exception as e: - print("⚠️ Failed to download:", e) + safe_print(f"⚠️ Failed to download: {e}") return filename = url.split("/")[-1].split("?")[0] @@ -216,7 +244,7 @@ def main(): cur.execute("SELECT attachment_id FROM medevio_downloads") existing_ids = {row["attachment_id"] for row in cur.fetchall()} - print(f"📦 Already downloaded attachments: {len(existing_ids)}\n") + safe_print(f"📦 Already downloaded attachments: {len(existing_ids)}\n") # ---- Select pozadavky needing message sync sql = """ @@ -229,12 +257,12 @@ def main(): cur.execute(sql) requests_to_process = cur.fetchall() - print(f"📋 Found {len(requests_to_process)} pozadavků requiring message sync.\n") + safe_print(f"📋 Found {len(requests_to_process)} pozadavků requiring message sync.\n") - # ---- Process each pozadavek + # ---- Process each record for idx, row in enumerate(requests_to_process, 1): req_id = row["id"] - print(f"[{idx}/{len(requests_to_process)}] Processing {req_id} …") + safe_print(f"[{idx}/{len(requests_to_process)}] Processing {req_id} …") messages = fetch_messages(headers, req_id) @@ -248,11 +276,11 @@ def main(): cur.execute("UPDATE pozadavky SET messagesProcessed = NOW() WHERE id = %s", (req_id,)) conn.commit() - print(f" ✅ {len(messages)} messages saved\n") + safe_print(f" ✅ {len(messages)} messages saved\n") time.sleep(0.25) conn.close() - print("🎉 Done!") + safe_print("🎉 Done!") if __name__ == "__main__": diff --git a/10ReadPozadavky/PRAVIDELNE_4_StahniPrilohyUlozDoMySQL.py b/10ReadPozadavky/PRAVIDELNE_4_StahniPrilohyUlozDoMySQL.py index 1a7d578..22f5275 100644 --- a/10ReadPozadavky/PRAVIDELNE_4_StahniPrilohyUlozDoMySQL.py +++ b/10ReadPozadavky/PRAVIDELNE_4_StahniPrilohyUlozDoMySQL.py @@ -14,6 +14,36 @@ import pymysql from pathlib import Path from datetime import datetime import time +import sys + +# Force UTF-8 output even under Windows Task Scheduler +import sys +try: + sys.stdout.reconfigure(encoding='utf-8') + sys.stderr.reconfigure(encoding='utf-8') +except AttributeError: + # Python < 3.7 fallback (not needed for you, but safe) + import io + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') + + +# ============================== +# 🛡 SAFE PRINT FOR CP1250 / EMOJI +# ============================== +def safe_print(text: str): + enc = sys.stdout.encoding or "" + if not enc or not enc.lower().startswith("utf"): + # strip emoji + characters outside BMP + text = ''.join(ch for ch in text if ord(ch) < 65536) + + try: + print(text) + except UnicodeEncodeError: + # ASCII fallback + text = ''.join(ch for ch in text if ord(ch) < 128) + print(text) + # ============================== # 🔧 CONFIGURATION @@ -67,6 +97,7 @@ def read_token(p: Path) -> str: tok = p.read_text(encoding="utf-8").strip() return tok.split(" ", 1)[1] if tok.startswith("Bearer ") else tok + # ============================== # 📡 FETCH ATTACHMENTS # ============================== @@ -78,42 +109,40 @@ def fetch_attachments(headers, request_id): } r = requests.post("https://api.medevio.cz/graphql", json=payload, headers=headers, timeout=30) if r.status_code != 200: - print(f"❌ HTTP {r.status_code} for request {request_id}") + safe_print(f"❌ HTTP {r.status_code} for request {request_id}") return [] return r.json().get("data", {}).get("patientRequestMedicalRecords", []) # ============================== -# 💾 SAVE TO MYSQL (clean version) +# 💾 SAVE TO MYSQL # ============================== def insert_download(cur, req_id, a, m, created_date, existing_ids): attachment_id = a.get("id") if attachment_id in existing_ids: - print(f" ⏭️ Already downloaded {attachment_id}") + safe_print(f" ⏭️ Already downloaded {attachment_id}") return False url = m.get("downloadUrl") if not url: - print(" ⚠️ Missing download URL") + safe_print(" ⚠️ Missing download URL") return False filename = extract_filename_from_url(url) - # Download file try: r = requests.get(url, timeout=30) r.raise_for_status() content = r.content except Exception as e: - print(f" ⚠️ Download failed {url}: {e}") + safe_print(f" ⚠️ Download failed {url}: {e}") return False file_size = len(content) attachment_type = a.get("attachmentType") content_type = m.get("contentType") - # 🚨 CLEAN INSERT — no patient_jmeno/no patient_prijmeni cur.execute(""" INSERT INTO medevio_downloads ( request_id, attachment_id, attachment_type, @@ -136,7 +165,7 @@ def insert_download(cur, req_id, a, m, created_date, existing_ids): )) existing_ids.add(attachment_id) - print(f" 💾 Saved {filename} ({file_size/1024:.1f} kB)") + safe_print(f" 💾 Saved {filename} ({file_size/1024:.1f} kB)") return True @@ -152,11 +181,12 @@ def main(): conn = pymysql.connect(**DB_CONFIG) - # Load existing IDs + # Load existing attachments with conn.cursor() as cur: cur.execute("SELECT attachment_id FROM medevio_downloads") existing_ids = {row["attachment_id"] for row in cur.fetchall()} - print(f"✅ {len(existing_ids)} attachments already saved.") + + safe_print(f"✅ {len(existing_ids)} attachments already saved.") # Build query for pozadavky sql = """ @@ -173,7 +203,7 @@ def main(): cur.execute(sql, params) req_rows = cur.fetchall() - print(f"📋 Found {len(req_rows)} pozadavky to process.") + safe_print(f"📋 Found {len(req_rows)} pozadavky to process.") # Process each pozadavek for i, row in enumerate(req_rows, 1): @@ -182,12 +212,12 @@ def main(): jmeno = row.get("pacient_jmeno") or "" created_date = row.get("createdAt") or datetime.now() - print(f"\n[{i}/{len(req_rows)}] 🧾 {prijmeni}, {jmeno} ({req_id})") + safe_print(f"\n[{i}/{len(req_rows)}] 🧾 {prijmeni}, {jmeno} ({req_id})") attachments = fetch_attachments(headers, req_id) if not attachments: - print(" ⚠️ No attachments found") + safe_print(" ⚠️ No attachments found") with conn.cursor() as cur: cur.execute("UPDATE pozadavky SET attachmentsProcessed = NOW() WHERE id = %s", (req_id,)) conn.commit() @@ -199,17 +229,16 @@ def main(): insert_download(cur, req_id, a, m, created_date, existing_ids) conn.commit() - # Mark processed with conn.cursor() as cur: cur.execute("UPDATE pozadavky SET attachmentsProcessed = NOW() WHERE id = %s", (req_id,)) conn.commit() - print(f" ✅ Done ({len(attachments)} attachments)") - + safe_print(f" ✅ Done ({len(attachments)} attachments)") time.sleep(0.3) conn.close() - print("\n🎯 All attachments processed.") + safe_print("\n🎯 All attachments processed.") + # ============================== if __name__ == "__main__": diff --git a/10ReadPozadavky/PRAVIDELNE_5_SaveToFileSystem incremental.py b/10ReadPozadavky/PRAVIDELNE_5_SaveToFileSystem incremental.py index 6d907c4..2492756 100644 --- a/10ReadPozadavky/PRAVIDELNE_5_SaveToFileSystem incremental.py +++ b/10ReadPozadavky/PRAVIDELNE_5_SaveToFileSystem incremental.py @@ -10,6 +10,17 @@ from datetime import datetime import time import sys +# Force UTF-8 output even under Windows Task Scheduler +import sys +try: + sys.stdout.reconfigure(encoding='utf-8') + sys.stderr.reconfigure(encoding='utf-8') +except AttributeError: + # Python < 3.7 fallback (not needed for you, but safe) + import io + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') + # ============================== # 🛡 SAFE PRINT FOR CP1250 / EMOJI # ============================== @@ -92,17 +103,16 @@ safe_print("🔍 Loading metadata from DB (FAST)…") cur_meta.execute(""" SELECT d.id AS download_id, - d.request_id, - d.filename, - d.created_at, - p.updatedAt AS req_updated_at, - p.pacient_jmeno AS jmeno, - p.pacient_prijmeni AS prijmeni, - p.displayTitle -FROM medevio_downloads d -JOIN pozadavky p ON d.request_id = p.id -WHERE d.downloaded_at IS NULL -ORDER BY p.updatedAt DESC + d.request_id, + d.filename, + d.created_at, + p.updatedAt AS req_updated_at, + p.pacient_jmeno AS jmeno, + p.pacient_prijmeni AS prijmeni, + p.displayTitle + FROM medevio_downloads d + JOIN pozadavky p ON d.request_id = p.id + ORDER BY p.updatedAt DESC """) rows = cur_meta.fetchall() diff --git a/10ReadPozadavky/PRAVIDELNE_PLNYSCRIPT.py b/10ReadPozadavky/PRAVIDELNE_PLNYSCRIPT.py index 69063e7..17721b2 100644 --- a/10ReadPozadavky/PRAVIDELNE_PLNYSCRIPT.py +++ b/10ReadPozadavky/PRAVIDELNE_PLNYSCRIPT.py @@ -15,7 +15,7 @@ Spustí všechny PRAVIDELNÉ skripty v daném pořadí: import time, socket for _ in range(30): try: - socket.create_connection(("127.0.0.1", 3307), timeout=3).close() + socket.create_connection(("192.168.1.76", 3307), timeout=3).close() break except OSError: time.sleep(10) diff --git a/10ReadPozadavky/test.py b/10ReadPozadavky/test.py new file mode 100644 index 0000000..60efc51 --- /dev/null +++ b/10ReadPozadavky/test.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Orchestrator for all PRAVIDELNE scripts in exact order. +""" + +import time, socket +for _ in range(30): + try: + socket.create_connection(("192.168.1.76", 3307), timeout=3).close() + break + except OSError: + time.sleep(10) + +import sys +import subprocess +from pathlib import Path +from datetime import datetime + +# ===================================================================== +# Import EXACT Functions.py from: C:\Reporting\Fio\Functions.py +# This bypasses all other Functions.py files in the system. +# ===================================================================== + +import importlib.util + +FUNCTIONS_FILE = Path(r"C:\Reporting\Fio\Functions.py") + +spec = importlib.util.spec_from_file_location("Functions_FIO", FUNCTIONS_FILE) +Functions_FIO = importlib.util.module_from_spec(spec) +sys.modules["Functions_FIO"] = Functions_FIO +spec.loader.exec_module(Functions_FIO) + +# correct WhatsApp function +SendWhatsAppMessage = Functions_FIO.SendWhatsAppMessage + + +# ===================================================================== +# General Orchestrator Settings +# ===================================================================== + +# folder where orchestrator + sub-scripts live +BASE_DIR = Path(__file__).resolve().parent + +SCRIPTS_IN_ORDER = [ + "PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py", + "PRAVIDELNE_1_ReadLast300DonePozadavku.py", + "PRAVIDELNE_2_ReadPoznamky.py", + "PRAVIDELNE_3_StahniKomunikaci.py", + "PRAVIDELNE_4_StahniPrilohyUlozDoMySQL.py", + "PRAVIDELNE_5_SaveToFileSystem incremental.py", +] + +LOG_FILE = BASE_DIR / "PRAVIDELNE_log.txt" + + +# ===================================================================== +# Logging + WhatsApp wrappers +# ===================================================================== + +def log(msg: str): + ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + line = f"[{ts}] {msg}" + print(line) + try: + with LOG_FILE.open("a", encoding="utf-8") as f: + f.write(line + "\n") + except: + pass + + +def whatsapp_notify(text: str): + """WhatsApp message wrapper — never allowed to crash orchestrator""" + try: + SendWhatsAppMessage(text) + except: + pass + + +# ===================================================================== +# Main orchestrator +# ===================================================================== + +def main(): + log("=== START pravidelného běhu ===") + whatsapp_notify("🏁 *PRAVIDELNÉ skripty: START*") + + for script_name in SCRIPTS_IN_ORDER: + script_path = BASE_DIR / script_name + + if not script_path.exists(): + err = f"❌ Skript nenalezen: {script_path}" + log(err) + whatsapp_notify(err) + continue + + log(f"▶ Spouštím: {script_path.name}") + whatsapp_notify(f"▶ *Spouštím:* {script_path.name}") + + try: + result = subprocess.run( + [sys.executable, str(script_path)], + cwd=str(BASE_DIR), + capture_output=True, + text=True, + encoding="utf-8", + errors="ignore", + ) + except Exception as e: + err = f"💥 Chyba při spouštění {script_path.name}: {e}" + log(err) + whatsapp_notify(err) + continue + + # return code + rc_msg = f"↳ {script_path.name} return code: {result.returncode}" + log(rc_msg) + whatsapp_notify(rc_msg) + + # stderr (warnings/errors) + if result.stderr: + err_msg = f"⚠ stderr v {script_path.name}:\n{result.stderr.strip()}" + log(err_msg) + whatsapp_notify(err_msg) + + log("=== KONEC pravidelného běhu ===") + whatsapp_notify("✅ *PRAVIDELNÉ skripty: KONEC*\n") + + +# ===================================================================== +# Entry point +# ===================================================================== + +if __name__ == "__main__": + main()