Search code examples
node.jstypescriptgoogle-apigoogle-calendar-apigoogle-oauth

Google node sdk Calendar freebusy query not returning time for private calendars


I'm trying to get free / busy times for a user which I've previously oauthed and have their access token and refresh token stored in my DB, but for some reason, I keep getting the following response:

data: {
        kind: 'calendar#freeBusy',
        timeMin: '2019-09-14T23:49:03.000Z',
        timeMax: '2019-09-20T07:00:00.000Z',
        calendars: {
          '[email protected]': {
            errors: [ { domain: 'global', reason: 'notFound' } ],
            busy: []
          }
        }
      },

Here is my code to set up the request:

import { ICalendarService } from './ICalendarService'
import { google } from 'googleapis'
import { Match, User } from '../../entities'
import * as moment from 'moment-timezone'
import { MatchService } from '../MatchService'
import { Errors } from '../../constants'
import { Logger } from '../../utils'
import { inspect } from 'util'

export class GoogleCalendarService implements ICalendarService {
    private calendar
    private oauth2client

    public constructor() {
        Logger.info(`GoogleCalendarService()`)

        this.calendar = google.calendar({
            version: 'v3',
            auth: process.env.GOOGLE_CALENDAR_API_KEY
        })

    }

/**
     * Gets free and busy times for a given user
     * @param user
     */
    public async getFreeBusy(user: User) {
        this.oauth2client = new google.auth.OAuth2(
            process.env.GOOGLE_CALENDAR_CLIENT_ID,
            process.env.GOOGLE_CALENDAR_CLIENT_SECRET,
            `postmessage`
        )

        this.oauth2client.setCredentials({
            access_token: user.googleAccessToken,
            refresh_token: user.googleRefreshToken
        })

        this.oauth2client.on(`tokens`, tokens => {
            Logger.info(`GoogleCalendarService.onTokens: ${inspect(tokens)}`)
        })

        this.calendar = google.calendar({
            version: 'v3',
            auth: process.env.GOOGLE_CALENDAR_API_KEY
        })

        const freeBusy = await this.calendar.freebusy.query(
            {
                resource: {
                    timeMin: moment().toISOString(),
                    timeMax: moment(MatchService.getMatchCycleEndDate()).toISOString(),
                    items: [{ id: user.email }]
                }
            }       )

        return freeBusy
    }
}

I've confirmed this code works for calendars that are public, but not private ones. Anybody know what I'm doing wrong?


Solution

  • So, I figured this out. I needed to add my oauth2client with credentials set as part of the query.

    e.g.

    this.oauth2client.credentials = {
        access_token: user.googleAccessToken,
        refresh_token: user.googleRefreshToken
    }
    
    const response = await this.calendar.freebusy.query({
                auth: this.oauth2client,
                resource: {
                    timeMin: moment
                        .tz(user.timezone)
                        .add(1, 'day')
                        .startOf('day')
                        .toISOString(),
                    timeMax: moment(MatchService.getMatchCycleEndDate())
                        .tz(user.timezone)
                        .toISOString(),
                    items: [{ id: user.email }]
                }
            })