utn-frm-si/reservas

View on GitHub
app_reservas/adapters/google_calendar.py

Summary

Maintainability
A
2 hrs
Test Coverage
# coding=utf-8

from apiclient import discovery
from datetime import datetime
from dateutil import parser
from httplib2 import ServerNotFoundError

from reservas.settings.base import GOOGLE_CALENDAR_TOKEN


def crear_servicio():
    """Construye un servicio para comunicarse con la API de Google Calendar.

    Returns
    -------
    object
        Objeto que proporciona el servicio de comunicación con la API de Google Calendar.
    """
    return discovery.build('calendar', 'v3', developerKey=GOOGLE_CALENDAR_TOKEN)


def generar_lista_eventos(calendar_id, limite_anio_siguiente=True):
    """Genera el listado de eventos de un calendario específico de Google Calendar.

    Retorna el listado de eventos de un calendario específico de Google Calendar, con la
    información requerida por la aplicación. En caso de que se produzca algún problema de conexión
    a Google Calendar, no se retorna ningún evento.

    Parameters
    ----------
    calendar_id : str
        ID de calendario de Google Calendar.
    limite_anio_siguiente : bool, optional
        Variable que especifica que los eventos a obtener comprendan únicamente a aquellos del año
        actual y el año próximo. En caso de ser falso, se obtienen todos los eventos del
        calendario, sin considerar la fecha de los mismos. Por defecto, es verdadero.

    Returns
    -------
    list of dicts
        Lista de eventos, organizados como diccionarios.
    """
    lista_eventos = []

    # Obtiene de Google Calendar los eventos del calendario.
    eventos = obtener_eventos(calendar_id, limite_anio_siguiente)

    for evento in eventos:
        inicio = parser.parse(
            evento['start'].get(
                'dateTime',
                evento['start'].get('date')
            )
        )
        fin = parser.parse(
            evento['end'].get(
                'dateTime',
                evento['end'].get('date')
            )
        )

        lista_eventos.append(
            {
                'titulo': evento.get('summary', u'Evento sin título'),
                'inicio': inicio,
                'fin': fin,
                'inicio_str': inicio.strftime("%Y-%m-%dT%H:%M:%S"),
                'fin_str': fin.strftime("%Y-%m-%dT%H:%M:%S"),
            }
        )

    return lista_eventos


def obtener_eventos(calendar_id, limite_anio_siguiente=True):
    """Obtiene de Google Calendar los eventos de un calendario específico.

    Retorna los eventos de un calendario específico, solicitados a la API de Google Calendar. En
    caso de que se produzca algún problema de conexión a Google Calendar, no se retorna ningún
    evento.

    Parameters
    ----------
    calendar_id : str
        ID de calendario de Google Calendar.
    limite_anio_siguiente : bool, optional
        Variable que especifica que los eventos a obtener comprendan únicamente a aquellos del año
        actual y el año próximo. En caso de ser falso, se obtienen todos los eventos del
        calendario, sin considerar la fecha de los mismos. Por defecto, es verdadero.

    Returns
    -------
    list of dicts
        Lista de eventos, organizados como diccionarios.
    """
    service = crear_servicio()

    primer_dia_anio_actual = None
    primer_dia_anio_subsiguiente = None
    if limite_anio_siguiente:
        # Obtiene únicamente los eventos del año actual y el siguiente.
        primer_dia_anio_actual = datetime(
            datetime.today().year,
            1,
            1,
        ).isoformat('T') + 'Z'
        primer_dia_anio_subsiguiente = datetime(
            datetime.today().year + 2,
            1,
            1,
        ).isoformat('T') + 'Z'

    eventos = []
    page_token = None

    while True:
        try:
            # Realiza la petición de eventos del calendario a Google Calendar.
            events_result = service.events().list(
                calendarId=calendar_id,
                maxResults=2500,
                singleEvents=True,
                timeMin=primer_dia_anio_actual,
                timeMax=primer_dia_anio_subsiguiente,
                pageToken=page_token,
                orderBy='startTime'
            ).execute()
        except ServerNotFoundError:
            # En caso de problemas de conexión a Google Calendar, no se retorna ningún evento.
            eventos = []
            break

        # Añade los eventos obtenidos de la petición al listado de eventos.
        eventos.extend(events_result.get('items', []))

        # Se recupera el token de página retornado por la petición a Google Calendar. Este token,
        # en caso de estar especificado, indica que se debe realizar otra petición para obtener una
        # nueva página de eventos para el calendario.
        page_token = events_result.get('nextPageToken')
        # Si no se obtuvo token de página, se ha finalizado con la obtención de eventos.
        if not page_token:
            break

    return eventos