Files
citas-getter/book_at_midnight.py
cc-ultrav-1 3c960c1ce5 Add booking artifacts, API data, and catalog files
- booking_log.txt: midnight run results (cita booked at 15:15, 3347ms RTT)
- fire_at_midnight.py: original midnight launch script
- book_cita.sh / book_at_midnight.py: booking shell scripts
- fetch_final.py / fetch_cita.sh: API fetch utilities
- services_full.js, controllers_full.js, app_real2.js: frontend source
- services_real.js, url.js: API endpoint references
- tipos_doc.json: document type data from API
- benchmark_results.json: server load profiling results
2026-10-04 02:40:30 +02:00

194 lines
6.3 KiB
Python

#!/usr/bin/env python3
"""
Precision midnight booking for CitaPrevia Portugal Tardes (cola I).
Runs in background, pre-establishes TLS at 23:59:55, fires at 00:00:00.
User: Humberto Normey Gomez, NIE X2491454W
Service: S (SAIC), Cola: I (Portugal Tardes, Padron), Fecha: 19-10-2026
"""
import http.client
import ssl
import time
import json
import sys
from datetime import datetime
# ── User Data ──────────────────────────────────────────────
SERVICIO = "S"
COLA = "I"
FECHA = "19-10-2026"
DOC = "X2491454W"
NOMBRE = "Humberto"
APE1 = "Normey"
APE2 = "Gomez"
TIPO = "2" # NIE
TEL = "687915599"
EMAIL = "hj@normey.net"
IMPUESTOS = "N"
COMENTARIO = "Solicitud de Alta en el Padrón"
IP = "0.0.0.0"
# Slots in priority order: 16:00 first, then earliest first
HORAS = ["16:00", "14:30", "14:45", "15:00", "15:15", "15:30", "15:45", "16:15", "16:30"]
HOST = "webservices.alicante.es"
PORT = 443
PATH = "/WsCitaPreviaPublic-RESTWebService-context-root/rest/1/ScCitaVo1"
CT = "application/vnd.oracle.adf.action+json"
# ── Target: Oct 4, 2026 00:00:00 CEST ─────────────────────
target_ts = datetime(2026, 10, 4, 0, 0, 0).timestamp()
preconnect_ts = target_ts - 5 # pre-establish TLS 5s before midnight
def log(msg):
ts = datetime.now().strftime('%H:%M:%S.%f')[:-3]
print(f"[{ts}] {msg}", flush=True)
def build_body(hora, motivo_ts):
data = {
"name": "insertarCitaPrevia",
"parameters": [
{"servicio": SERVICIO},
{"cola": COLA},
{"fecha": FECHA},
{"hora": hora},
{"documento": DOC},
{"ip": IP},
{"nombre": NOMBRE},
{"apellido1": APE1},
{"apellido2": APE2},
{"tipo": TIPO},
{"telefono": TEL},
{"email": EMAIL},
{"impuestos": IMPUESTOS},
{"motivo": f"{motivo_ts} {COMENTARIO}"},
{"procedencia":"NULO"}
]
}
return json.dumps(data, separators=(',', ':'))
def build_check_body(hora):
"""getHorasCitas to check availability"""
data = {
"name": "getHorasCitas",
"parameters": [
{"servicio": SERVICIO},
{"cola": COLA},
{"fecha": FECHA}
]
}
return json.dumps(data, separators=(',', ':'))
# ── Main ───────────────────────────────────────────────────
log("Starting midnight booking bot")
log(f"Target midnight: {datetime.fromtimestamp(target_ts)}")
log(f"Pre-connect time: {datetime.fromtimestamp(preconnect_ts)}")
# Phase 1: Sleep until 5 seconds before midnight
now = time.time()
if now < preconnect_ts:
sleep_dur = preconnect_ts - now
log(f"Sleeping {sleep_dur:.0f}s until pre-connect phase...")
time.sleep(sleep_dur)
# Phase 2: Pre-establish TLS connection
log("Pre-establishing TLS connection...")
context = ssl.create_default_context()
conn = http.client.HTTPSConnection(HOST, PORT, context=context, timeout=12)
try:
conn.connect()
log("TLS connection established ✓")
except Exception as e:
log(f"Connection failed: {e}")
log("Will retry at midnight...")
conn = None
# Phase 3: Busy-wait until midnight
log("Entering busy-wait until midnight...")
while time.time() < target_ts:
pass
# Phase 4: At midnight — fire requests
log("=== MIDNIGHT! Firing booking requests ===")
success = False
for hora in HORAS:
motivo_ts = datetime.now().strftime('%H:%M:%S')
body = build_body(hora, motivo_ts)
if conn is None:
# Fallback: re-establish connection
log(f"Reconnecting for {hora}...")
context = ssl.create_default_context()
conn = http.client.HTTPSConnection(HOST, PORT, context=context, timeout=12)
conn.connect()
headers = {
"Content-Type": CT,
"Origin": "https://citaprevia.alicante.es",
"Referer": "https://citaprevia.alicante.es/CitaPrevia/",
}
log(f"→ Attempting: {FECHA} at {hora}")
try:
conn.request("POST", PATH, body=body, headers=headers)
response = conn.getresponse()
raw = response.read().decode('utf-8')
# Parse response
try:
resp_json = json.loads(raw)
result = resp_json.get('result', '')
except:
result = raw[:200] if raw else "(empty response)"
log(f" Response ({response.status}): {result}")
if result == "Cita insertada":
log(f"")
log(f"*** ✅ CITA BOOKED! ***")
log(f" Servicio: {SERVICIO} (SAC/SAIC)")
log(f" Cola: {COLA} (C/PORTUGAL 17 TARDE - PADRÓN)")
log(f" Fecha: {FECHA}")
log(f" Hora: {hora}")
log(f" Nombre: {NOMBRE} {APE1} {APE2}")
log(f" NIE: {DOC}")
log(f" Motivo: {motivo_ts} {COMENTARIO}")
log(f"")
log(f" Verify: getHorasCitas for {FECHA} — slot {hora} should be gone")
log(f" View cita: https://citaprevia.alicante.es/CitaPrevia/#/verCita/{DOC}/{SERVICIO}{COLA}{DOC}/OLD")
success = True
break
elif result == "Fecha posterior al limite permitido":
log(f" → Timing issue (server clock?). Retrying immediately...")
time.sleep(0.05)
elif result == "Hora no permitida":
log(f" → Slot taken or invalid. Trying next...")
else:
log(f" → Unexpected response. Stopping.")
break
except Exception as e:
log(f" → Error: {e}")
# Try re-establishing connection
try:
conn.close()
context = ssl.create_default_context()
conn = http.client.HTTPSConnection(HOST, PORT, context=context, timeout=12)
conn.connect()
log(" Connection re-established.")
except:
log(" Failed to re-establish connection.")
break
if not success:
log("")
log("❌ All slots failed. The 9 slots at Oct 19 may have been grabbed by bots.")
log(" Check getHorasCitas manually for remaining availability.")
log("Script finished.")