Port to new django version - not yet fully working

- location field makes problems
This commit is contained in:
Martin Bauer
2019-01-05 11:27:15 +01:00
parent 72a9642a8e
commit 663185fd40
168 changed files with 797 additions and 5967 deletions

View File

@@ -1,2 +0,0 @@
import signals

View File

@@ -3,45 +3,43 @@ import httplib2
import datetime
import time
from eventplanner.models import Event, EventParticipation
from eventplanner_gcal.models import GCalMapping, GCalPushChannel,UserGCalCoupling
from eventplanner.models import Event, EventParticipation
from eventplanner_gcal.models import GCalMapping, GCalPushChannel, UserGCalCoupling
from apiclient.http import BatchHttpRequest
from django.contrib.auth.models import User
from django.conf import settings
from pprint import pprint
logger = logging.getLogger(__name__)
# --------------------- Authentication using oauth2 --------------------------------------------
def createGCalServiceObject():
"""Creates a Google API service object. This object is required whenever a Google API call is made"""
from oauth2client.file import Storage
from apiclient.discovery import build
from oauth2client import tools, client
gcal_settings = settings.GCAL_COUPLING
storage = Storage( gcal_settings['credentials_file'] )
storage = Storage(gcal_settings['credentials_file'])
credentials = storage.get()
print("credentials", credentials)
if credentials is None or credentials.invalid == True:
#flow = client.flow_from_clientsecrets(CLIENT_SEICRET_FILE, SCOPES)
# flow = client.flow_from_clientsecrets(CLIENT_SEICRET_FILE, SCOPES)
print("invalid credentials for gcal")
logger.error("Unable to initialize Google Calendar coupling. Check your settings!")
return None
http = httplib2.Http()
http = credentials.authorize( http )
res = build( serviceName='calendar', version='v3',
http=http, developerKey=gcal_settings['developerKey'] )
http = credentials.authorize(http)
res = build(serviceName='calendar', version='v3',
http=http, developerKey=gcal_settings['developerKey'])
print("res", res)
if res is None:
logger.error( "Authentication at google API failed. Check your settings!" )
logger.error("Authentication at google API failed. Check your settings!")
return res
@@ -50,14 +48,15 @@ def getServiceObject():
getServiceObject.__serviceObject = createGCalServiceObject()
return getServiceObject.__serviceObject
getServiceObject.__serviceObject = None
getServiceObject.__serviceObject = None
# --------------------- Building GCal event representation ------------------------------------
def buildGCalAttendeesObj( event ):
def buildGCalAttendeesObj(event):
"""Builds a attendees object that is inserted into the GCal event.
Attendees are all users that have a google mail address. """
result = []
@@ -66,9 +65,9 @@ def buildGCalAttendeesObj( event ):
u = userMapping.user
# No get or create here, since a create would trigger another synchronization
#participation = EventParticipation.get_or_create( u, event )
# participation = EventParticipation.get_or_create( u, event )
try:
participation = EventParticipation.objects.get( event = event, user = u )
participation = EventParticipation.objects.get(event=event, user=u)
localStatus = participation.status
localComment = participation.comment
except EventParticipation.DoesNotExist:
@@ -76,9 +75,9 @@ def buildGCalAttendeesObj( event ):
localComment = ""
status = "needsAction"
if localStatus == "?" : status = "tentative"
if localStatus == "?": status = "tentative"
if localStatus == 'Yes': status = "accepted"
if localStatus == 'No' : status = "declined"
if localStatus == 'No': status = "declined"
o = {
'id': userMapping.email,
@@ -87,20 +86,19 @@ def buildGCalAttendeesObj( event ):
'comment': localComment,
'responseStatus': status,
}
result.append( o )
result.append(o)
return result
def buildGCalEvent( event, timezone="Europe/Berlin" ):
def buildGCalEvent(event, timezone="Europe/Berlin"):
""" Builds a GCal event using a local event. """
def createDateTimeObj( date, time ):
def createDateTimeObj(date, time):
if time is None:
return { 'date': unicode(date), 'timeZone': timezone }
return {'date': unicode(date), 'timeZone': timezone}
else:
return { 'dateTime': unicode(date) + 'T' + unicode(time) , 'timeZone': timezone }
return {'dateTime': unicode(date) + 'T' + unicode(time), 'timeZone': timezone}
startDate = event.date
endDate = event.end_date
@@ -112,47 +110,48 @@ def buildGCalEvent( event, timezone="Europe/Berlin" ):
if startTime is None:
endTime = None
else:
endTime = datetime.time( 22, 30 )
endTime = datetime.time(22, 30)
gLocation = unicode(event.location)
if event.map_location:
# Map location has the following format: latitude,longitude,zoomlevel
# the first two are needed
s = event.map_location.split(",")
gLocation = unicode ( "%s,%s" % (s[0],s[1] ) )
gLocation = unicode("%s,%s" % (s[0], s[1]))
return {
'summary': unicode(settings.GCAL_COUPLING['eventPrefix'] + event.title),
'summary': unicode(settings.GCAL_COUPLING['eventPrefix'] + event.title),
'description': unicode(event.desc),
'location': gLocation,
'start': createDateTimeObj( startDate, startTime ),
'end' : createDateTimeObj( endDate, endTime ),
'location': gLocation,
'start': createDateTimeObj(startDate, startTime),
'end': createDateTimeObj(endDate, endTime),
'extendedProperties': {
'private': {
'blechreizEvent': 'true',
'blechreizID': event.id,
}
},
'attendees': buildGCalAttendeesObj( event ),
'attendees': buildGCalAttendeesObj(event),
}
# ------------------------------ Callback Functions ------------------------------------------------
def onGcalEventCreated( request_id, response, exception=None ):
def onGcalEventCreated(request_id, response, exception=None):
"""Callback function for created events to enter new gcal id in the mapping table"""
if exception is not None:
print ( "response " + str( response ) )
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 = GCalMapping(gcal_id=googleId, event=Event.objects.get(pk=djangoId))
mapping.save()
# ------------------------------ GCal Api Calls -------------------------------------------------
def getAllGCalEvents( service, fromNow=False ):
def getAllGCalEvents(service, fromNow=False):
"""Retrieves all gcal events with custom property blechreizEvent=True i.e. all
events that have been created by this script."""
@@ -170,99 +169,99 @@ def getAllGCalEvents( service, fromNow=False ):
timeMin=minTime,
timeMax='2100-01-01T00:00:00-00:00',
privateExtendedProperty='blechreizEvent=true',
).execute()
).execute()
return events['items']
def createGCalEvent( service, event, timezone="Europe/Berlin" ):
def createGCalEvent(service, event, timezone="Europe/Berlin"):
"""Creates a new gcal event using a local event"""
googleEvent = buildGCalEvent(event,timezone)
return service.events().insert(calendarId='primary', body=googleEvent )
googleEvent = buildGCalEvent(event, timezone)
return service.events().insert(calendarId='primary', body=googleEvent)
def updateGCalEvent( service, event, timezone="Europe/Berlin"):
def updateGCalEvent(service, event, timezone="Europe/Berlin"):
"""Updates an existing gcal event, using a local event"""
googleEvent = buildGCalEvent(event,timezone)
googleEvent = buildGCalEvent(event, timezone)
try:
mapping = GCalMapping.objects.get( event=event )
mapping = GCalMapping.objects.get(event=event)
except GCalMapping.DoesNotExist:
return createGCalEvent( service, event, timezone )
return createGCalEvent(service, event, timezone)
return service.events().patch(calendarId='primary', eventId= mapping.gcal_id, body=googleEvent)
return service.events().patch(calendarId='primary', eventId=mapping.gcal_id, body=googleEvent)
def deleteGCalEvent( service, event ):
def deleteGCalEvent(service, event):
"""Deletes gcal that belongs to the given local event"""
mapping = GCalMapping.objects.get( event=event )
mapping = GCalMapping.objects.get(event=event)
gcalId = mapping.gcal_id
mapping.delete()
return service.events().delete(calendarId='primary', eventId=gcalId)
# ------------------------------------- Synchronization ----------------------------------------------------
def deleteAllGCalEvents( service = getServiceObject() ):
def deleteAllGCalEvents(service=None):
"""Deletes all gcal events that have been created by this script"""
if service is None: service = getServiceObject()
if service is None:
service = getServiceObject()
gcalIds = [ ev['id'] for ev in getAllGCalEvents( service ) ]
l = len( gcalIds )
gcalIds = [ev['id'] for ev in getAllGCalEvents(service)]
l = len(gcalIds)
if l == 0:
return l
batch = BatchHttpRequest()
for id in gcalIds:
batch.add( service.events().delete(calendarId='primary', eventId=id) )
batch.add(service.events().delete(calendarId='primary', eventId=id))
batch.execute()
GCalMapping.objects.all().delete()
return l
def syncFromLocalToGoogle( service = None ):
def syncFromLocalToGoogle(service=None):
""" Creates a google event for each local event (if it does not exist yet) and deletes all google events
that are not found in local database. Updates participation info of gcal events using local data
"""
if service is None: service = getServiceObject()
allEvents = getAllGCalEvents( service )
allEvents = getAllGCalEvents(service)
eventsAtGoogle_djangoID = set()
eventsAtGoogle_googleID = set()
for gcalEv in allEvents:
eventsAtGoogle_djangoID.add( int(gcalEv['extendedProperties']['private']['blechreizID'] ) )
eventsAtGoogle_googleID.add( gcalEv['id'] )
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) )
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( createGCalEvent( service, Event.objects.get( pk=eventDjangoID ) ), callback=onGcalEventCreated )
batchIsEmpty=False
batch.add(createGCalEvent(service, 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
batch.add(service.events().delete(calendarId='primary', eventId=eventGoogleID))
batchIsEmpty = False
for gcalEv in allEvents:
eventDjangoID = int( gcalEv['extendedProperties']['private']['blechreizID'] )
eventDjangoID = int(gcalEv['extendedProperties']['private']['blechreizID'])
try:
djangoEv = Event.objects.get( pk=eventDjangoID )
if 'attendees' not in gcalEv:
djangoEv = Event.objects.get(pk=eventDjangoID)
if 'attendees' not in gcalEv:
gcalEv['attendees'] = []
if gcalEv['attendees'] != buildGCalAttendeesObj( djangoEv ):
batch.add( updateGCalEvent( service, djangoEv ) )
if gcalEv['attendees'] != buildGCalAttendeesObj(djangoEv):
batch.add(updateGCalEvent(service, djangoEv))
batchIsEmpty = False
except Event.DoesNotExist:
pass
@@ -270,40 +269,38 @@ def syncFromLocalToGoogle( service = None ):
if not batchIsEmpty:
batch.execute()
return len(eventsToCreate_djangoID), len(eventsToDelete_googleID)
return len (eventsToCreate_djangoID), len(eventsToDelete_googleID)
def syncFromGoogleToLocal( service = None ):
def syncFromGoogleToLocal(service=None):
"""Retrieves only participation infos for all events and updates local database if anything has changed. """
if service is None: service = getServiceObject()
if service is None:
service = getServiceObject()
newStatusReceived = False
allEvents = getAllGCalEvents( service, fromNow=True)
allEvents = getAllGCalEvents(service, fromNow=True)
for e in allEvents:
localId = e['extendedProperties']['private']['blechreizID']
localEvent = Event.objects.get( pk=localId )
localId = e['extendedProperties']['private']['blechreizID']
localEvent = Event.objects.get(pk=localId)
for a in e['attendees']:
user = UserGCalCoupling.objects.get( email = a['email'] ).user
part = EventParticipation.get_or_create( user, localEvent )
user = UserGCalCoupling.objects.get(email=a['email']).user
part = EventParticipation.get_or_create(user, localEvent)
if 'comment' in a:
part.comment = a['comment']
if a['responseStatus'] == 'needsAction' :
if a['responseStatus'] == 'needsAction':
part.status = "-"
elif a['responseStatus']=='tentative':
elif 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'] )
logger.error("Unknown response status when mapping gcal event: " + a['responseStatus'])
prev = EventParticipation.objects.get( event = part.event, user = part.user )
prev = EventParticipation.objects.get(event=part.event, user=part.user)
# Important: Save only if the participation info has changed
# otherwise everything is synced back to google via the post save signal
@@ -315,18 +312,18 @@ def syncFromGoogleToLocal( service = None ):
return newStatusReceived
# ------------------------------------- Synchronization ----------------------------------------------------
def checkGCalSubscription( service=None, timeToLive = 14*24*3600, renewBeforeExpiry = None ):
def checkGCalSubscription(service=None, timeToLive=14 * 24 * 3600, renewBeforeExpiry=None):
"""Google offers a push service if any event information has changed. This works using a so called
channel, which has a certain time to live. This method checks that a valid channel exists:
- if none exists a new one is created
- if existing channel does expire soon, the channel is renewed
- if channel has already expired a sync is triggered and a new channel is created
"""
if service is None: service = getServiceObject()
if service is None:
service = getServiceObject()
if renewBeforeExpiry is None:
renewBeforeExpiry = 0.8 * timeToLive
@@ -335,73 +332,75 @@ def checkGCalSubscription( service=None, timeToLive = 14*24*3600, renewBeforeEx
# Test if a channel already exists for this callbackURL
try:
dbChannel = GCalPushChannel.objects.get( address=callbackUrl )
dbChannel = GCalPushChannel.objects.get(address=callbackUrl)
gChannel = dbChannel.toGChannel()
# if expiration time between 0 and two days: stop and create new channel
curTime = int( time.time() * 1000)
curTime = int(time.time() * 1000)
if gChannel.expiration > curTime:
# not yet expired
if curTime + renewBeforeExpiry*1000 > gChannel.expiration:
#will expire in less than "renewBeforeExpiry"
print ( "Renewing Google Calendar Subscription: " + callbackUrl )
GCalPushChannel.stop( service, gChannel )
GCalPushChannel.createNew( callbackUrl, service, timeToLive )
if curTime + renewBeforeExpiry * 1000 > gChannel.expiration:
# will expire in less than "renewBeforeExpiry"
print("Renewing Google Calendar Subscription: " + callbackUrl)
GCalPushChannel.stop(service, gChannel)
GCalPushChannel.createNew(callbackUrl, service, timeToLive)
else:
print ("Channel active until %d " % ( gChannel.expiration, ) )
print("Channel active until %d " % (gChannel.expiration,))
else:
logger.info( "Google calendar subscription had expired - getting new subscription" )
logger.info("Google calendar subscription had expired - getting new subscription")
# to get back in sync again we have to decide which data to take
# so we use the local data as reference
syncFromLocalToGoogle( service )
GCalPushChannel.createNew( callbackUrl, service, timeToLive )
syncFromLocalToGoogle(service)
GCalPushChannel.createNew(callbackUrl, service, timeToLive)
except GCalPushChannel.DoesNotExist:
# create new channel and save it in database
logger.info ( "No CGalCallback Channel exists yet for: " + callbackUrl )
logger.info("No CGalCallback Channel exists yet for: " + callbackUrl)
# to get back in sync again we have to decide which data to take
# so we use the local data as reference
syncFromLocalToGoogle( service )
GCalPushChannel.createNew( callbackUrl, service, timeToLive )
syncFromLocalToGoogle(service)
GCalPushChannel.createNew(callbackUrl, service, timeToLive)
def stopAllGCalSubscriptions( service=None ):
def stopAllGCalSubscriptions(service=None):
"""Stops the channel subscription """
if service is None: service = getServiceObject()
if service is None:
service = getServiceObject()
for dbChannel in GCalPushChannel.objects.all():
print("Stopping %s expiry at %d " % ( dbChannel.id, dbChannel.expiration ) )
GCalPushChannel.stop( service, dbChannel.toGChannel() )
print("Stopping %s expiry at %d " % (dbChannel.id, dbChannel.expiration))
GCalPushChannel.stop(service, dbChannel.toGChannel())
def checkIfGoogleCallbackIsValid( token, channelID, resourceID, service=None ):
if service is None: service = getServiceObject()
def checkIfGoogleCallbackIsValid(token, channelID, resourceID, service=None):
if service is None:
service = getServiceObject()
allChannels = GCalPushChannel.objects.all()
if len(allChannels) == 0:
return False # no known subscriptions -> callback has to be from an old channel
return False # no known subscriptions -> callback has to be from an old channel
if len(allChannels) > 1:
logger.warning( "Multiple GCal subscriptions! This is strange and probably an error. "
"All channels are closed and one new is created. ")
stopAllGCalSubscriptions( service )
logger.warning("Multiple GCal subscriptions! This is strange and probably an error. "
"All channels are closed and one new is created. ")
stopAllGCalSubscriptions(service)
checkGCalSubscription()
allChannels = GCalPushChannel.objects.all()
assert( len(allChannels) == 1 )
assert (len(allChannels) == 1)
theChannel = allChannels[0]
if channelID != theChannel.id or resourceID != theChannel.resource_id or token != theChannel.token:
logger.warning( "Got GCal Response from an unexpected Channel"
"Got (%s,%s,%s) "
"expected (%s,%s,%s) "
"Old Channel is stopped."
% ( channelID, resourceID,token, theChannel.id, theChannel.resource_id, theChannel.token ))
logger.warning("Got GCal Response from an unexpected Channel"
"Got (%s,%s,%s) "
"expected (%s,%s,%s) "
"Old Channel is stopped."
% (channelID, resourceID, token, theChannel.id, theChannel.resource_id, theChannel.token))
channelToStop = GCalPushChannel( id = channelID, resource_id = resourceID, token = token )
GCalPushChannel.stop( service, channelToStop.toGChannel() )
channelToStop = GCalPushChannel(id=channelID, resource_id=resourceID, token=token)
GCalPushChannel.stop(service, channelToStop.toGChannel())
return False

View File

@@ -3,59 +3,57 @@ import uuid
from eventplanner.models import Event
from django.contrib.auth.models import User
from apiclient.channel import Channel
from django.db import models
logger = logging.getLogger(__name__)
class UserGCalCoupling( models.Model ):
class UserGCalCoupling(models.Model):
# For every user in this table the gcal coupling is activated
user = models.OneToOneField( User )
email = models.CharField( max_length=1024 )
user = models.OneToOneField(User, on_delete=models.CASCADE)
email = models.CharField(max_length=1024)
class GCalMapping( models.Model ):
class GCalMapping(models.Model):
"""Mapping between event id at google and local event id"""
gcal_id = models.CharField( max_length=64 )
event = models.OneToOneField( Event, primary_key=True )
gcal_id = models.CharField(max_length=64)
event = models.OneToOneField(Event, primary_key=True, on_delete=models.CASCADE)
class GCalPushChannel( models.Model ):
class GCalPushChannel(models.Model):
"""This table has either zero or one entry. Required to store if a channel already exists,
when it expires and how to stop (renew) the channel
"""
id = models.CharField( max_length=128, primary_key=True )
address = models.CharField( max_length=256 )
token = models.CharField( max_length=128 )
resource_id = models.CharField( max_length=128 )
expiration = models.IntegerField()
id = models.CharField(max_length=128, primary_key=True)
address = models.CharField(max_length=256)
token = models.CharField(max_length=128)
resource_id = models.CharField(max_length=128)
expiration = models.IntegerField()
def toGChannel( self ):
return Channel( 'web_hook', self.id, self.token, self.address, self.expiration, resource_id = self.resource_id )
def toGChannel(self):
return Channel('web_hook', self.id, self.token, self.address, self.expiration, resource_id=self.resource_id)
@staticmethod
def fromGChannel( gChannel ):
return GCalPushChannel( id = gChannel.id,
address = gChannel.address,
token = gChannel.token,
expiration = gChannel.expiration,
resource_id= gChannel.resource_id )
def fromGChannel(gChannel):
return GCalPushChannel(id=gChannel.id,
address=gChannel.address,
token=gChannel.token,
expiration=gChannel.expiration,
resource_id=gChannel.resource_id)
@staticmethod
def createNew( callbackUrl, service, ttl = None ):
gChannel = Channel('web_hook', str(uuid.uuid4()), 'blechreizGcal', callbackUrl, params= { 'ttl' : int(ttl) } )
response = service.events().watch( calendarId='primary', body= gChannel.body() ).execute()
gChannel.update( response )
def createNew(callbackUrl, service, ttl=None):
gChannel = Channel('web_hook', str(uuid.uuid4()), 'blechreizGcal', callbackUrl, params={'ttl': int(ttl)})
response = service.events().watch(calendarId='primary', body=gChannel.body()).execute()
gChannel.update(response)
dbChannel = GCalPushChannel.fromGChannel( gChannel )
dbChannel = GCalPushChannel.fromGChannel(gChannel)
dbChannel.save()
@staticmethod
def stop( service, gChannel ):
def stop(service, gChannel):
channelService = service.channels()
channelService.stop( body = gChannel.body() ).execute()
GCalPushChannel.fromGChannel( gChannel ).delete()
channelService.stop(body=gChannel.body()).execute()
GCalPushChannel.fromGChannel(gChannel).delete()

View File

@@ -1,54 +1,51 @@
from django.db.models.signals import post_save,pre_delete
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
from eventplanner.models import Event, EventParticipation
from django.contrib.auth.models import User
from eventplanner_gcal.google_sync import getServiceObject, syncFromLocalToGoogle,\
createGCalEvent, deleteGCalEvent, updateGCalEvent, onGcalEventCreated
from eventplanner_gcal.google_sync import getServiceObject, \
createGCalEvent, deleteGCalEvent, updateGCalEvent, onGcalEventCreated
import logging
logger = logging.getLogger( __name__ )
logger = logging.getLogger(__name__)
#@receiver( post_save, sender=User )
#def user_changed( **kwargs ):
# @receiver( post_save, sender=User )
# def user_changed( **kwargs ):
# logger.info("Synchronizing with google - user information changed")
# syncFromLocalToGoogle( getServiceObject() )
@receiver( post_save,sender= Event)
def event_post_save_handler( **kwargs):
@receiver(post_save, sender=Event)
def event_post_save_handler(**kwargs):
event = kwargs['instance']
created = kwargs['created']
try:
if created:
logger.info("Creating Gcal event")
response = createGCalEvent( getServiceObject(), event ).execute()
onGcalEventCreated( None, response, None )
response = createGCalEvent(getServiceObject(), event).execute()
onGcalEventCreated(None, response, None)
else:
logger.info( "Updating Gcal event")
updateGCalEvent( getServiceObject(),event ).execute()
logger.info("Updating Gcal event")
updateGCalEvent(getServiceObject(), event).execute()
except:
logger.error( "Error updating Gcal event")
logger.error("Error updating Gcal event")
@receiver( pre_delete,sender= Event)
def event_pre_delete_handler( **kwargs):
@receiver(pre_delete, sender=Event)
def event_pre_delete_handler(**kwargs):
try:
event = kwargs['instance']
logger.info ("Deleting GCAL event")
deleteGCalEvent( getServiceObject(), event ).execute()
logger.info("Deleting GCAL event")
deleteGCalEvent(getServiceObject(), event).execute()
except:
logger.error("Error deleting GCAL event")
@receiver( post_save, sender=EventParticipation )
def participation_post_save_handler( **kwargs):
@receiver(post_save, sender=EventParticipation)
def participation_post_save_handler(**kwargs):
try:
participation = kwargs['instance']
logger.info("Participation post save -> update gcal")
updateGCalEvent( getServiceObject(), participation.event ).execute()
updateGCalEvent(getServiceObject(), participation.event).execute()
except:
logger.error("Error deleting GCAL event")

View File

@@ -1,10 +1,9 @@
from django.conf.urls import patterns, url
from django.conf.urls import url
from views import runSync, gcalApiCallback, manage
urlpatterns = patterns('',
url(r'^runSync$', runSync ),
url(r'^gcalApiCallback$', gcalApiCallback ),
url(r'^manage$', manage ),
)
from .views import runSync, gcalApiCallback, manage
urlpatterns = [
url(r'^runSync$', runSync),
url(r'^gcalApiCallback$', gcalApiCallback),
url(r'^manage$', manage),
]