blechreiz-website/eventplanner_gcal/models.py

172 lines
5.1 KiB
Python
Raw Normal View History

2014-03-08 22:36:25 +01:00
from django.db import models
from eventplanner.models import Event, EventParticipation
from apiclient.discovery import build
from apiclient.http import BatchHttpRequest
from oauth2client.file import Storage
import httplib2
from django.conf import settings
import logging
import datetime
from django.contrib.auth.models import User
logger = logging.getLogger(__name__)
class GCalMapping( models.Model ):
gcal_id = models.CharField( max_length=64 )
event = models.OneToOneField( Event, primary_key=True )
def init( gcal_settings ):
"""Creates a API service object required by the following synchronization functions"""
storage = Storage( gcal_settings['credentials_file'] )
credentials = storage.get()
if credentials is None or credentials.invalid == True:
logger.error("Unable to initialize Google Calendar coupling. Check your settings!")
return None
http = httplib2.Http()
http = credentials.authorize( http )
return build( serviceName='calendar', version='v3',
http=http, developerKey=gcal_settings['developerKey'] )
service = init( settings.GCAL_COUPLING )
def createAttendeesObj( event ):
result = []
for u in User.objects.all():
if u.email.endswith( "@gmail.com") or u.email.endswith("@googlemail.com"):
participation = EventParticipation.get_or_create( u, event )
status = "tentative"
if participation.status == 'Yes': status = "accepted"
if participation.status == 'No' : status = "declined"
o = {
'id': u.email,
'email': u.email,
'displayName': u.username,
'comment': participation.comment,
'responseStatus': status,
}
result.append( o )
return result
def createEvent( event, timezone="Europe/Berlin" ):
if service is None:
logger.error("createEvent: Google API connection not configured")
return
def createDateTimeObj( date, time ):
if time is None:
return { 'date': unicode(date), 'timeZone': timezone }
else:
return { 'dateTime': unicode(date) + 'T' + unicode(time) , 'timeZone': timezone }
startDate = event.date
endDate = event.end_date
if endDate is None: endDate = startDate
startTime = event.meeting_time
if startTime is None: startTime = event.time
if startTime is None:
endTime = None
else:
endTime = datetime.time( 22, 30 )
googleEvent = {
'summary': unicode(settings.GCAL_COUPLING['eventPrefix'] + event.title),
'description': unicode(event.desc),
'location': unicode(event.location),
'start': createDateTimeObj( startDate, startTime ),
'end' : createDateTimeObj( endDate, endTime ),
'extendedProperties': {
'private': {
'blechreizEvent': 'true',
'blechreizID': event.id,
}
},
'attendees': createAttendeesObj( event ),
}
return service.events().insert(calendarId='primary', body=googleEvent)
def getAllEvents(pageToken=None):
events = service.events().list(
calendarId='primary',
singleEvents=True,
maxResults=1000,
orderBy='startTime',
timeMin='2000-01-01T00:00:00-00:00',
timeMax='2100-01-01T00:00:00-00:00',
pageToken=pageToken,
privateExtendedProperty='blechreizEvent=true',
).execute()
return events['items']
def onGcalEventCreated( request_id, response, exception ):
if exception is not None:
print ( "response " + str( response ) )
raise exception
googleId = response['id']
djangoId = response['extendedProperties']['private']['blechreizID']
mapping = GCalMapping( gcal_id = googleId, event = Event.objects.get( pk=djangoId ) )
mapping.save()
def syncGCalEvents():
if service is None:
logger.error("syncGCalEvents: Google API connection not configured")
return
allEvents = getAllEvents()
eventsAtGoogle_djangoID = set()
eventsAtGoogle_googleID = set()
for gcalEv in allEvents:
eventsAtGoogle_djangoID.add( int(gcalEv['extendedProperties']['private']['blechreizID'] ) )
eventsAtGoogle_googleID.add( gcalEv['id'] )
localEvents_djangoID = set( Event. objects.all().values_list('pk' , flat=True) )
localEvents_googleID = set( GCalMapping.objects.all().values_list('gcal_id', flat=True) )
eventsToCreate_djangoID = localEvents_djangoID - eventsAtGoogle_djangoID
eventsToDelete_googleID = eventsAtGoogle_googleID - localEvents_googleID
batch = BatchHttpRequest()
batchIsEmpty = True
for eventDjangoID in eventsToCreate_djangoID:
batch.add( createEvent( Event.objects.get( pk=eventDjangoID ) ), callback=onGcalEventCreated )
batchIsEmpty=False
for eventGoogleID in eventsToDelete_googleID:
batch.add( service.events().delete(calendarId='primary', eventId=eventGoogleID) )
batchIsEmpty=False
if not batchIsEmpty:
batch.execute()