gcal-commander
Version:
A command-line interface for Google Calendar operations
167 lines (166 loc) • 6.93 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@oclif/core");
const base_command_1 = require("../../base-command");
class EventsCreate extends base_command_1.BaseCommand {
static args = {
summary: core_1.Args.string({
description: 'Event title/summary',
required: true,
}),
};
static description = 'Create a new calendar event';
static examples = [
'<%= config.bin %> <%= command.id %> "Team Meeting" --start "2024-01-15T14:00:00"',
'<%= config.bin %> <%= command.id %> "Lunch" --start "2024-01-15T12:00:00" --duration 60',
'<%= config.bin %> <%= command.id %> "Conference" --start "2024-01-15" --all-day',
'<%= config.bin %> <%= command.id %> "Project Review" --start "2024-01-15T14:00:00" --end "2024-01-15T16:00:00" --location "Room A"',
];
static flags = {
...base_command_1.BaseCommand.baseFlags,
'all-day': core_1.Flags.boolean({
description: 'Create all-day event',
}),
attendees: core_1.Flags.string({
description: 'Comma-separated list of attendee emails',
}),
calendar: core_1.Flags.string({
char: 'c',
default: 'primary',
description: 'Calendar ID to create event in',
}),
description: core_1.Flags.string({
description: 'Event description',
}),
duration: core_1.Flags.integer({
char: 'd',
description: 'Duration in minutes (alternative to --end)',
}),
end: core_1.Flags.string({
char: 'e',
description: 'End date/time (ISO format)',
}),
location: core_1.Flags.string({
char: 'l',
description: 'Event location',
}),
'send-updates': core_1.Flags.string({
default: 'none',
description: 'Send event invitations',
options: ['all', 'externalOnly', 'none'],
}),
start: core_1.Flags.string({
char: 's',
description: 'Start date/time (ISO format)',
required: true,
}),
};
async run() {
const { args, flags } = await this.parse(EventsCreate);
try {
await this.initI18nService();
this.logStatus(this.t('events.create.authenticating'));
await this.initCalendarService();
// Validate mutual exclusion of end and duration
if (flags.end && flags.duration) {
this.logError(this.t('events.create.errors.conflictingFlags'));
}
// Parse start time
const startTime = this.parseDateTime(flags.start, flags['all-day']);
// Calculate end time
let endTime;
if (flags.end) {
endTime = this.parseDateTime(flags.end, flags['all-day']);
}
else if (flags.duration) {
endTime = this.calculateEndTime(startTime, flags.duration, flags['all-day']);
}
else {
// Default to 1 hour duration
endTime = this.calculateEndTime(startTime, 60, flags['all-day']);
}
// Parse attendees
const attendees = flags.attendees ? flags.attendees.split(',').map((email) => email.trim()) : undefined;
// Create event parameters
const createParams = {
attendees,
calendarId: flags.calendar,
description: flags.description,
end: endTime,
location: flags.location,
sendUpdates: flags['send-updates'],
start: startTime,
summary: args.summary,
};
this.logStatus(this.t('events.create.creating'));
const event = await this.calendarService.createEvent(createParams);
if (this.format === 'json' || this.format === 'pretty-json') {
this.outputJson(event);
}
else {
this.displayEventCreated(event);
}
}
catch (error) {
this.logError(this.t('events.create.errors.failed', { error }));
}
}
calculateEndTime(startTime, durationMinutes, isAllDay) {
if (isAllDay && // For all-day events, add 1 day
startTime.date) {
const startDate = new Date(startTime.date);
startDate.setDate(startDate.getDate() + 1);
return { date: startDate.toISOString().split('T')[0] };
}
if (startTime.dateTime) {
const startDate = new Date(startTime.dateTime);
startDate.setMinutes(startDate.getMinutes() + durationMinutes);
return { dateTime: startDate.toISOString() };
}
throw new Error(this.t('events.create.errors.invalidStartTime'));
}
displayEventCreated(event) {
this.logResult(this.t('events.create.success') + '\n');
this.logResult(`${this.t('events.create.labels.title')}: ${event.summary || this.t('events.create.noTitle')}`);
this.logResult(`${this.t('events.create.labels.id')}: ${event.id}`);
if (event.start) {
if (event.start.date) {
this.logResult(`${this.t('events.create.labels.date')}: ${new Date(event.start.date).toLocaleDateString()}`);
}
else if (event.start.dateTime) {
this.logResult(`${this.t('events.create.labels.start')}: ${new Date(event.start.dateTime).toLocaleString()}`);
}
}
if (event.end && event.end.dateTime) {
this.logResult(`${this.t('events.create.labels.end')}: ${new Date(event.end.dateTime).toLocaleString()}`);
}
if (event.location) {
this.logResult(`${this.t('events.create.labels.location')}: ${event.location}`);
}
if (event.htmlLink) {
this.logResult(`${this.t('events.create.labels.googleCalendarLink')}: ${event.htmlLink}`);
}
this.logResult('');
}
parseDateTime(dateTimeString, isAllDay) {
if (isAllDay) {
// For all-day events, expect YYYY-MM-DD format
if (!/^\d{4}-\d{2}-\d{2}$/.test(dateTimeString)) {
throw new Error(this.t('events.create.errors.allDayDateFormat'));
}
return { date: dateTimeString };
}
// For timed events, expect ISO format
try {
const date = new Date(dateTimeString);
if (Number.isNaN(date.getTime())) {
throw new TypeError(this.t('events.create.errors.invalidDateFormat'));
}
return { dateTime: date.toISOString() };
}
catch {
throw new Error(this.t('events.create.errors.invalidDateTimeFormat'));
}
}
}
exports.default = EventsCreate;