1
0
mirror of https://github.com/b4tman/sync_ics2gcal synced 2024-09-21 08:58:03 +00:00
sync_ics2gcal/gcal_sync/gcal.py
2018-04-05 11:16:20 +03:00

216 lines
8.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from apiclient import discovery
import httplib2
import logging
from oauth2client import service_account
from pytz import utc
import sys
class GoogleCalendarService():
@staticmethod
def from_srv_acc_file(service_account_file):
scopes = 'https://www.googleapis.com/auth/calendar'
credentials = service_account.ServiceAccountCredentials.from_json_keyfile_name(
service_account_file, scopes=scopes)
http = credentials.authorize(httplib2.Http())
service = discovery.build('calendar', 'v3', http=http)
return service
class GoogleCalendar():
logger = logging.getLogger('GoogleCalendar')
def __init__(self, service, calendarId):
self.service = service
self.calendarId = calendarId
def list_events_from(self, start):
''' Получение списка событий из GCAL начиная с даты start
'''
events = []
page_token = None
timeMin = utc.normalize(start.astimezone(utc)).replace(
tzinfo=None).isoformat() + 'Z'
while True:
response = self.service.events().list(calendarId=self.calendarId, pageToken=page_token,
singleEvents=True, timeMin=timeMin, fields='id,iCalUID,updated').execute()
if 'items' in response:
events.extend(response['items'])
page_token = response.get('nextPageToken')
if not page_token:
break
self.logger.info('%d events listed', len(events))
return events
def find_exists(self, events):
""" Поиск уже существующих в GCAL событий, из списка событий к вставке
Arguments:
events {list} -- list of events
Returns:
tuple -- (events_exist, events_not_found)
events_exist - list of tuples: (new_event, exists_event)
"""
events_by_req = []
exists = []
not_found = []
def list_callback(request_id, response, exception):
found = False
event = events_by_req[int(request_id)]
if exception is None:
found = ([] != response['items'])
else:
self.logger.error('exception %s, while listing event with UID: %s', str(
exception), event['iCalUID'])
if found:
exists.append(
(event, response['items'][0]))
else:
not_found.append(events_by_req[int(request_id)])
batch = self.service.new_batch_http_request(callback=list_callback)
i = 0
for event in events:
events_by_req.append(event)
batch.add(self.service.events().list(calendarId=self.calendarId,
iCalUID=event['iCalUID'], showDeleted=True, fields='id,iCalUID,updated'), request_id=str(i))
i += 1
batch.execute()
self.logger.info('%d events exists, %d not found',
len(exists), len(not_found))
return exists, not_found
def insert_events(self, events):
""" Вставка событий в GCAL
Arguments:
events -- список событий
"""
events_by_req = []
def insert_callback(request_id, response, exception):
if exception is not None:
event = events_by_req[int(request_id)]
self.logger.error('failed to insert event with UID: %s, exception: %s', event.get(
'UID'), str(exception))
else:
event = response
self.logger.info('event created, id: %s', event.get('id'))
batch = self.service.new_batch_http_request(callback=insert_callback)
i = 0
for event in events:
events_by_req.append(event)
batch.add(self.service.events().insert(
calendarId=self.calendarId, body=event, fields='id,iCalUID,updated'), request_id=str(i))
i += 1
batch.execute()
def patch_events(self, event_tuples):
""" Обновление (патч) событий в GCAL
Arguments:
calendarId -- ИД календаря
event_tuples -- список кортежей событий (новое, старое)
"""
events_by_req = []
def patch_callback(request_id, response, exception):
if exception is not None:
event = events_by_req[int(request_id)]
self.logger.error('failed to patch event with UID: %s, exception: %s', event.get(
'UID'), str(exception))
else:
event = response
self.logger.info('event patched, id: %s', event.get('id'))
batch = self.service.new_batch_http_request(callback=patch_callback)
i = 0
for event_new, event_old in event_tuples:
if 'id' not in event_old:
continue
events_by_req.append(event_new)
batch.add(self.service.events().patch(
calendarId=self.calendarId, eventId=event_old['id'], body=event_new), fields='id,iCalUID,updated', request_id=str(i))
i += 1
batch.execute()
def update_events(self, event_tuples):
""" Обновление событий в GCAL
Arguments:
event_tuples -- список кортежей событий (новое, старое)
"""
events_by_req = []
def update_callback(request_id, response, exception):
if exception is not None:
event = events_by_req[int(request_id)]
self.logger.error('failed to update event with UID: %s, exception: %s', event.get(
'UID'), str(exception))
else:
event = response
self.logger.info('event updated, id: %s', event.get('id'))
batch = self.service.new_batch_http_request(callback=update_callback)
i = 0
for event_new, event_old in event_tuples:
if 'id' not in event_old:
continue
events_by_req.append(event_new)
batch.add(self.service.events().update(
calendarId=self.calendarId, eventId=event_old['id'], body=event_new, fields='id,iCalUID,updated'), request_id=str(i))
i += 1
batch.execute()
def delete_events(self, events):
""" Удаление событий в GCAL
Arguments:
events -- список событий
"""
events_by_req = []
def delete_callback(request_id, _, exception):
event = events_by_req[int(request_id)]
if exception is not None:
self.logger.error('failed to delete event with UID: %s, exception: %s', event.get(
'UID'), str(exception))
else:
self.logger.info('event deleted, id: %s', event.get('id'))
batch = self.service.new_batch_http_request(callback=delete_callback)
i = 0
for event in events:
events_by_req.append(event)
batch.add(self.service.events().delete(
calendarId=self.calendarId, eventId=event['id']), request_id=str(i))
i += 1
batch.execute()
def make_public(self):
rule_public = {
'scope': {
'type': 'default',
},
'role': 'reader'
}
return self.service.acl().insert(calendarId=self.calendarId, body=rule_public).execute()
def add_owner(self, email):
rule_owner = {
'scope': {
'type': 'user',
'value': email,
},
'role': 'owner'
}
return self.service.acl().insert(calendarId=self.calendarId, body=rule_owner).execute()