Personal Website

My Web: MindEchoes.com

Monday, April 26, 2010

Google Calendar API

Haciendo un Plugin (que todavía no esta terminado) para PyTv, me quise poner a usar la API de Google para Calendar, y aunque tiene varios ejemplos, ahí determinadas cosas para cuando se quiere trabajar con un Calendario que no sea el default que me costo encontrar, así que hago este Post:

La instalación de la librería se puede consultar en: Installing the Google Data Library

Los pasos a seguir van a ser los siguientes:
  1. Agregar los módulos necesarios
  2. Conectarse a Calendar con una cuenta de usuario.
  3. Crear un Nuevo Calendario.
  4. Mostrar los distintos Calendarios del Usuario y tomar el ID de uno especifico.
  5. Crear eventos en ese Calendario especifico
  6. Listar la información de todos los eventos entre determinadas fechas del Calendario creado.
1) Primero veamos cuales son los módulos que vamos a necesitar para el ejemplo:

import time

import gdata.calendar.service
import gdata.service
import atom.service
import gdata.calendar

2) Ahora creamos una Clase "MyCalendar" y realizamos la conexión con Calendar en el constructor:

class MyCalendar(object):

    def __init__(self):
        calendar_service = gdata.calendar.service.CalendarService()
        calendar_service.email = 'diego.sarmentero@gmail.com'
        calendar_service.password = 'PASSWORD'
        calendar_service.ProgrammaticLogin()

        self.execute(calendar_service)

Hay distintas formas de realizar la conexión como puede verse en la documentación, esta es una de esas.

3) Creando un Nuevo Calendario:

def create_calendar(self, calendar_service):
    #Crear Calendario
    calendar = gdata.calendar.CalendarListEntry()
    #Configurar Titulo del Calendario
    calendar.title = atom.Title(text='PyTv Calendar')
    #Configurar Descripcion del Calendario
    calendar.summary = atom.Summary(text='PyTv: Tv Series ' \
                              'notification utility')
    #Configurar el Color con el que se mostraran los eventos
    calendar.color = gdata.calendar.Color(value='#2952A3')
    #Especificar si se podra ver en la lista de "Mis Calendarios"
    calendar.hidden = gdata.calendar.Hidden(value='false')

    #Completar la Creación del Calendario
    new_calendar = calendar_service.InsertCalendar(
                    new_calendar=calendar)

4) Mostrar los distintos Calendarios del Usuario y tomar el ID de uno:
El ID que vamos a tomar es el del Calendario que acabamos de crear.

def print_own_calendars(self, calendar_service):
    #Obtenemos un XML con los datos de los Calendarios
    feed = calendar_service.GetOwnCalendarsFeed()
    print feed.title.text
    #Recorremos los resultados obtenidos imprimiendo
    #el número de orden y el Titulo del Calendario
    for i, a_calendar in enumerate(feed.entry):
        print '\t%s. %s' % (i, a_calendar.title.text,)
        #Si el Titulo es igual al que creamos guardamos el ID
        if a_calendar.title.text == 'PyTv Calendar':
            self.id = a_calendar.id.text
            self.id = self.id.split('full/')[1].replace('%40', '@')

5) Crear Eventos en un Calendario Especifico:
En este caso el "Calendario especifico" será aquel del cual obtuvimos el ID, pero de la misma forma que se obtuvo el ID del Calendario "PyTv Calendar", se podría haber tomado el de otro cualquiera.
Otra aclaración importante es que en este caso vamos a crear "eventos simples", pero si quisiéramos también podríamos crear eventos recurrentes como se puede consultar en la documentación.

def insert_single_event(self, calendar_service, 
                title='Unnamed Event', content='', 
                start_time=None, end_time=None, minutes=10):
    #Crear evento
    event = gdata.calendar.CalendarEventEntry()
    #Asignar titulo del Evento
    event.title = atom.Title(text=title)
    #Asignar descripción
    event.content = atom.Content(text=content)

    #Configurar Tiempo de Inicio y de Fin del Evento
    if start_time is None:
        #Si start_time es None se toma la hora actual
        #como comienzo y una hora despues para fin
        start_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', 
                                time.gmtime())
        end_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', 
                                time.gmtime(time.time() + 3600))
    event.when.append(gdata.calendar.When(start_time=start_time, 
                                end_time=end_time))

    #Guardamos el Evento en el Nuevo Calendario
    #creado pasandole su ID con: self.id
    new_event = calendar_service.InsertEvent(event, 
                    '/calendar/feeds/' + self.id + '/private/full')
    return new_event

6) Listar los Eventos entre determinadas Fechas del Calendario con el que se viene trabajando

def date_range_query(self, calendar_service, 
            start_date='2010-04-24', end_date='2010-04-29'):
    print 'Events from %s to %s:' % (start_date, end_date,)
    #Colocando self.id se toma el Nuevo Calendario creado
    #colocando 'default' toma el Calendario por defecto
    query = gdata.calendar.service.CalendarEventQuery(
                self.id, 'private', 'full')
    query.start_min = start_date
    query.start_max = end_date 
    feed = calendar_service.CalendarQuery(query)
    for i, an_event in enumerate(feed.entry):
        print '\t%s. %s' % (i, an_event.title.text,)
        for a_when in an_event.when:
            print '\t\tStart time: %s' % (a_when.start_time,)
            print '\t\tEnd time:   %s' % (a_when.end_time,)


Ahora creamos una función "execute" que se llama en el "main" para que ejecute todas las operaciones que hemos creado:

def execute(self, calendar_service):
    #Crear Calendario
    self.create_calendar(calendar_service)
    #Mostrar los Calendarios y tomar ID
    self.print_own_calendars(calendar_service)
    #Crear Eventos
    #Evento simple con hora de inicio y fin
    self.insert_single_event(calendar_service, 
            title='Evento Ejemplo', content='Nada que agregar...', 
            minutes=25)
    #Evento de todo el dia
    self.insert_single_event(calendar_service, 
            title='Evento de Todo el Dia',
            content='Mirar Series :P',
            start_time='2010-04-27',
            end_time='2010-04-28')
    #Mostrar Eventos
    self.date_range_query(calendar_service)

Y como resultado en Calendar obtenemos:



Todavia no pude encontrar como hacer que al Crear el Calendario, se le pueda decir con que tipo de Notificaciones queremos que se cree, por defecto se crea sin notificaciones, de lo contrario, al "Agregar un Evento", antes de ejecutar "InsertEvent(...)", podríamos realizar lo siguiente para configurar las notificaciones:

for a_when in event.when:
    if len(a_when.reminder) > 0:
        a_when.reminder[0].minutes = minutes
    else:
        a_when.reminder.append(
            gdata.calendar.Reminder(minutes=minutes))

Y de esa forma el Evento creado emitiría una notificación (popup, mail, sms, etc) tantos minutos antes del evento.

No comments: