Code Monkey home page Code Monkey logo

google-calendar-simple-api's Introduction

Google Calendar Simple API

PyPi Package

Documentation Status

Tests

Discord

Google Calendar Simple API or gcsa is a library that simplifies event and calendar management in Google Calendars. It is a Pythonic object oriented adapter for the official API. See the full documentation.

Installation

pip install gcsa

See Getting started page for more details and installation options.

Example usage

List events

from gcsa.google_calendar import GoogleCalendar

calendar = GoogleCalendar('[email protected]')
for event in calendar:
    print(event)

Create event

from gcsa.event import Event

event = Event(
    'The Glass Menagerie',
    start=datetime(2020, 7, 10, 19, 0),
    location='Záhřebská 468/21',
    minutes_before_popup_reminder=15
)
calendar.add_event(event)

Create recurring event

from gcsa.recurrence import Recurrence, DAILY

event = Event(
    'Breakfast',
    start=date(2020, 7, 16),
    recurrence=Recurrence.rule(freq=DAILY)
)
calendar.add_event(event)

Suggestion: use beautiful_date to create date and datetime objects in your projects (because its beautiful... just like you).

References

Template for setup.py was taken from kennethreitz/setup.py

google-calendar-simple-api's People

Contributors

abdur-rahmaanj avatar alexander-minchin avatar dependabot[bot] avatar hroncok avatar jaonewguy avatar julesgrd avatar kenomaerz avatar kuzmoyev avatar louispotok avatar mstuebner avatar ofekedri avatar pschmitt avatar randomnameuser avatar seanbreckenridge avatar vpoulailleau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

google-calendar-simple-api's Issues

WinError 10013 when trying to create calendar object

I think this is potentially due to either attempting to run this on a computer that's managed by my organization or something, but when I try to just run the first line to instantiate a "calendar" object, I get this error:

