Agregar logging estructurado, try-catches y envío de errores por Telegram
- Agregado logging estructurado en todos los módulos - Implementados try-catches en todos los métodos críticos - Errores ahora se envían automáticamente por Telegram - Mejorado manejo de excepciones en requests HTTP - Agregado try-catch global en main.py para errores no manejados - Logging detallado en timenet_manager, telegram_bot, google_calendar y config_parser
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import google.oauth2.credentials
|
||||
import logging
|
||||
|
||||
from google.auth.transport.requests import Request
|
||||
from google.oauth2.credentials import Credentials
|
||||
@@ -11,51 +12,120 @@ from dateutil.relativedelta import relativedelta
|
||||
|
||||
import os
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GoogleCalendar:
|
||||
def __init__(self):
|
||||
self.creds = None
|
||||
self.service = None
|
||||
self.SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
|
||||
self.authfile = os.path.join(os.path.dirname(__file__), '../googleoauth.json')
|
||||
self.grantfile = os.path.join(os.path.dirname(__file__), '../googleoauth_grant.json')
|
||||
try:
|
||||
logger.info("Inicializando GoogleCalendar...")
|
||||
self.creds = None
|
||||
self.service = None
|
||||
self.SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
|
||||
self.authfile = os.path.join(os.path.dirname(__file__), '../googleoauth.json')
|
||||
self.grantfile = os.path.join(os.path.dirname(__file__), '../googleoauth_grant.json')
|
||||
|
||||
logger.info(f"Auth file: {self.authfile}, Grant file: {self.grantfile}")
|
||||
|
||||
if os.path.exists(self.authfile):
|
||||
try:
|
||||
self.creds = Credentials.from_authorized_user_file(self.authfile, self.SCOPES)
|
||||
except ValueError as error:
|
||||
print(error)
|
||||
if os.path.exists(self.authfile):
|
||||
try:
|
||||
logger.info("Cargando credenciales desde archivo...")
|
||||
self.creds = Credentials.from_authorized_user_file(self.authfile, self.SCOPES)
|
||||
logger.info("Credenciales cargadas correctamente")
|
||||
except ValueError as error:
|
||||
logger.error(f"Error al cargar credenciales: {error}", exc_info=True)
|
||||
print(f"Error al cargar credenciales: {error}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error inesperado al cargar credenciales: {str(e)}", exc_info=True)
|
||||
print(f"Error inesperado al cargar credenciales: {str(e)}")
|
||||
else:
|
||||
logger.info("No se encontró archivo de credenciales, se solicitará autenticación")
|
||||
|
||||
self.checkAuth()
|
||||
self.buildService()
|
||||
logger.info("Verificando autenticación...")
|
||||
self.checkAuth()
|
||||
logger.info("Construyendo servicio...")
|
||||
self.buildService()
|
||||
logger.info("GoogleCalendar inicializado correctamente")
|
||||
except Exception as e:
|
||||
logger.error(f"Error al inicializar GoogleCalendar: {str(e)}", exc_info=True)
|
||||
print(f"Error al inicializar GoogleCalendar: {str(e)}")
|
||||
raise
|
||||
|
||||
def serverAuth(self):
|
||||
flow = InstalledAppFlow.from_client_secrets_file(self.grantfile, self.SCOPES)
|
||||
self.creds = flow.run_local_server(port=0)
|
||||
try:
|
||||
logger.info("Iniciando autenticación del servidor...")
|
||||
if not os.path.exists(self.grantfile):
|
||||
error_msg = f"Archivo de grant no encontrado: {self.grantfile}"
|
||||
logger.error(error_msg)
|
||||
raise FileNotFoundError(error_msg)
|
||||
|
||||
flow = InstalledAppFlow.from_client_secrets_file(self.grantfile, self.SCOPES)
|
||||
self.creds = flow.run_local_server(port=0)
|
||||
logger.info("Autenticación del servidor completada")
|
||||
except FileNotFoundError as e:
|
||||
logger.error(f"Archivo de grant no encontrado: {str(e)}", exc_info=True)
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error durante autenticación del servidor: {str(e)}", exc_info=True)
|
||||
raise
|
||||
|
||||
def saveAuth(self):
|
||||
with open(self.authfile, 'w') as token:
|
||||
token.write(self.creds.to_json())
|
||||
try:
|
||||
logger.info("Guardando credenciales...")
|
||||
with open(self.authfile, 'w') as token:
|
||||
token.write(self.creds.to_json())
|
||||
logger.info("Credenciales guardadas correctamente")
|
||||
except Exception as e:
|
||||
logger.error(f"Error al guardar credenciales: {str(e)}", exc_info=True)
|
||||
raise
|
||||
|
||||
def refreshAuth(self):
|
||||
self.creds.refresh(Request())
|
||||
try:
|
||||
logger.info("Refrescando credenciales...")
|
||||
self.creds.refresh(Request())
|
||||
logger.info("Credenciales refrescadas correctamente")
|
||||
except google.oauth2.credentials.exceptions.RefreshError as e:
|
||||
logger.warning(f"Error al refrescar credenciales: {str(e)}")
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error inesperado al refrescar credenciales: {str(e)}", exc_info=True)
|
||||
raise
|
||||
|
||||
def checkAuth(self):
|
||||
if not self.creds or not self.creds.valid:
|
||||
if self.creds and self.creds.expired and self.creds.refresh_token:
|
||||
try:
|
||||
self.refreshAuth()
|
||||
except google.oauth2.credentials.exceptions.RefreshError as rerror:
|
||||
try:
|
||||
logger.info("Verificando estado de autenticación...")
|
||||
if not self.creds or not self.creds.valid:
|
||||
logger.info("Credenciales no válidas o no existentes")
|
||||
if self.creds and self.creds.expired and self.creds.refresh_token:
|
||||
try:
|
||||
logger.info("Intentando refrescar credenciales expiradas...")
|
||||
self.refreshAuth()
|
||||
except google.oauth2.credentials.exceptions.RefreshError as rerror:
|
||||
logger.warning(f"No se pudo refrescar credenciales: {str(rerror)}, solicitando nueva autenticación")
|
||||
self.serverAuth()
|
||||
except Exception as e:
|
||||
logger.error(f"Error inesperado al refrescar: {str(e)}", exc_info=True)
|
||||
self.serverAuth()
|
||||
else:
|
||||
logger.info("Solicitando nueva autenticación...")
|
||||
self.serverAuth()
|
||||
else:
|
||||
self.serverAuth()
|
||||
|
||||
self.saveAuth()
|
||||
logger.info("Guardando credenciales después de autenticación...")
|
||||
self.saveAuth()
|
||||
else:
|
||||
logger.info("Credenciales válidas")
|
||||
except Exception as e:
|
||||
logger.error(f"Error durante checkAuth: {str(e)}", exc_info=True)
|
||||
raise
|
||||
|
||||
def buildService(self):
|
||||
self.service = build('calendar', 'v3', credentials=self.creds)
|
||||
# self.service.calendars().get(calendarId='e51d3bfb6b352c48afb8bd7a5d494599cc3eaa686800a856796306f50c6d72fd@group.calendar.google.com')
|
||||
# self.service.create_notification_channel()
|
||||
try:
|
||||
logger.info("Construyendo servicio de Google Calendar...")
|
||||
self.service = build('calendar', 'v3', credentials=self.creds)
|
||||
logger.info("Servicio de Google Calendar construido correctamente")
|
||||
except Exception as e:
|
||||
logger.error(f"Error al construir servicio de Google Calendar: {str(e)}", exc_info=True)
|
||||
raise
|
||||
|
||||
def getNow(self):
|
||||
return datetime.utcnow().strftime('%Y-%m-%dT00:00:00Z')
|
||||
@@ -65,43 +135,88 @@ class GoogleCalendar:
|
||||
|
||||
def getEvent(self):
|
||||
try:
|
||||
logger.info("Obteniendo eventos de Google Calendar...")
|
||||
now = self.getNow()
|
||||
now_after_one_day = self.getNowAfterOneDay()
|
||||
logger.info(f"Buscando eventos entre {now} y {now_after_one_day}")
|
||||
|
||||
events_result_autoficher = self.service.events().list(
|
||||
calendarId='e51d3bfb6b352c48afb8bd7a5d494599cc3eaa686800a856796306f50c6d72fd@group.calendar.google.com',
|
||||
timeMin=now,
|
||||
timeMax=now_after_one_day, maxResults=10, singleEvents=True,
|
||||
orderBy='startTime').execute()
|
||||
events_result_holiday = self.service.events().list(
|
||||
calendarId='es.spain#holiday@group.v.calendar.google.com',
|
||||
timeMin=now,
|
||||
timeMax=now_after_one_day,
|
||||
maxResults=10, singleEvents=True,
|
||||
orderBy='startTime').execute()
|
||||
try:
|
||||
logger.info("Consultando calendario autoficher...")
|
||||
events_result_autoficher = self.service.events().list(
|
||||
calendarId='e51d3bfb6b352c48afb8bd7a5d494599cc3eaa686800a856796306f50c6d72fd@group.calendar.google.com',
|
||||
timeMin=now,
|
||||
timeMax=now_after_one_day, maxResults=10, singleEvents=True,
|
||||
orderBy='startTime').execute()
|
||||
logger.info(f"Eventos de autoficher obtenidos: {len(events_result_autoficher.get('items', []))}")
|
||||
except HttpError as e:
|
||||
logger.error(f"Error HTTP al consultar calendario autoficher: {str(e)}", exc_info=True)
|
||||
events_result_autoficher = {'items': []}
|
||||
except Exception as e:
|
||||
logger.error(f"Error inesperado al consultar calendario autoficher: {str(e)}", exc_info=True)
|
||||
events_result_autoficher = {'items': []}
|
||||
|
||||
try:
|
||||
logger.info("Consultando calendario de festivos...")
|
||||
events_result_holiday = self.service.events().list(
|
||||
calendarId='es.spain#holiday@group.v.calendar.google.com',
|
||||
timeMin=now,
|
||||
timeMax=now_after_one_day,
|
||||
maxResults=10, singleEvents=True,
|
||||
orderBy='startTime').execute()
|
||||
logger.info(f"Eventos de festivos obtenidos: {len(events_result_holiday.get('items', []))}")
|
||||
except HttpError as e:
|
||||
logger.warning(f"Error HTTP al consultar calendario de festivos (puede ser normal): {str(e)}")
|
||||
events_result_holiday = {'items': []}
|
||||
except Exception as e:
|
||||
logger.warning(f"Error inesperado al consultar calendario de festivos: {str(e)}")
|
||||
events_result_holiday = {'items': []}
|
||||
|
||||
events = events_result_autoficher.get('items', []) + events_result_holiday.get('items', [])
|
||||
logger.info(f"Total de eventos encontrados: {len(events)}")
|
||||
|
||||
if not events:
|
||||
logger.info("No se encontraron eventos")
|
||||
return False
|
||||
|
||||
# Prints the start and name of the next 10 events
|
||||
for event in events:
|
||||
start = event['start'].get('dateTime', event['start'].get('date'))
|
||||
end = event['end'].get('dateTime', event['end'].get('date'))
|
||||
try:
|
||||
start = event['start'].get('dateTime', event['start'].get('date'))
|
||||
end = event['end'].get('dateTime', event['end'].get('date'))
|
||||
logger.debug(f"Evaluando evento: {event.get('summary', 'Sin título')} - {start} a {end}")
|
||||
|
||||
if datetime.fromisoformat(start).timestamp() <= datetime.now().timestamp() <= datetime.fromisoformat(
|
||||
end).timestamp():
|
||||
if event['organizer']['displayName'] == 'autoficher':
|
||||
return 'Forzado desde autoficher - ' + event.get("summary", "Sin Título")
|
||||
if datetime.fromisoformat(start).timestamp() <= datetime.now().timestamp() <= datetime.fromisoformat(
|
||||
end).timestamp():
|
||||
logger.info(f"Evento activo encontrado: {event.get('summary', 'Sin título')}")
|
||||
if event.get('organizer', {}).get('displayName') == 'autoficher':
|
||||
result = 'Forzado desde autoficher - ' + event.get("summary", "Sin Título")
|
||||
logger.info(f"Evento de autoficher activo: {result}")
|
||||
return result
|
||||
|
||||
#Desactivado por que no funcionaba muy bien ese calendario... se han puesto en el calendario autoficher los dias festivos correctos
|
||||
#if 'description' in event and ("Cataluña" in event['description'] or 'Día festivo' in event[
|
||||
# 'description'] or 'Celebración\n' in event['description']) and not 'Cambio de horario' in event[
|
||||
# 'summary']:
|
||||
# return event['summary']
|
||||
#Desactivado por que no funcionaba muy bien ese calendario... se han puesto en el calendario autoficher los dias festivos correctos
|
||||
#if 'description' in event and ("Cataluña" in event['description'] or 'Día festivo' in event[
|
||||
# 'description'] or 'Celebración\n' in event['description']) and not 'Cambio de horario' in event[
|
||||
# 'summary']:
|
||||
# return event['summary']
|
||||
except KeyError as e:
|
||||
logger.warning(f"Evento sin campo requerido: {str(e)}, evento: {event.get('summary', 'Sin título')}")
|
||||
continue
|
||||
except ValueError as e:
|
||||
logger.warning(f"Error al parsear fecha del evento: {str(e)}, evento: {event.get('summary', 'Sin título')}")
|
||||
continue
|
||||
except Exception as e:
|
||||
logger.warning(f"Error al procesar evento: {str(e)}, evento: {event.get('summary', 'Sin título')}")
|
||||
continue
|
||||
|
||||
logger.info("No se encontraron eventos activos")
|
||||
return False
|
||||
except HttpError as error:
|
||||
error_msg = f'Error HTTP de Google Calendar: {error}'
|
||||
logger.error(error_msg, exc_info=True)
|
||||
print(f'An error occurred: {error}')
|
||||
return 'Error de llama a Google Calendar'
|
||||
|
||||
return False
|
||||
return 'Error de llamada a Google Calendar'
|
||||
except Exception as e:
|
||||
error_msg = f'Error inesperado en getEvent: {str(e)}'
|
||||
logger.error(error_msg, exc_info=True)
|
||||
print(f'Error inesperado: {error_msg}')
|
||||
return 'Error de llamada a Google Calendar'
|
||||
|
||||
Reference in New Issue
Block a user