@bobfrankston/gcal 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/gcal.ts +6 -67
- package/glib/gutils.ts +5 -16
- package/package.json +50 -46
package/gcal.ts
CHANGED
|
@@ -90,8 +90,7 @@ async function listEvents(
|
|
|
90
90
|
accessToken: string,
|
|
91
91
|
calendarId = 'primary',
|
|
92
92
|
maxResults = 10,
|
|
93
|
-
timeMin?: string
|
|
94
|
-
timeMax?: string
|
|
93
|
+
timeMin?: string
|
|
95
94
|
): Promise<GoogleEvent[]> {
|
|
96
95
|
const params = new URLSearchParams({
|
|
97
96
|
maxResults: maxResults.toString(),
|
|
@@ -99,9 +98,6 @@ async function listEvents(
|
|
|
99
98
|
orderBy: 'startTime',
|
|
100
99
|
timeMin: timeMin || new Date().toISOString()
|
|
101
100
|
});
|
|
102
|
-
if (timeMax) {
|
|
103
|
-
params.set('timeMax', timeMax);
|
|
104
|
-
}
|
|
105
101
|
|
|
106
102
|
const url = `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events?${params}`;
|
|
107
103
|
const res = await apiFetch(url, accessToken);
|
|
@@ -243,19 +239,14 @@ Options:
|
|
|
243
239
|
-defaultUser <email> Set default user for future use
|
|
244
240
|
-c, -calendar <id> Calendar ID (default: primary)
|
|
245
241
|
-n <count> Number of events to list
|
|
246
|
-
-
|
|
247
|
-
-before <when> List events before this date/time
|
|
248
|
-
-verbose Show event IDs and links
|
|
249
|
-
-v, --version Show version
|
|
242
|
+
-v, -verbose Show event IDs and links
|
|
250
243
|
|
|
251
244
|
Examples:
|
|
252
245
|
gcal meeting.ics Import ICS file
|
|
253
246
|
gcal list List next 10 events
|
|
254
|
-
gcal list -after tomorrow -before "jan 30"
|
|
255
247
|
gcal add "Dentist" "Friday 3pm" "1h"
|
|
256
248
|
gcal add "Lunch" "1/14/2026 12:00" "1h"
|
|
257
|
-
gcal add "Meeting" "tomorrow
|
|
258
|
-
gcal add "Call" "3pm" "30m"
|
|
249
|
+
gcal add "Meeting" "tomorrow 10:00"
|
|
259
250
|
gcal add "Appointment" "jan 15 2pm"
|
|
260
251
|
gcal -defaultUser bob@gmail.com Set default user
|
|
261
252
|
|
|
@@ -274,10 +265,7 @@ interface ParsedArgs {
|
|
|
274
265
|
count: number;
|
|
275
266
|
help: boolean;
|
|
276
267
|
verbose: boolean;
|
|
277
|
-
version: boolean;
|
|
278
268
|
icsFile: string; /** Direct .ics file path */
|
|
279
|
-
after: string; /** Filter: events after this date/time */
|
|
280
|
-
before: string; /** Filter: events before this date/time */
|
|
281
269
|
}
|
|
282
270
|
|
|
283
271
|
function parseArgs(argv: string[]): ParsedArgs {
|
|
@@ -290,10 +278,7 @@ function parseArgs(argv: string[]): ParsedArgs {
|
|
|
290
278
|
count: 10,
|
|
291
279
|
help: false,
|
|
292
280
|
verbose: false,
|
|
293
|
-
|
|
294
|
-
icsFile: '',
|
|
295
|
-
after: '',
|
|
296
|
-
before: ''
|
|
281
|
+
icsFile: ''
|
|
297
282
|
};
|
|
298
283
|
|
|
299
284
|
const unknown: string[] = [];
|
|
@@ -318,23 +303,11 @@ function parseArgs(argv: string[]): ParsedArgs {
|
|
|
318
303
|
case '-n':
|
|
319
304
|
result.count = parseInt(argv[++i]) || 10;
|
|
320
305
|
break;
|
|
321
|
-
case '-
|
|
322
|
-
case '--after':
|
|
323
|
-
result.after = argv[++i] || '';
|
|
324
|
-
break;
|
|
325
|
-
case '-before':
|
|
326
|
-
case '--before':
|
|
327
|
-
result.before = argv[++i] || '';
|
|
328
|
-
break;
|
|
306
|
+
case '-v':
|
|
329
307
|
case '-verbose':
|
|
330
308
|
case '--verbose':
|
|
331
309
|
result.verbose = true;
|
|
332
310
|
break;
|
|
333
|
-
case '-v':
|
|
334
|
-
case '-V':
|
|
335
|
-
case '--version':
|
|
336
|
-
result.version = true;
|
|
337
|
-
break;
|
|
338
311
|
case '-h':
|
|
339
312
|
case '-help':
|
|
340
313
|
case '--help':
|
|
@@ -405,12 +378,6 @@ async function main(): Promise<void> {
|
|
|
405
378
|
}
|
|
406
379
|
}
|
|
407
380
|
|
|
408
|
-
if (parsed.version) {
|
|
409
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(import.meta.dirname, 'package.json'), 'utf-8'));
|
|
410
|
-
console.log(`gcal ${pkg.version}`);
|
|
411
|
-
process.exit(0);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
381
|
if (parsed.help) {
|
|
415
382
|
showUsage();
|
|
416
383
|
process.exit(0);
|
|
@@ -461,9 +428,7 @@ async function main(): Promise<void> {
|
|
|
461
428
|
case 'list': {
|
|
462
429
|
const count = parsed.args[0] ? parseInt(parsed.args[0]) : parsed.count;
|
|
463
430
|
const token = await getAccessToken(user, false);
|
|
464
|
-
const
|
|
465
|
-
const timeMax = parsed.before ? parseDateTime(parsed.before).toISOString() : undefined;
|
|
466
|
-
const events = await listEvents(token, parsed.calendar, count, timeMin, timeMax);
|
|
431
|
+
const events = await listEvents(token, parsed.calendar, count);
|
|
467
432
|
|
|
468
433
|
if (events.length === 0) {
|
|
469
434
|
console.log('No upcoming events found.');
|
|
@@ -519,32 +484,6 @@ async function main(): Promise<void> {
|
|
|
519
484
|
const durationMins = parseDuration(duration);
|
|
520
485
|
const endTime = new Date(startTime.getTime() + durationMins * 60 * 1000);
|
|
521
486
|
|
|
522
|
-
// Check for suspicious dates (likely parsing errors)
|
|
523
|
-
const now = new Date();
|
|
524
|
-
const twoYearsFromNow = new Date(now);
|
|
525
|
-
twoYearsFromNow.setFullYear(twoYearsFromNow.getFullYear() + 2);
|
|
526
|
-
|
|
527
|
-
let warning = '';
|
|
528
|
-
if (startTime < now) {
|
|
529
|
-
warning = `Date is in the past: ${formatDateTime({ dateTime: startTime.toISOString() })}`;
|
|
530
|
-
} else if (startTime > twoYearsFromNow) {
|
|
531
|
-
warning = `Date is more than 2 years away: ${formatDateTime({ dateTime: startTime.toISOString() })}`;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
if (warning) {
|
|
535
|
-
console.log(`\nWarning: ${warning}`);
|
|
536
|
-
console.log(`Input was: "${when}"`);
|
|
537
|
-
const readline = await import('readline');
|
|
538
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
539
|
-
const response = await new Promise<string>(resolve => {
|
|
540
|
-
rl.question('Continue? (y/N) ', answer => { rl.close(); resolve(answer); });
|
|
541
|
-
});
|
|
542
|
-
if (response.toLowerCase() !== 'y') {
|
|
543
|
-
console.log('Cancelled.');
|
|
544
|
-
process.exit(0);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
487
|
const event: GoogleEvent = {
|
|
549
488
|
summary: title,
|
|
550
489
|
start: {
|
package/glib/gutils.ts
CHANGED
|
@@ -307,29 +307,18 @@ export function parseDateTime(input: string): Date {
|
|
|
307
307
|
return d;
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
-
// Handle time with am/pm
|
|
311
|
-
const
|
|
312
|
-
if (
|
|
313
|
-
const [, hour, min, ampm] =
|
|
314
|
-
const d = new Date(now);
|
|
310
|
+
// Handle time with am/pm (2pm, 10am, 2:30pm) - assume today
|
|
311
|
+
const ampmMatch = lower.match(/^(\d{1,2})(?::(\d{2}))?\s*(am|pm)$/);
|
|
312
|
+
if (ampmMatch) {
|
|
313
|
+
const [, hour, min, ampm] = ampmMatch;
|
|
315
314
|
let h = parseInt(hour);
|
|
316
315
|
if (ampm === 'pm' && h < 12) h += 12;
|
|
317
316
|
if (ampm === 'am' && h === 12) h = 0;
|
|
317
|
+
const d = new Date(now);
|
|
318
318
|
d.setHours(h, parseInt(min || '0'), 0, 0);
|
|
319
319
|
return d;
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
-
// Handle bare hour: "10", "14" - interpret as today at that hour (not a month)
|
|
323
|
-
const bareHourMatch = input.match(/^(\d{1,2})$/);
|
|
324
|
-
if (bareHourMatch) {
|
|
325
|
-
const hour = parseInt(bareHourMatch[1]);
|
|
326
|
-
if (hour >= 0 && hour <= 23) {
|
|
327
|
-
const d = new Date(now);
|
|
328
|
-
d.setHours(hour, 0, 0, 0);
|
|
329
|
-
return d;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
322
|
// Try native Date parsing
|
|
334
323
|
const parsed = new Date(input);
|
|
335
324
|
if (!isNaN(parsed.getTime())) {
|
package/package.json
CHANGED
|
@@ -1,46 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@bobfrankston/gcal",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Google Calendar CLI tool with ICS import support",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "gcal.ts",
|
|
7
|
-
"bin": {
|
|
8
|
-
"gcal": "gcal.ts"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"gcal.ts",
|
|
12
|
-
"glib/**/*.ts",
|
|
13
|
-
"tsconfig.json",
|
|
14
|
-
"README.md"
|
|
15
|
-
],
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/BobFrankston/gcal.git"
|
|
19
|
-
},
|
|
20
|
-
"scripts": {
|
|
21
|
-
"check": "tsc --noEmit",
|
|
22
|
-
"prerelease:local": "git add -A && (git diff-index --quiet HEAD || git commit -m \"Pre-release commit\")",
|
|
23
|
-
"preversion": "npm run check && git add -A",
|
|
24
|
-
"postversion": "git push && git push --tags",
|
|
25
|
-
"release": "npm run prerelease:local && npm version patch && npm publish --access public",
|
|
26
|
-
"release:local": "npm run prerelease:local && npm version patch && npm publish --access public --ignore-scripts",
|
|
27
|
-
"installer": "npm run release && npm install -g ."
|
|
28
|
-
},
|
|
29
|
-
"keywords": [
|
|
30
|
-
"google",
|
|
31
|
-
"calendar",
|
|
32
|
-
"ics",
|
|
33
|
-
"ical",
|
|
34
|
-
"oauth",
|
|
35
|
-
"cli"
|
|
36
|
-
],
|
|
37
|
-
"author": "Bob Frankston",
|
|
38
|
-
"license": "MIT",
|
|
39
|
-
"devDependencies": {
|
|
40
|
-
"@types/node": "^25.0.
|
|
41
|
-
},
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"@bobfrankston/oauthsupport": "^1.0.
|
|
44
|
-
"ical.js": "^2.1.0"
|
|
45
|
-
}
|
|
46
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@bobfrankston/gcal",
|
|
3
|
+
"version": "0.1.11",
|
|
4
|
+
"description": "Google Calendar CLI tool with ICS import support",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "gcal.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"gcal": "gcal.ts"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"gcal.ts",
|
|
12
|
+
"glib/**/*.ts",
|
|
13
|
+
"tsconfig.json",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/BobFrankston/gcal.git"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"check": "tsc --noEmit",
|
|
22
|
+
"prerelease:local": "git add -A && (git diff-index --quiet HEAD || git commit -m \"Pre-release commit\")",
|
|
23
|
+
"preversion": "npm run check && git add -A",
|
|
24
|
+
"postversion": "git push && git push --tags",
|
|
25
|
+
"release": "npm run prerelease:local && npm version patch && npm publish --access public",
|
|
26
|
+
"release:local": "npm run prerelease:local && npm version patch && npm publish --access public --ignore-scripts",
|
|
27
|
+
"installer": "npm run release && npm install -g ."
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"google",
|
|
31
|
+
"calendar",
|
|
32
|
+
"ics",
|
|
33
|
+
"ical",
|
|
34
|
+
"oauth",
|
|
35
|
+
"cli"
|
|
36
|
+
],
|
|
37
|
+
"author": "Bob Frankston",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^25.0.9"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@bobfrankston/oauthsupport": "^1.0.5",
|
|
44
|
+
"ical.js": "^2.1.0"
|
|
45
|
+
},
|
|
46
|
+
".dependencies": {
|
|
47
|
+
"@bobfrankston/oauthsupport": "file:../../../projects/OAuth/OauthSupport",
|
|
48
|
+
"ical.js": "^2.1.0"
|
|
49
|
+
}
|
|
50
|
+
}
|