Traceback (most recent call last):
  File "test2.py", line 8, in <module>
    calendar = GoogleCalendar('[email protected]')
  File "E:\_TemporaryBetaCode\CalendarBooker\google-calendar-simple-api\gcsa\google_calendar.py", line 56, in __init__
    credentials = self._get_credentials()
  File "E:\_TemporaryBetaCode\CalendarBooker\google-calendar-simple-api\gcsa\google_calendar.py", line 73, in _get_credentials
    credentials = flow.run_local_server()
  File "C:\Users\sit\Anaconda3\lib\site-packages\google_auth_oauthlib\flow.py", line 442, in run_local_server
    local_server = wsgiref.simple_server.make_server(
  File "C:\Users\sit\Anaconda3\lib\wsgiref\simple_server.py", line 154, in make_server
    server = server_class((host, port), handler_class)
  File "C:\Users\sit\Anaconda3\lib\socketserver.py", line 452, in __init__
    self.server_bind()
  File "C:\Users\sit\Anaconda3\lib\wsgiref\simple_server.py", line 50, in server_bind
    HTTPServer.server_bind(self)
  File "C:\Users\sit\Anaconda3\lib\http\server.py", line 138, in server_bind
    socketserver.TCPServer.server_bind(self)
  File "C:\Users\sit\Anaconda3\lib\socketserver.py", line 466, in server_bind
    self.socket.bind(self.server_address)
OSError: [WinError 10013] An attempt was made to access a socket in a way forbidden by its access permissions

Start point for GoogleCalendar iteration is off.

If I use

for event in calendar:
    print(event)

and there is an event on the current day, but it happens fairly soon, that event will not be printed. Say for example, it is currently 2:00PM and I have an Event at 3:30PM.

Allow different ways of retrieving an access_/refresh_token

Oh @kuzmoyev I was just checking the code. Would it be possible for me to pass access_token and refresh_token for using the user's Google Calendar ?

My workflow is as follows:

  1. A user signs up using his google account and I get the offline access to his calendar.
  2. I use this auth tokens for performing some action on user's calendar.

Right now, I think gcsa only accepts credentials file path for access.

Is there a workaround with this? 🤔

Originally posted by @raju249 in #42 (comment)

Add get_event() method

I required a way to get a single events by id, so I quickly put one together. I can beautify it make a PR, if wanted.

calendar.clear() function needs correction

Hello, a small change in the module is needed to get the calendar.clear() function to work.

When using the calendar.clear() statement as found in the docs the following traceback occurs:

Traceback (most recent call last):
   File "test.py", line 32, in <module>
     calendar.clear()
   File "....\lib\site-packages\gcsa\google_calendar.py", line 146, in clear
     self.service.calendars().clear(self.calendar).execute()
TypeError: method() takes 1 positional argument but 2 were given

After changing line 146 in file google_calendar.py from:

self.service.calendars().clear(self.calendar).execute()

to:

self.service.calendars().clear(calendarId=self.calendar).execute()

the call worked as expected.

Used environment:

Python 3.8.6 on Windows 10x64

gcsa-1.0.0.dist-info
googleapis_common_protos-1.52.0-py3.8.egg
google_api_core-1.20.0-py3.8.egg
google_api_python_client-1.9.3-py3.8.egg
google_auth-1.17.2-py3.8.egg
google_auth_httplib2-0.0.4.dist-info
google_auth_oauthlib-0.4.2.dist-info

Thank you

Deleting Events

I am running into a 'str is not callable error' when trying to delete events. The problem seems to be in google_calendar.py:110 (GoogleCalendar::delete_event()). It should be

if event.event_id is None:

instead of

if event.event_id() is None:

Making that change seems to fix it for me.

Thanks!

Is there a way to add timeout, when Google browser popup is closed?

Right now, if you close the browser window, the script will hang, waiting for user permission.

Is there a way to add a timeout?

For example, the local server:

credentials = flow.run_local_server()

If there are no credentials returned for 1 minute, close local server, and return error.

Support multiple google accounts

Hi, thanks for maintaining this; having dealt with google sheets directly in the past this is a much nicer interface.

I have multiple accounts that I want to periodically back up, so I have multiple credential.json files, one which has API access to each google account.

Currently, this writes to the same static token.pickle file to save credentials, so I can't use multiple files.

It fails with an error like:

    events = self.service.events().list(calendarId=self.calendar,
  File "/home/sean/.local/lib/python3.8/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/home/sean/.local/lib/python3.8/site-packages/googleapiclient/http.py", line 907, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://www.googleapis.com/calendar/v3/calendars/email-here/events?timeMin=1900-01-01T00%3A00%3A00-07%3A53&timeMax=2100-01-01T23%3A59%3A59.999999-08%3A00&orderBy=startTime&singleEvents=true&alt=json returned "Not Found">

... presumably because the email I'm requesting doesn't match the old credentials.

I think this could be pretty easily fixed by adding another kwarg to the GoogleCalendar constructor to specify a different pickle filepath.

I can create a PR if you're willing to merge that in. I haven't worked with readthedocs before, but I would think I just add the parameter here?

Perhaps the default could be token.pickle (which gets combined into os.path.join(self._credential_dir, 'token.pickle')?; if a kwarg is provided it overwrites that filepath. Save that as self._token_path in __init__ and then access that in get_credentials? Not too sure on how that should handle a filename like other_token.pickle vs a full path provided by the user/how that'd be documented in readthedocs.

Edit: realized its possible to do this if I put my credentials in different directories, but that seems like a bit of a hack.

Token Refresh Failing

I do not know if this is something I am doing wrong, but after I authorize a flow and the token.pickle is created in my credentials the token fails to refresh. If I delete the token and run my script I have to authorize the flow again from a web browser, then I can use that token for a few minutes. Afterwards I have to delete it and authorize the flow again.

gadget_serializer: KeyError when fetching events from Contacts calendar

Google Calendar has a built-in calendar called "Contacts" (id: addressbook#[email protected]) that syncs with some data like birthdays from Google Contacts, but these events seems to be somewhat special as their gadget-JSON is different from others, as it is missing most paramentes:

{'iconLink': 'https://calendar.google.com/googlecalendar/images/cake.gif', 'preferences': {'goo.contactsGivenName': 'Isabela', 'goo.contactsEventType': 'BIRTHDAY', 'goo.contactsFullName': 'Isabela', 'goo.isGPlusUser': 'false', 'goo.contactsContactId': '123a4b5c6d89efgh', 'goo.contactsIsMyContact': 'true'}}

This difference means GCSA raises an Exception when serializing such events:

  File "C:/Users/eitch/PycharmProjects/gcal2todoist/code/scratch.py", line 11, in <module>
    for event in a:
  File "C:\Users\eitch\PycharmProjects\gcal2todoist\venv\lib\site-packages\gcsa\google_calendar.py", line 183, in get_events
    event = EventSerializer(event_json).get_object()
  File "C:\Users\eitch\PycharmProjects\gcal2todoist\venv\lib\site-packages\gcsa\serializers\base_serializer.py", line 20, in get_object
    return self.to_object(self.data)
  File "C:\Users\eitch\PycharmProjects\gcal2todoist\venv\lib\site-packages\gcsa\serializers\base_serializer.py", line 38, in to_object
    return cls._to_object(json_)
  File "C:\Users\eitch\PycharmProjects\gcal2todoist\venv\lib\site-packages\gcsa\serializers\event_serializer.py", line 94, in _to_object
    gadget = GadgetSerializer.to_object(gadget_json) if gadget_json else None
  File "C:\Users\eitch\PycharmProjects\gcal2todoist\venv\lib\site-packages\gcsa\serializers\base_serializer.py", line 38, in to_object
    return cls._to_object(json_)
  File "C:\Users\eitch\PycharmProjects\gcal2todoist\venv\lib\site-packages\gcsa\serializers\gadget_serializer.py", line 34, in _to_object
    title=json_gadget['title'],
KeyError: 'title'

How to move to other calendar

I fully expect this to be silly user error, but I'm stumped and would appreciate input:
After the initial Google Calendar API registration, everything worked fine. I now want to move to another calendar. What I did:

  1. Activate the new calendar's api using https://developers.google.com/calendar/quickstart/python#step_1_turn_on_the (Selected "Dektop", AFAIK that is what gcsa requires?)
  2. Replace the client_secret.json

After restarting the app, I can still only access the calendar from my original account, not the new one. No authorization window is popping up. What am I missing?

Enable sending of invitations

It would be a relevant use case for me to send invitations to attendees. As far as I understand, this is not currently possible with gcsa. Are there any plans to support this? Would you be willing to accept a pull request? (no promises yet on delivery)

problems specifying a calendar from my google account

I don't know how to specify a calendar named 'FJD' in order to create a new event.

It only creates one in my primary calendar.

this is my code:

from gcsa.event import Event
from gcsa.google_calendar import GoogleCalendar

from beautiful_date import Feb

calendar = GoogleCalendar('[email protected]')
event = Event(
    'Python test',
    start=(25 / Feb / 2020)[20:00],
    minutes_before_email_reminder=50
)

calendar.add_event(event)

Thank you in advance.

Typo in interval handling

I'm getting exception when trying to set an interval in the Recurrence. I think the problem is line 447 in recurrence.py should be

if interval and (not isinstance(interval, int) or interval < 1):

instead of

if interval and (isinstance(interval, int) or interval < 1):

That seems to fix it for me, at least. ;)

Add support for conference data

Would be really helpful if someone can provide an example that helps adding the Google Meet link in the Calendar Event.

I am searching for this myself, if I get it first, I will post the solution here.

Thanks 🙏

404 Error when updating recurring events

The google API throws a 404 when trying to update instances of recurring events. Tested on the newest dev, was present on 0.4 as well. The parameters sent by gcsa seem to be correct to me, google must expect some special treatment of series when updating that I do not understand yet.

Recurrence missing 'until' option

Recurrence handling is missing one of the most important options: giving an end date for the repeating event (UNTIL).

The following patch works for me, but can probably take some polishing:

$ diff -c3 recurrence.py recurrence.py.orig
*** recurrence.py       2020-05-24 00:27:54.917591200 -0400
--- recurrence.py.orig  2020-05-23 23:50:52.821505600 -0400
***************
*** 122,128 ****
              freq=DAILY,
              interval=None,
              count=None,
-             until=None,
              by_second=None,
              by_minute=None,
              by_hour=None,
--- 122,127 ----
***************
*** 143,150 ****
                  positive integer representing how often the recurrence rule repeats
          :param count:
                  number of occurrences at which to range-bound the recurrence
-         :param until:
-                 end date of recurrence
          :param by_second:
                  second or list of seconds within a minute. Valid values are 0 to 60
          :param by_minute:
--- 142,147 ----
***************
*** 182,188 ****

          .. _`RRULE format`: https://tools.ietf.org/html/rfc5545#section-3.8.5
          """
!         return 'RRULE:' + Recurrence._rule(freq, interval, count, until, by_second, by_minute, by_hour, by_week_day,
                                             by_month_day, by_year_day, by_week, by_month, by_set_pos, week_start)

      @staticmethod
--- 179,185 ----

          .. _`RRULE format`: https://tools.ietf.org/html/rfc5545#section-3.8.5
          """
!         return 'RRULE:' + Recurrence._rule(freq, interval, count, by_second, by_minute, by_hour, by_week_day,
                                             by_month_day, by_year_day, by_week, by_month, by_set_pos, week_start)

      @staticmethod
***************
*** 190,196 ****
              freq=DAILY,
              interval=None,
              count=None,
-             until=None,
              by_second=None,
              by_minute=None,
              by_hour=None,
--- 187,192 ----
***************
*** 211,218 ****
                  positive integer representing how often the recurrence rule repeats
          :param count:
                  number of occurrences at which to range-bound the recurrence
-         :param until:
-                 end date of recurrence
          :param by_second:
                  second or list of seconds within a minute. Valid values are 0 to 60
          :param by_minute:
--- 207,212 ----
***************
*** 250,256 ****

          .. _`RRULE format`: https://tools.ietf.org/html/rfc5545#section-3.8.5
          """
!         return 'EXRULE:' + Recurrence._rule(freq, interval, count, until, by_second, by_minute, by_hour, by_week_day,
                                              by_month_day, by_year_day, by_week, by_month, by_set_pos, week_start)

      @staticmethod
--- 244,250 ----

          .. _`RRULE format`: https://tools.ietf.org/html/rfc5545#section-3.8.5
          """
!         return 'EXRULE:' + Recurrence._rule(freq, interval, count, by_second, by_minute, by_hour, by_week_day,
                                              by_month_day, by_year_day, by_week, by_month, by_set_pos, week_start)

      @staticmethod
***************
*** 399,405 ****
              freq=DAILY,
              interval=None,
              count=None,
-             until=None,
              by_second=None,  # BYSECOND
              by_minute=None,  # BYMINUTE
              by_hour=None,  # BYHOUR
--- 393,398 ----
***************
*** 420,427 ****
                  positive integer representing how often the recurrence rule repeats
          :param count:
                  number of occurrences at which to range-bound the recurrence
-         :param until:
-                 end date of recurrence
          :param by_second:
                  second or list of seconds within a minute. Valid values are 0 to 60
          :param by_minute:
--- 413,418 ----
***************
*** 490,502 ****
              raise ValueError('"count" parameter must be a positive int. '
                               '{} was provided'.format(count))

-         if until:
-             if not isinstance(until, (date, datetime)):
-                 msg = 'The until object must be a date or datetime, not {!r}.'.format(end.__class__.__name__)
-                 raise TypeError(msg)
-             else:
-                 until = until.strftime("%Y%m%dT%H%M%SZ")
-
          by_second = assure_iterable(by_second)
          check_all_type_and_range(by_second, int, (0, 60), "by_second")

--- 481,486 ----
***************
*** 537,543 ****
          rule_properties = (
              ('INTERVAL', interval),
              ('COUNT', count),
-             ('UNTIL', until),
              ('BYSECOND', to_string(by_second)),
              ('BYMINUTE', to_string(by_minute)),
              ('BYHOUR', to_string(by_hour)),
--- 521,526 ----

Hope it helps!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.