Google calender API getting started

拥有回忆 提交于 2021-01-29 15:00:39

问题


I'm trying to get familiar with the google calendar api. In the getting started guide they have this code example:

from __future__ import print_function
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']


def main():
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    # Call the Calendar API
    now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
    print('Getting the upcoming 10 events')
    events_result = service.events().list(calendarId='primary', timeMin=now,
                                        maxResults=10, singleEvents=True,
                                        orderBy='startTime').execute()
    events = events_result.get('items', [])

    if not events:
        print('No upcoming events found.')
    for event in events:
        start = event['start'].get('dateTime', event['start'].get('date'))
        print(start, event['summary'])


if __name__ == '__main__':
    main()

In this example we automatically open a window to ask the user to access their calendar, if we don't already have access through the pickle file. The thing is I don't want this window to open automatically, I want to print a link instead that the user can click to authenticate. I have looked around in the documentation but can't seem to find anything usefull. I would appriciate any help i could get, thanks!


回答1:


  • For authorizing process, you want to show only the URL. You don't want to automatically open the browser.
  • You want to achieve this using googleapis with python.

If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.

In this case, please use Flow.from_client_secrets_file instead of InstalledAppFlow.from_client_secrets_file.

Modified script:

When your script is modified, please modify as follows.

From:

from google_auth_oauthlib.flow import InstalledAppFlow

To:

from google_auth_oauthlib.flow import Flow

and

From:

if os.path.exists('token.pickle'):
    with open('token.pickle', 'rb') as token:
        creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file(
            'credentials.json', SCOPES)
        creds = flow.run_local_server(port=0)
    # Save the credentials for the next run
    with open('token.pickle', 'wb') as token:
        pickle.dump(creds, token)

service = build('calendar', 'v3', credentials=creds)

To:

if os.path.exists('token.pickle'):
    with open('token.pickle', 'rb') as token:
        creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        # Create the flow using the client secrets file from the Google API
        # Console.
        flow = Flow.from_client_secrets_file('client_secret.json', SCOPES, redirect_uri='urn:ietf:wg:oauth:2.0:oob')

        # Tell the user to go to the authorization URL.
        auth_url, _ = flow.authorization_url(prompt='consent')

        print('Please go to this URL: {}'.format(auth_url))

        # The user will get an authorization code. This code is used to get the
        # access token.
        code = input('Enter the authorization code: ')
        flow.fetch_token(code=code)
        creds = flow.credentials

    # Save the credentials for the next run
    with open('token.pickle', 'wb') as token:
        pickle.dump(creds, token)

service = build('calendar', 'v3', credentials=creds)
  • In this case, when you run the script under token.pickle is not existing, the URL for the authorization is displayed to the console. The browser is not opened. So please access to the URL by opening the browser and authorize the scopes. Then, please the copied authorization code to the console and input enter key. By this, the access token is retrieved and the file of token.pickle is created.

Note:

  • If an error related to the redirect uri occurs, please modify it to http://localhost and test it again.

Reference:

  • google_auth_oauthlib.flow module

If I misunderstood your question and this was not the direction you want, I apologize.

Added:

  • From I want to print a link instead that the user can click to authenticate in your question, I proposed above sample script.
  • From some way not to manually confirm authorization codes in your replying, I think that that above sample script is not suitable.

In this case, how about using the service account? When the service account is used, no authorization code is required. The script for using the service account is as follows.

Sample script:

from google.oauth2 import service_account
from googleapiclient.discovery import build

SERVICE_ACCOUNT_FILE = 'service-account-credentials.json'  # Here, please set the creadential file of the service account.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)

service = build('calendar', 'v3', credentials=creds)

Note:

  • In order to access to the Google calendar using the service account, at first, please share the Google calendar with the email of the service account. Please be careful this.

Reference:

  • Creating a service account


来源:https://stackoverflow.com/questions/60667025/google-calender-api-getting-started

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!