feat: Implement initial project setup including calendar synchronization scripts, dependency management, and Docker configuration.
This commit is contained in:
102
sync_calendar.py
Normal file
102
sync_calendar.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import requests
|
||||
import caldav
|
||||
from caldav.elements import dav, cdav
|
||||
from datetime import datetime
|
||||
import os
|
||||
import time
|
||||
|
||||
# --- CONFIGURACIÓN ---
|
||||
# Default to 5 minutes (300 seconds)
|
||||
SYNC_FREQUENCY = int(os.getenv("SYNC_FREQUENCY", 300))
|
||||
|
||||
# Tu URL de Outlook
|
||||
ICS_URL = os.getenv("ICS_URL")
|
||||
|
||||
# Tu Baïkal
|
||||
BAIKAL_URL = os.getenv("BAIKAL_URL")
|
||||
BAIKAL_USER = os.getenv("BAIKAL_USER")
|
||||
BAIKAL_PASS = os.getenv("BAIKAL_PASS")
|
||||
|
||||
# Headers para parecer un navegador real y evitar 'Connection Reset'
|
||||
HEADERS = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Unraid-Sync/1.0"
|
||||
}
|
||||
|
||||
def sync():
|
||||
if not all([ICS_URL, BAIKAL_URL, BAIKAL_USER, BAIKAL_PASS]):
|
||||
print(f"[{datetime.now()}] !!! Error: Faltan variables de entorno. Asegúrate de configurar ICS_URL, BAIKAL_URL, BAIKAL_USER y BAIKAL_PASS.")
|
||||
return
|
||||
|
||||
print(f"[{datetime.now()}] Iniciando sincronización...")
|
||||
|
||||
# 1. Descargar ICS de Outlook
|
||||
print("-> Descargando calendario de Outlook...")
|
||||
try:
|
||||
response = requests.get(ICS_URL, headers=HEADERS, timeout=30)
|
||||
response.raise_for_status()
|
||||
ics_data = response.text
|
||||
print(f"-> Descarga exitosa ({len(ics_data)} bytes).")
|
||||
except Exception as e:
|
||||
print(f"!!! Error descargando Outlook: {e}")
|
||||
return
|
||||
|
||||
# 2. Conectar a Baïkal
|
||||
print("-> Conectando a Baïkal...")
|
||||
try:
|
||||
client = caldav.DAVClient(
|
||||
url=BAIKAL_URL,
|
||||
username=BAIKAL_USER,
|
||||
password=BAIKAL_PASS,
|
||||
headers=HEADERS, # Clave para evitar el bloqueo
|
||||
ssl_verify_cert=True # Cambiar a False si tienes problemas de certificado SSL auto-firmado
|
||||
)
|
||||
principal = client.principal()
|
||||
calendars = principal.calendars()
|
||||
|
||||
# Buscar el calendario correcto o usar el primero que encuentre en esa URL
|
||||
if calendars:
|
||||
calendar = calendars[0]
|
||||
print(f"-> Calendario encontrado: {calendar}")
|
||||
else:
|
||||
print("!!! No se encontró ningún calendario en esa URL.")
|
||||
return
|
||||
|
||||
# 3. Importar eventos
|
||||
print("-> Procesando archivo ICS...")
|
||||
from icalendar import Calendar
|
||||
cal = Calendar.from_ical(ics_data)
|
||||
|
||||
events = cal.walk('vevent')
|
||||
total_events = len(events)
|
||||
print(f"-> Encontrados {total_events} eventos.")
|
||||
|
||||
success_count = 0
|
||||
error_count = 0
|
||||
|
||||
for i, component in enumerate(events, 1):
|
||||
try:
|
||||
# Intentamos pasar el string decodificado
|
||||
calendar.add_event(component.to_ical().decode('utf-8'))
|
||||
success_count += 1
|
||||
except Exception as ev_err:
|
||||
error_count += 1
|
||||
# Solo imprimimos los primeros 5 errores para no saturar
|
||||
if error_count <= 5:
|
||||
summary = component.get('summary', 'sin titulo')
|
||||
print(f"!!! Error ({i}/{total_events}) '{summary}': {ev_err}")
|
||||
|
||||
# Print progress every 50 events
|
||||
if i % 50 == 0:
|
||||
print(f" Procesados {i}/{total_events} (Exitos: {success_count}, Errores: {error_count})")
|
||||
|
||||
print(f"-> ¡Sincronización finalizada! Éxitos: {success_count}, Errores: {error_count}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"!!! Error en Baïkal: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"Iniciando servicio de sincronización. Frecuencia: {SYNC_FREQUENCY} segundos.")
|
||||
while True:
|
||||
sync()
|
||||
print(f"[{datetime.now()}] Durmiendo {SYNC_FREQUENCY} segundos...")
|
||||
time.sleep(SYNC_FREQUENCY)
|
||||
Reference in New Issue
Block a user