|
|
from dateutil import rrule, tzfrom oauth2client import toolsfrom googleapiclient.errors import HttpErrorfrom dateutil.parser import parse as date_parseimport reimport tzlocalimport argparseimport datetime
if __name__ == "__main__": from api import APIelse: from gapi.api import API
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()APPLICATION_NAME = "Google Calendar API Python"
SUN = 6MON = 0TUE = 1WED = 2THU = 3FRI = 4SAT = 5
def to_dateTime(datetime: datetime.datetime): """converts a datetime into json format for rest api""" if not datetime.tzinfo: datetime = datetime.astimezone() zone = tzlocal.get_localzone().zone datetime = datetime.isoformat(timespec="seconds") return {"timeZone": zone, "dateTime": datetime}
def from_dateTime(dateTime): """converts to a datetime from json format returned by rest api""" timezone = tz.gettz(dateTime["timeZone"]) datetime = date_parse(dateTime["dateTime"]) datetime.replace(tzinfo=timezone) return datetime
class calendar_api(API): def __init__( self, app_name, client_secret_file, credentials_dir, scopes="https://www.googleapis.com/auth/calendar", version="v3", ): super().__init__( "calendar", scopes, app_name, client_secret_file, credentials_dir, version )
self.calendars = self.get_calendars() self.ids = dict( (calendar["summary"].lower(), calendar["id"]) for calendar in self.calendars )
def create_event(self, calendar_id, body):
try: calendar_id = self.ids[calendar_id] except KeyError: pass service = self.service event_service = service.events() event = event_service.insert(calendarId=calendar_id, body=body).execute() return event["id"]
def update_event(self, calendar_id, event_id, body): try: calendar_id = self.ids[calendar_id] except KeyError: pass
service = self.service event_service = service.events() try: event = event_service.get( calendarId=calendar_id, eventId=event_id ).execute() except HttpError as e: if e.resp.status == 404: return self.create_event(calendar_id, body)
updated_event = ( service.events() .update(calendarId=calendar_id, eventId=event["id"], body=body) .execute() ) return updated_event["id"]
def get_calendars(self): page_token = None cl = [] first = True while page_token or first: first = False calendar_list_service = self.service.calendarList() calendar_list = calendar_list_service.list(pageToken=page_token).execute() cl += list(calendar_entry for calendar_entry in calendar_list["items"]) page_token = calendar_list.get("nextPageToken") return cl
def get_events(self, cal_id): service = self.service try: cal_id = self.ids[cal_id] except KeyError: pass page_token = None ret = [] while True: event_service = service.events() events = event_service.list( calendarId=cal_id, pageToken=page_token ).execute() ret += events["items"] page_token = events.get("nextPageToken") if not page_token: break return ret
def get_event_by_id(self, cal_id, event_id): """Retrieves event from cal_id and event_id""" service = self.service event_service = service.events() return event_service.get(calendarId=cal_id, eventId=event_id).execute()
class Event: """Model for a calendar event that can be uploaded"""
def __init__( self, start, end, name, description=None, recurrence=None, reminders=None, attendees=None, location=None, id=None, ): self.start = start self.attendees = attendees self.end = end self.name = name self.description = description self.location = location self.recurrence = recurrence self.id = id if reminders is None: self.reminders = {"useDefault": True} else: self.reminders = reminders
def add_reminder(self, until, method="popup"): """Add a reminder minutes before an event.
Use either a notification (popup) or email"""
assert method in ("email", "popup") self.reminders["useDefault"] = False if isinstance(until, datetime.timedelta): minutes_until = until.days * 24 * 60 minutes_until += until.seconds // 60 else: minutes_until = until self.reminders.setdefault("overrides", []).append( {"method": method, "minutes": minutes_until} )
def add_weekly_recurrence(self, until: datetime.datetime, *days): if not until.tzinfo: until = until.astimezone() ret = rrule.rrule( freq=rrule.WEEKLY, dtstart=self.start, wkst=SUN, until=until, byweekday=days ) ret_str = str(ret).split("\n")[-1] ret_str = re.sub(r"(UNTIL=[^;]+)", r"\1Z", ret_str) if self.recurrence is None: self.recurrence = [] self.recurrence.append(ret_str)
def to_json(self): keys = ("attendees", "description", "location", "recurrence", "reminders") ret = { "summary": self.name, "start": to_dateTime(self.start), "end": to_dateTime(self.end), } for key in keys: try: value = self.__getattribute__(key) if value: ret[key] = value except AttributeError: pass return ret
def add_attendees(self): pass
@classmethod def from_json(cls, body): args = {} args["name"] = body.get("summary", "unnamed") args["start"] = from_dateTime(body["start"]) args["end"] = from_dateTime(body["end"]) keys = ("attendees", "description", "location", "recurrence", "reminders", "id") for key in keys: try: args[key] = body[key] except KeyError: pass instance = cls(**args) return instance
@classmethod def from_id(cls, api: calendar_api, calendar_id, event_id): """creates an event model from specified calendar and event_id""" event = api.get_event_by_id(calendar_id, event_id) return cls.from_json(event)
def upload(self, api: calendar_api, calendar_id): """Upload an event to calendar.
Either modifies an event in place or creates a new event."""
if self.id is not None: event_id = api.update_event(calendar_id, self.id, self.to_json()) else: event_id = api.create_event(calendar_id, self.to_json()) return event_id
if __name__ == "__main__": import os
# ~~BODY EXAMPLE~~##~~BODY EXAMPLE~~ example = { "attendees": [{"email": "lpage@example.com"}, {"email": "sbrin@example.com"}], "description": "A chance to hear more about Google's\
developer products.", "end": { "dateTime": "2015-05-28T17:00:00-07:00", "timeZone": "America/Los_Angeles", }, "location": "800 Howard St., San Francisco, CA 94103", "recurrence": ["RRULE:FREQ=DAILY;COUNT=2"], "reminders": { "overrides": [ {"method": "email", "minutes": 1440}, {"method": "popup", "minutes": 10}, ], "useDefault": False, }, "start": { "dateTime": "2015-05-28T09:00:00-07:00", "timeZone": "America/Los_Angeles", }, "summary": "Google I/O 2015", } e = Event( date_parse("march 16, 2019 10:00 am"), date_parse("march 16, 2019 3:30 pm"), "Hang out with Matt", ) path = r"C:\Users\Raphael\Documents\local_repo\cred" my_api = my_api = calendar_api( "python", os.path.join(path, "client_secret.json", path), path ) cal_id = "raphael.roberts48@gmail.com" e2 = Event.from_id(my_api, cal_id, "qmrsd88ma8ko67ri98d8pbhd7s") until = datetime.datetime.today() + datetime.timedelta(days=20) e2.add_weekly_recurrence(until, MON, TUE) # e2.upload(my_api, cal_id)
|