notebookvb
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Zapise poznamku lekare do Medevio kalendare (color=CHARCOAL).
|
||||
|
||||
Hlavni funkce: `zapis_poznamku()` - bere parametry:
|
||||
calendar_id UUID kalendare (Vlado / manzelka / ...)
|
||||
den date nebo str 'YYYY-MM-DD'
|
||||
cas str 'HH:MM' nebo time
|
||||
trvani_min int - delka v minutach
|
||||
poznamka str - text
|
||||
perioda None | str - "DAILY", "WEEKDAYS", atd. (zatim NotImplemented)
|
||||
color ECRFIconColor enum, default CHARCOAL
|
||||
clinic_slug default mudr-buzalkova
|
||||
|
||||
Vrati id vytvorene rezervace (str).
|
||||
|
||||
CLI:
|
||||
python zapis_poznamky.py --den 2026-06-03 --cas 09:00 --trvani 5 --poznamka "Text"
|
||||
python zapis_poznamky.py --den 2026-06-03 --cas 09:00 --trvani 5 --poznamka "Text" --kalendar manzelka
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from datetime import datetime, date, time as dtime, timedelta
|
||||
|
||||
import requests
|
||||
from dateutil import tz
|
||||
|
||||
try:
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
GRAPHQL_URL = "https://api.medevio.cz/graphql"
|
||||
CLINIC_SLUG = "mudr-buzalkova"
|
||||
PRAGUE_TZ = tz.gettz("Europe/Prague")
|
||||
|
||||
# Pojmenovane kalendare - viz pamet project-medevio-kalendar
|
||||
CALENDARS = {
|
||||
"vlado": "b6555c7e-4e95-4657-b441-87c2c9a7b2ca",
|
||||
"manzelka": "144c4e12-347c-49ca-9ec0-8ca965a4470d",
|
||||
}
|
||||
DEFAULT_CALENDAR = "vlado"
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent
|
||||
TOKEN_PATH = BASE_DIR / "token.txt"
|
||||
DEBUG_DIR = BASE_DIR / "debug"
|
||||
|
||||
MUTATION = """mutation CreateReservation_MakeReservationByDoctor(
|
||||
$clinicSlug: String!,
|
||||
$color: ECRFIconColor,
|
||||
$note: String!,
|
||||
$timeSlotInput: TimeSlotInput!
|
||||
) {
|
||||
reservation: makeReservationByDoctor(
|
||||
clinicSlug: $clinicSlug
|
||||
color: $color
|
||||
note: $note
|
||||
timeSlotInput: $timeSlotInput
|
||||
) {
|
||||
id
|
||||
__typename
|
||||
}
|
||||
}"""
|
||||
|
||||
|
||||
def _load_token() -> str:
|
||||
token = TOKEN_PATH.read_text(encoding="utf-8").strip()
|
||||
if token.startswith("Bearer "):
|
||||
token = token.split(" ", 1)[1]
|
||||
return token
|
||||
|
||||
|
||||
def _headers() -> dict:
|
||||
return {
|
||||
"content-type": "application/json",
|
||||
"authorization": f"Bearer {_load_token()}",
|
||||
"origin": "https://my.medevio.cz",
|
||||
"referer": "https://my.medevio.cz/",
|
||||
}
|
||||
|
||||
|
||||
def _to_utc_iso(dt: datetime) -> str:
|
||||
if dt.tzinfo is None:
|
||||
dt = dt.replace(tzinfo=PRAGUE_TZ)
|
||||
return dt.astimezone(tz.UTC).strftime("%Y-%m-%dT%H:%M:%S.000Z")
|
||||
|
||||
|
||||
def _resolve_calendar(calendar) -> str:
|
||||
"""Prijme UUID nebo nazev ('vlado', 'manzelka'). Vrati UUID."""
|
||||
if calendar in CALENDARS:
|
||||
return CALENDARS[calendar]
|
||||
if isinstance(calendar, str) and len(calendar) == 36 and calendar.count("-") == 4:
|
||||
return calendar
|
||||
raise ValueError(f"Neznamy kalendar: {calendar!r}. Pouzij UUID nebo jeden z {list(CALENDARS)}.")
|
||||
|
||||
|
||||
def _resolve_day(den) -> date:
|
||||
if isinstance(den, date) and not isinstance(den, datetime):
|
||||
return den
|
||||
if isinstance(den, datetime):
|
||||
return den.date()
|
||||
return datetime.strptime(str(den), "%Y-%m-%d").date()
|
||||
|
||||
|
||||
def _resolve_time(cas) -> dtime:
|
||||
if isinstance(cas, dtime):
|
||||
return cas
|
||||
return datetime.strptime(str(cas), "%H:%M").time()
|
||||
|
||||
|
||||
def zapis_poznamku(
|
||||
calendar: str = DEFAULT_CALENDAR,
|
||||
den=None,
|
||||
cas=None,
|
||||
trvani_min: int = 5,
|
||||
poznamka: str = "",
|
||||
perioda: str | None = None,
|
||||
color: str = "CHARCOAL",
|
||||
clinic_slug: str = CLINIC_SLUG,
|
||||
save_debug: bool = True,
|
||||
) -> str:
|
||||
"""Vytvori poznamku lekare v Medevio kalendari. Vraci id rezervace."""
|
||||
if perioda is not None:
|
||||
raise NotImplementedError(
|
||||
"Periodicita zatim neni implementovana - neznam format payloadu. "
|
||||
"Zachyt jednu opakujici se rezervaci pres Claude in Chrome a doplnime."
|
||||
)
|
||||
if den is None or cas is None:
|
||||
raise ValueError("Musis zadat 'den' a 'cas'.")
|
||||
|
||||
calendar_id = _resolve_calendar(calendar)
|
||||
d = _resolve_day(den)
|
||||
t = _resolve_time(cas)
|
||||
start_dt = datetime.combine(d, t).replace(tzinfo=PRAGUE_TZ)
|
||||
end_dt = start_dt + timedelta(minutes=int(trvani_min))
|
||||
|
||||
payload = {
|
||||
"operationName": "CreateReservation_MakeReservationByDoctor",
|
||||
"variables": {
|
||||
"clinicSlug": clinic_slug,
|
||||
"color": color,
|
||||
"note": poznamka,
|
||||
"timeSlotInput": {
|
||||
"calendarId": calendar_id,
|
||||
"start": _to_utc_iso(start_dt),
|
||||
"end": _to_utc_iso(end_dt),
|
||||
},
|
||||
},
|
||||
"query": MUTATION,
|
||||
}
|
||||
|
||||
r = requests.post(GRAPHQL_URL, headers=_headers(), data=json.dumps(payload), timeout=30)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
|
||||
if save_debug:
|
||||
DEBUG_DIR.mkdir(exist_ok=True)
|
||||
debug_path = DEBUG_DIR / f"poznamka_{datetime.now():%Y%m%d_%H%M%S}.json"
|
||||
debug_path.write_text(
|
||||
json.dumps({"request": payload["variables"], "response": data}, ensure_ascii=False, indent=2),
|
||||
encoding="utf-8",
|
||||
)
|
||||
print(f"[debug] {debug_path}")
|
||||
|
||||
if "errors" in data:
|
||||
raise RuntimeError(f"GraphQL error: {data['errors']}")
|
||||
|
||||
res_id = data["data"]["reservation"]["id"]
|
||||
print(f"OK: {d} {t:%H:%M} +{trvani_min}min '{poznamka}' -> {res_id}")
|
||||
return res_id
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Zapis poznamku lekare do Medevio kalendare.")
|
||||
ap.add_argument("--kalendar", default=DEFAULT_CALENDAR,
|
||||
help=f"Jmeno ({'/'.join(CALENDARS)}) nebo UUID. Default '{DEFAULT_CALENDAR}'.")
|
||||
ap.add_argument("--den", required=True, help="YYYY-MM-DD")
|
||||
ap.add_argument("--cas", required=True, help="HH:MM (lokalni cas Europe/Prague)")
|
||||
ap.add_argument("--trvani", type=int, default=5, help="delka v minutach (default 5)")
|
||||
ap.add_argument("--poznamka", required=True, help="text poznamky")
|
||||
ap.add_argument("--perioda", default=None,
|
||||
help="opakovani (zatim NotImplemented)")
|
||||
ap.add_argument("--color", default="CHARCOAL")
|
||||
args = ap.parse_args()
|
||||
|
||||
zapis_poznamku(
|
||||
calendar=args.kalendar,
|
||||
den=args.den,
|
||||
cas=args.cas,
|
||||
trvani_min=args.trvani,
|
||||
poznamka=args.poznamka,
|
||||
perioda=args.perioda,
|
||||
color=args.color,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user