Google calendar sync

This commit is contained in:
Martin Bauer 2014-04-18 13:43:02 +02:00
parent a85e2472f1
commit ba0cde09c1
10 changed files with 1625 additions and 25 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@

View File

@ -2,12 +2,14 @@ from django.db import models
from django.utils.translation import ugettext as _
from django.contrib.auth.models import User, Permission
from django.db.models import Q
from datetime import datetime
from location_field.models import PlainLocationField
from django.db.models import Q
from django.dispatch import Signal
class NoNextEventException( Exception ):
def __str__(self):
@ -114,6 +116,9 @@ class Event ( models.Model ):
return nextEvent
before_read = Signal()
class EventParticipation( models.Model ):
OPTIONS = ( ('?' , _('?' )),
('Yes', _('Yes')),
@ -125,6 +130,7 @@ class EventParticipation( models.Model ):
status = models.CharField ( max_length=3, choices = OPTIONS, default='?', verbose_name=_("status") )
comment = models.CharField ( max_length=64, blank=True, verbose_name=_("comment") )
def get_username(self):
return self.user.username
@ -141,6 +147,10 @@ class EventParticipation( models.Model ):
else:
return True
@staticmethod
def raiseBeforeReadSignal():
before_read.send( sender=EventParticipation )
@staticmethod
def isMember( user ):
return user.has_perm('eventplanner.member')

View File

@ -6,7 +6,6 @@ from django.forms import TextInput
from models import Event, EventParticipation
from serializers import ParticipationSerializer
import datetime
@ -62,6 +61,7 @@ def eventplanning( request ):
"""
View for a specific user, to edit his events
"""
EventParticipation.raiseBeforeReadSignal()
# non-members see the grid - but cannot edit anything
if not EventParticipation.isMember( request.user ):
return events_grid(request)
@ -78,6 +78,8 @@ def eventplanning( request ):
def events_grid( request ):
EventParticipation.raiseBeforeReadSignal()
usernames = [ u.username for u in EventParticipation.members() ]
all_future_events = list ( Event.objects.filter( date__gte = datetime.date.today() ).order_by( 'date') )

View File

@ -1 +1,2 @@
__author__ = 'martin'
import signals

View File

@ -0,0 +1,22 @@
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.file import Storage
flow = OAuth2WebServerFlow(client_id='34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com',
client_secret='y4t9XBrJdCODPTO5UvtONWWn',
scope='https://www.googleapis.com/auth/calendar',
redirect_uri='http://localhost')
createLink = False
if createLink:
auth_uri = flow.step1_get_authorize_url()
print "AuthURI:"
print auth_uri
print "Visit this link - grab the key from the url and paste it into the else block"
exit(0)
else:
code = "4/Iais8aK8_KxbMQjq3Rtw3PFXu6Nr.8itpukY_6ZgZOl05ti8ZT3ax27a3hAI"
credentials = flow.step2_exchange( code )
storage = Storage('calendarCredentials.dat')
storage.put( credentials )

View File

@ -0,0 +1,76 @@
from oauth2client.client import OAuth2WebServerFlow
from apiclient.discovery import build
from oauth2client.file import Storage
import httplib2
flow = OAuth2WebServerFlow(client_id='34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com',
client_secret='y4t9XBrJdCODPTO5UvtONWWn',
scope='https://www.googleapis.com/auth/calendar',
redirect_uri='http://localhost')
#auth_uri = flow.step1_get_authorize_url()
#print "AuthURI:"
#print auth_uri
#exit(0)
#code="4/z524dROAcIc24igDftg99LqjyJPG.4jR5ZcA_RPYaOl05ti8ZT3a5aIW3hAI"
#credentials = flow.step2_exchange( code )
storage = Storage('calendarCredentials.dat')
credentials = storage.get()
if credentials is None or credentials.invalid == True:
print "Invalid credentials"
exit( 0)
http = httplib2.Http()
http = credentials.authorize( http )
service = build( serviceName='calendar', version='v3', http=http, developerKey='blechreiz-homepage' )
calendarId = 'blechreizensemble@gmail.com'
def getEvents(pageToken=None):
events = service.events().list(
calendarId='primary',
singleEvents=True,
maxResults=1000,
orderBy='startTime',
timeMin='2012-11-01T00:00:00-08:00',
timeMax='2018-11-30T00:00:00-08:00',
pageToken=pageToken,
).execute()
return events
def createEvent():
print ( "Creating Event ")
event = {
'summary': 'Blechreiz Probe',
'description': 'Eine Beschreibung.. bitte alle instrumente mitbringen',
'location': 'Rohr',
'start': {
'dateTime': '2014-03-23T19:00:00',
'timeZone': 'Europe/Berlin'
},
'end': {
'dateTime': '2014-03-23T23:05:00',
'timeZone': 'Europe/Berlin'
},
'attendees': [
{
'id': 'martinbauer86@gmail.com',
'email': 'martinbauer86@gmail.com',
'displayName': "MartinB",
},
],
}
created_event = service.events().insert(calendarId='primary', body=event).execute()
print created_event['id']
#createEvent()
print getEvents()

View File

@ -106,13 +106,20 @@ def buildGCalEvent( event, timezone="Europe/Berlin" ):
# -------------------------------------------------------------------------------
def getAllGCalEvents(pageToken=None):
def getAllGCalEvents( fromNow=False, pageToken=None ):
if fromNow:
now = datetime.datetime.now()
minTime = now.strftime("%Y-%m-%dT%H:%M:%S-00:00")
else:
minTime = '2000-01-01T00:00:00-00:00'
events = service.events().list(
calendarId='primary',
singleEvents=True,
maxResults=1000,
orderBy='startTime',
timeMin='2000-01-01T00:00:00-00:00',
timeMin=minTime,
timeMax='2100-01-01T00:00:00-00:00',
pageToken=pageToken,
privateExtendedProperty='blechreizEvent=true',
@ -208,3 +215,25 @@ def syncGCalEvents():
return len (eventsToCreate_djangoID), len(eventsToDelete_googleID )
def syncParticipationFromGoogleToLocal():
allEvents = getAllGCalEvents(fromNow=True)
for e in allEvents:
localId = e['extendedProperties']['private']['blechreizID']
localEvent = Event.objects.get( pk=localId )
for a in e['attendees']:
user = User.objects.get( email= a['email'] )
part = EventParticipation.get_or_create( user, localEvent )
if 'comment' in a:
part.comment = a['comment']
if a['responseStatus'] == 'needsAction' or a['responseStatus']=='tentative':
part.status = '?'
elif a['responseStatus'] == 'accepted':
part.status = 'Yes'
elif a['responseStatus'] == 'declined':
part.status = 'No'
else:
logger.error("Unknown response status when mapping gcal event: " + a['responseStatus'] )
part.save()

View File

@ -1,27 +1,67 @@
from django.db.models.signals import post_save,pre_delete
from django.dispatch import receiver
from eventplanner.models import Event, EventParticipation
from eventplanner.models import Event, EventParticipation, before_read
from eventplanner_gcal.models import createGCalEvent, updateGCalEvent
from eventplanner_gcal.models import deleteGCalEvent, syncParticipationFromGoogleToLocal
class SignalLock:
def __init__(self):
self.locked=False
def __enter__(self):
if self.locked:
return False
self.locked=True
return True
def __exit__(self, type, value, traceback):
self.locked=False
def isLocked(self):
return self.locked
signalLock = SignalLock()
from eventplanner_gcal.models import createGCalEvent, updateGCalEvent, deleteGCalEvent
@receiver( post_save,sender= Event)
def event_post_save_handler(event, **kwargs):
def event_post_save_handler( **kwargs):
if not signalLock.isLocked():
with signalLock:
event = kwargs['instance']
created = kwargs['created']
if created:
print("Creating Gcal event")
createGCalEvent( event ).execute()
else:
print( "Updating Gcal event")
updateGCalEvent( event ).execute()
@receiver( pre_delete,sender= Event)
def event_pre_delete_handler(event, **kwargs):
def event_pre_delete_handler( **kwargs):
if not signalLock.isLocked():
with signalLock:
event = kwargs['instance']
print ("Deleting GCAL event")
deleteGCalEvent( event ).execute()
@receiver( post_save, sender=EventParticipation )
def participation_post_save_handler(participation, **kwargs):
def participation_post_save_handler( **kwargs):
if not signalLock.isLocked():
with signalLock:
participation = kwargs['instance']
print("Participation post save -> update gcal")
updateGCalEvent( participation.event ).execute()
@receiver( before_read, sender=EventParticipation )
def participation_before_read_handler( **kwargs):
if not signalLock.isLocked():
with signalLock:
print("SyncParticipation from google")
syncParticipationFromGoogleToLocal()