gcal-commander
Version:
A command-line interface for Google Calendar operations
148 lines (147 loc) • 5.76 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CalendarService = void 0;
const googleapis_1 = require("googleapis");
const promises_1 = require("node:fs/promises");
const tsyringe_1 = require("tsyringe");
const tokens_1 = require("../di/tokens");
const paths_1 = require("../utils/paths");
let CalendarService = class CalendarService {
authService;
calendar = null;
hasReauthenticated = false;
constructor(authService) {
this.authService = authService;
}
async createEvent(params) {
return this.withRetryOnScopeError(async () => {
await this.ensureInitialized();
const eventResource = {
description: params.description,
end: params.end,
location: params.location,
start: params.start,
summary: params.summary,
};
if (params.attendees?.length) {
eventResource.attendees = params.attendees.map((email) => ({ email }));
}
try {
const response = await this.calendar.events.insert({
calendarId: params.calendarId,
requestBody: eventResource,
sendUpdates: params.sendUpdates || 'none',
});
return response.data;
}
catch (error) {
throw new Error(`Failed to create event: ${error}`);
}
});
}
async getEvent(eventId, calendarId = 'primary') {
return this.withRetryOnScopeError(async () => {
await this.ensureInitialized();
try {
const response = await this.calendar.events.get({
calendarId,
eventId,
});
return response.data;
}
catch (error) {
throw new Error(`Failed to get event: ${error}`);
}
});
}
async listCalendars() {
return this.withRetryOnScopeError(async () => {
await this.ensureInitialized();
try {
const response = await this.calendar.calendarList.list();
return response.data.items || [];
}
catch (error) {
throw new Error(`Failed to list calendars: ${error}`);
}
});
}
async listEvents(params) {
return this.withRetryOnScopeError(async () => {
await this.ensureInitialized();
const { calendarId, maxResults, timeMax, timeMin } = params;
try {
const response = await this.calendar.events.list({
calendarId,
maxResults,
orderBy: 'startTime',
singleEvents: true,
timeMax,
timeMin,
});
return response.data.items || [];
}
catch (error) {
throw new Error(`Failed to list events: ${error}`);
}
});
}
async deleteTokenAndReinitialize() {
const TOKEN_PATH = paths_1.AppPaths.getTokenPath();
try {
await (0, promises_1.unlink)(TOKEN_PATH);
// Token deleted, will re-authenticate with updated permissions
}
catch {
// Token file might not exist, which is fine
}
this.calendar = null;
this.hasReauthenticated = true;
await this.ensureInitialized();
}
async ensureInitialized() {
if (!this.calendar) {
const auth = await this.authService.getCalendarAuth();
this.calendar = googleapis_1.google.calendar({ auth: auth.client, version: 'v3' });
}
}
isScopeError(error) {
const errorString = String(error);
return (errorString.includes('insufficient authentication scopes') ||
errorString.includes('Request had insufficient authentication scopes') ||
errorString.includes('access_denied') ||
errorString.includes('scope') ||
errorString.includes('401') ||
errorString.includes('403'));
}
async withRetryOnScopeError(operation) {
try {
return await operation();
}
catch (error) {
if (this.isScopeError(error) && !this.hasReauthenticated) {
await this.deleteTokenAndReinitialize();
return operation();
}
throw error;
}
}
};
exports.CalendarService = CalendarService;
exports.CalendarService = CalendarService = __decorate([
(0, tsyringe_1.injectable)(),
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.AuthService)),
__metadata("design:paramtypes", [Object])
], CalendarService);