Initial backup 2026-02-17
This commit is contained in:
124
skills/lark-calendar/scripts/create-event.mjs
Normal file
124
skills/lark-calendar/scripts/create-event.mjs
Normal file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Create a calendar event
|
||||
*
|
||||
* Usage:
|
||||
* node create-event.mjs --title "Meeting" --start "2026-02-03 14:00:00" --end "2026-02-03 15:00:00"
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'util';
|
||||
import { createEvent, DEFAULT_CALENDAR_ID, DEFAULT_TIMEZONE } from '../lib/calendar.mjs';
|
||||
import { resolveNames, getDisplayNameSync } from '../lib/employees.mjs';
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
title: { type: 'string' },
|
||||
description: { type: 'string', default: '' },
|
||||
start: { type: 'string' },
|
||||
end: { type: 'string' },
|
||||
attendees: { type: 'string', default: '' },
|
||||
'attendee-ids': { type: 'string', default: '' },
|
||||
location: { type: 'string', default: '' },
|
||||
timezone: { type: 'string', default: DEFAULT_TIMEZONE },
|
||||
calendar: { type: 'string', default: DEFAULT_CALENDAR_ID },
|
||||
help: { type: 'boolean', short: 'h' }
|
||||
}
|
||||
});
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
Create a Lark calendar event
|
||||
|
||||
Options:
|
||||
--title Event title (required)
|
||||
--description Event description
|
||||
--start Start time: YYYY-MM-DD HH:MM:SS (required)
|
||||
--end End time: YYYY-MM-DD HH:MM:SS (required)
|
||||
--attendees Comma-separated names (auto-resolved to user_ids)
|
||||
--attendee-ids Comma-separated user_ids directly
|
||||
--location Event location
|
||||
--timezone IANA timezone (default: Asia/Singapore)
|
||||
--calendar Calendar ID (uses default Claw calendar if omitted)
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
node create-event.mjs --title "Team Sync" --start "2026-02-03 10:00:00" --end "2026-02-03 10:30:00"
|
||||
node create-event.mjs --title "Review" --start "2026-02-03 14:00:00" --end "2026-02-03 15:00:00" --attendees "Boyang,RK,jc"
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if (!values.title) {
|
||||
console.error('Error: --title is required');
|
||||
process.exit(1);
|
||||
}
|
||||
if (!values.start) {
|
||||
console.error('Error: --start is required');
|
||||
process.exit(1);
|
||||
}
|
||||
if (!values.end) {
|
||||
console.error('Error: --end is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Resolve attendees
|
||||
let attendeeIds = [];
|
||||
if (values['attendee-ids']) {
|
||||
attendeeIds = values['attendee-ids'].split(',').map(s => s.trim()).filter(Boolean);
|
||||
}
|
||||
if (values.attendees) {
|
||||
const names = values.attendees.split(',').map(s => s.trim()).filter(Boolean);
|
||||
const { resolved, unresolved } = resolveNames(names);
|
||||
attendeeIds = [...new Set([...attendeeIds, ...resolved])];
|
||||
if (unresolved.length > 0) {
|
||||
console.warn(`Warning: Could not resolve names: ${unresolved.join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log('Creating event...');
|
||||
console.log(` Title: ${values.title}`);
|
||||
console.log(` Start: ${values.start}`);
|
||||
console.log(` End: ${values.end}`);
|
||||
console.log(` Timezone: ${values.timezone}`);
|
||||
console.log(` Attendees: ${attendeeIds.map(id => getDisplayNameSync(id)).join(', ') || '(Boyang will be added automatically)'}`);
|
||||
if (values.location) console.log(` Location: ${values.location}`);
|
||||
console.log('');
|
||||
|
||||
const result = await createEvent({
|
||||
title: values.title,
|
||||
description: values.description,
|
||||
startTime: values.start,
|
||||
endTime: values.end,
|
||||
attendeeIds,
|
||||
location: values.location,
|
||||
timezone: values.timezone,
|
||||
calendarId: values.calendar
|
||||
});
|
||||
|
||||
console.log('✅ Event created successfully!');
|
||||
console.log('');
|
||||
console.log('Event Details:');
|
||||
console.log(` Event ID: ${result.event.event_id}`);
|
||||
console.log(` Title: ${result.event.summary}`);
|
||||
console.log(` Link: ${result.event.app_link || 'N/A'}`);
|
||||
console.log(` Attendees: ${result.attendeeNames || 'N/A'}`);
|
||||
|
||||
// Output JSON for programmatic use
|
||||
if (process.env.JSON_OUTPUT) {
|
||||
console.log('\nJSON:');
|
||||
console.log(JSON.stringify(result, null, 2));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to create event:', error.message);
|
||||
if (error.larkResponse) {
|
||||
console.error('Lark response:', JSON.stringify(error.larkResponse, null, 2));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
109
skills/lark-calendar/scripts/create-task.mjs
Normal file
109
skills/lark-calendar/scripts/create-task.mjs
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Create a task
|
||||
*
|
||||
* Usage:
|
||||
* node create-task.mjs --title "Review PR" --due "2026-02-05 18:00:00"
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'util';
|
||||
import { createTask } from '../lib/task.mjs';
|
||||
import { DEFAULT_TIMEZONE } from '../lib/calendar.mjs';
|
||||
import { resolveNames, getDisplayNameSync } from '../lib/employees.mjs';
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
title: { type: 'string' },
|
||||
description: { type: 'string', default: '' },
|
||||
due: { type: 'string' },
|
||||
assignees: { type: 'string', default: '' },
|
||||
'assignee-ids': { type: 'string', default: '' },
|
||||
timezone: { type: 'string', default: DEFAULT_TIMEZONE },
|
||||
help: { type: 'boolean', short: 'h' }
|
||||
}
|
||||
});
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
Create a Lark task
|
||||
|
||||
Options:
|
||||
--title Task title (required)
|
||||
--description Task description
|
||||
--due Due time: YYYY-MM-DD HH:MM:SS (required)
|
||||
--assignees Comma-separated names (auto-resolved to user_ids)
|
||||
--assignee-ids Comma-separated user_ids directly
|
||||
--timezone IANA timezone (default: Asia/Singapore)
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
node create-task.mjs --title "Review PR #123" --due "2026-02-05 18:00:00"
|
||||
node create-task.mjs --title "Finish report" --due "2026-02-03 17:00:00" --assignees "Boyang,jc"
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if (!values.title) {
|
||||
console.error('Error: --title is required');
|
||||
process.exit(1);
|
||||
}
|
||||
if (!values.due) {
|
||||
console.error('Error: --due is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Resolve assignees
|
||||
let assigneeIds = [];
|
||||
if (values['assignee-ids']) {
|
||||
assigneeIds = values['assignee-ids'].split(',').map(s => s.trim()).filter(Boolean);
|
||||
}
|
||||
if (values.assignees) {
|
||||
const names = values.assignees.split(',').map(s => s.trim()).filter(Boolean);
|
||||
const { resolved, unresolved } = resolveNames(names);
|
||||
assigneeIds = [...new Set([...assigneeIds, ...resolved])];
|
||||
if (unresolved.length > 0) {
|
||||
console.warn(`Warning: Could not resolve names: ${unresolved.join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log('Creating task...');
|
||||
console.log(` Title: ${values.title}`);
|
||||
console.log(` Due: ${values.due}`);
|
||||
console.log(` Timezone: ${values.timezone}`);
|
||||
console.log(` Assignees: ${assigneeIds.map(id => getDisplayNameSync(id)).join(', ') || '(none)'}`);
|
||||
console.log('');
|
||||
|
||||
const task = await createTask({
|
||||
title: values.title,
|
||||
description: values.description,
|
||||
dueTime: values.due,
|
||||
assigneeIds,
|
||||
timezone: values.timezone
|
||||
});
|
||||
|
||||
console.log('✅ Task created successfully!');
|
||||
console.log('');
|
||||
console.log('Task Details:');
|
||||
console.log(` Task ID: ${task.guid}`);
|
||||
console.log(` Title: ${task.summary}`);
|
||||
console.log(` URL: ${task.url || 'N/A'}`);
|
||||
|
||||
// Output JSON for programmatic use
|
||||
if (process.env.JSON_OUTPUT) {
|
||||
console.log('\nJSON:');
|
||||
console.log(JSON.stringify(task, null, 2));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to create task:', error.message);
|
||||
if (error.larkResponse) {
|
||||
console.error('Lark response:', JSON.stringify(error.larkResponse, null, 2));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
59
skills/lark-calendar/scripts/delete-event.mjs
Normal file
59
skills/lark-calendar/scripts/delete-event.mjs
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Delete a calendar event
|
||||
*
|
||||
* Usage:
|
||||
* node delete-event.mjs --event-id "f9900f6b-b472-4b17-a818-7b5584abdc37_0"
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'util';
|
||||
import { deleteEvent, DEFAULT_CALENDAR_ID } from '../lib/calendar.mjs';
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
'event-id': { type: 'string' },
|
||||
calendar: { type: 'string', default: DEFAULT_CALENDAR_ID },
|
||||
'no-notify': { type: 'boolean', default: false },
|
||||
help: { type: 'boolean', short: 'h' }
|
||||
}
|
||||
});
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
Delete a Lark calendar event
|
||||
|
||||
Options:
|
||||
--event-id Event ID to delete (required)
|
||||
--calendar Calendar ID
|
||||
--no-notify Don't send notifications to attendees
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
node delete-event.mjs --event-id "f9900f6b-b472-4b17-a818-7b5584abdc37_0"
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!values['event-id']) {
|
||||
console.error('Error: --event-id is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log(`Deleting event: ${values['event-id']}`);
|
||||
|
||||
await deleteEvent(values['event-id'], values.calendar, !values['no-notify']);
|
||||
|
||||
console.log('✅ Event deleted successfully!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to delete event:', error.message);
|
||||
if (error.larkResponse) {
|
||||
console.error('Lark response:', JSON.stringify(error.larkResponse, null, 2));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
55
skills/lark-calendar/scripts/delete-task.mjs
Normal file
55
skills/lark-calendar/scripts/delete-task.mjs
Normal file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Delete a task
|
||||
*
|
||||
* Usage:
|
||||
* node delete-task.mjs --task-id "35fc5310-a1b1-49c7-be75-be631d3079ee"
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'util';
|
||||
import { deleteTask } from '../lib/task.mjs';
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
'task-id': { type: 'string' },
|
||||
help: { type: 'boolean', short: 'h' }
|
||||
}
|
||||
});
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
Delete a Lark task
|
||||
|
||||
Options:
|
||||
--task-id Task GUID to delete (required)
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
node delete-task.mjs --task-id "35fc5310-a1b1-49c7-be75-be631d3079ee"
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!values['task-id']) {
|
||||
console.error('Error: --task-id is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log(`Deleting task: ${values['task-id']}`);
|
||||
|
||||
await deleteTask(values['task-id']);
|
||||
|
||||
console.log('✅ Task deleted successfully!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to delete task:', error.message);
|
||||
if (error.larkResponse) {
|
||||
console.error('Lark response:', JSON.stringify(error.larkResponse, null, 2));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
93
skills/lark-calendar/scripts/list-events.mjs
Normal file
93
skills/lark-calendar/scripts/list-events.mjs
Normal file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* List calendar events
|
||||
*
|
||||
* Usage:
|
||||
* node list-events.mjs
|
||||
* node list-events.mjs --start "2026-02-01" --end "2026-02-28"
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'util';
|
||||
import { listEvents, timestampToDatetime, DEFAULT_CALENDAR_ID, DEFAULT_TIMEZONE } from '../lib/calendar.mjs';
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
start: { type: 'string' },
|
||||
end: { type: 'string' },
|
||||
timezone: { type: 'string', default: DEFAULT_TIMEZONE },
|
||||
calendar: { type: 'string', default: DEFAULT_CALENDAR_ID },
|
||||
json: { type: 'boolean' },
|
||||
help: { type: 'boolean', short: 'h' }
|
||||
}
|
||||
});
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
List Lark calendar events
|
||||
|
||||
Options:
|
||||
--start Start date: YYYY-MM-DD (default: today)
|
||||
--end End date: YYYY-MM-DD (default: 7 days from now)
|
||||
--timezone IANA timezone (default: Asia/Singapore)
|
||||
--calendar Calendar ID
|
||||
--json Output as JSON
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
node list-events.mjs
|
||||
node list-events.mjs --start "2026-02-01" --end "2026-02-28"
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const events = await listEvents({
|
||||
calendarId: values.calendar,
|
||||
startTime: values.start,
|
||||
endTime: values.end,
|
||||
timezone: values.timezone
|
||||
});
|
||||
|
||||
if (values.json) {
|
||||
console.log(JSON.stringify(events, null, 2));
|
||||
return;
|
||||
}
|
||||
|
||||
if (events.length === 0) {
|
||||
console.log('No events found in the specified range.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Found ${events.length} event(s):\n`);
|
||||
|
||||
for (const event of events) {
|
||||
const startTime = event.start_time?.timestamp
|
||||
? timestampToDatetime(parseInt(event.start_time.timestamp), values.timezone)
|
||||
: 'N/A';
|
||||
const endTime = event.end_time?.timestamp
|
||||
? timestampToDatetime(parseInt(event.end_time.timestamp), values.timezone)
|
||||
: 'N/A';
|
||||
|
||||
console.log(`📅 ${event.summary || '(No title)'}`);
|
||||
console.log(` ID: ${event.event_id}`);
|
||||
console.log(` Time: ${startTime} → ${endTime}`);
|
||||
if (event.location?.name) {
|
||||
console.log(` Location: ${event.location.name}`);
|
||||
}
|
||||
if (event.description) {
|
||||
console.log(` Description: ${event.description.substring(0, 100)}${event.description.length > 100 ? '...' : ''}`);
|
||||
}
|
||||
console.log('');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to list events:', error.message);
|
||||
if (error.larkResponse) {
|
||||
console.error('Lark response:', JSON.stringify(error.larkResponse, null, 2));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
109
skills/lark-calendar/scripts/manage-attendees.mjs
Normal file
109
skills/lark-calendar/scripts/manage-attendees.mjs
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Add or remove attendees from a calendar event
|
||||
*
|
||||
* Usage:
|
||||
* node manage-attendees.mjs --event-id "xxx" --add "RK,jc"
|
||||
* node manage-attendees.mjs --event-id "xxx" --remove "jc"
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'util';
|
||||
import { addEventAttendees, removeEventAttendees, DEFAULT_CALENDAR_ID } from '../lib/calendar.mjs';
|
||||
import { resolveNames, getDisplayNameSync } from '../lib/employees.mjs';
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
'event-id': { type: 'string' },
|
||||
add: { type: 'string' },
|
||||
remove: { type: 'string' },
|
||||
'user-ids': { type: 'string' },
|
||||
calendar: { type: 'string', default: DEFAULT_CALENDAR_ID },
|
||||
help: { type: 'boolean', short: 'h' }
|
||||
}
|
||||
});
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
Manage calendar event attendees
|
||||
|
||||
Options:
|
||||
--event-id Event ID (required)
|
||||
--add Comma-separated names to add
|
||||
--remove Comma-separated names to remove
|
||||
--user-ids Comma-separated user_ids directly (use with --add or --remove)
|
||||
--calendar Calendar ID
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
node manage-attendees.mjs --event-id "xxx" --add "RK,jc"
|
||||
node manage-attendees.mjs --event-id "xxx" --remove "jc"
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!values['event-id']) {
|
||||
console.error('Error: --event-id is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!values.add && !values.remove) {
|
||||
console.error('Error: Either --add or --remove is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const calendarId = values.calendar;
|
||||
const eventId = values['event-id'];
|
||||
|
||||
if (values.add) {
|
||||
const names = values.add.split(',').map(s => s.trim()).filter(Boolean);
|
||||
const { resolved, unresolved } = resolveNames(names);
|
||||
|
||||
if (values['user-ids']) {
|
||||
resolved.push(...values['user-ids'].split(',').map(s => s.trim()).filter(Boolean));
|
||||
}
|
||||
|
||||
if (unresolved.length > 0) {
|
||||
console.warn(`Warning: Could not resolve names: ${unresolved.join(', ')}`);
|
||||
}
|
||||
|
||||
if (resolved.length === 0) {
|
||||
console.error('No valid attendees to add');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Adding attendees: ${resolved.map(id => getDisplayNameSync(id)).join(', ')}`);
|
||||
const result = await addEventAttendees(calendarId, eventId, resolved);
|
||||
console.log('✅ Attendees added successfully!');
|
||||
console.log(`Updated attendees: ${(result.attendees || []).map(a => a.display_name).join(', ')}`);
|
||||
}
|
||||
|
||||
if (values.remove) {
|
||||
const names = values.remove.split(',').map(s => s.trim()).filter(Boolean);
|
||||
const { resolved, unresolved } = resolveNames(names);
|
||||
|
||||
if (unresolved.length > 0) {
|
||||
console.warn(`Warning: Could not resolve names: ${unresolved.join(', ')}`);
|
||||
}
|
||||
|
||||
if (resolved.length === 0) {
|
||||
console.error('No valid attendees to remove');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Removing attendees: ${resolved.map(id => getDisplayNameSync(id)).join(', ')}`);
|
||||
await removeEventAttendees(calendarId, eventId, resolved);
|
||||
console.log('✅ Attendees removed successfully!');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed:', error.message);
|
||||
if (error.larkResponse) {
|
||||
console.error('Lark response:', JSON.stringify(error.larkResponse, null, 2));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
105
skills/lark-calendar/scripts/manage-task-members.mjs
Normal file
105
skills/lark-calendar/scripts/manage-task-members.mjs
Normal file
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Add or remove members from a task
|
||||
*
|
||||
* Usage:
|
||||
* node manage-task-members.mjs --task-id "xxx" --add "RK,jc"
|
||||
* node manage-task-members.mjs --task-id "xxx" --remove "jc"
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'util';
|
||||
import { addTaskMembers, removeTaskMembers } from '../lib/task.mjs';
|
||||
import { resolveNames, getDisplayNameSync } from '../lib/employees.mjs';
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
'task-id': { type: 'string' },
|
||||
add: { type: 'string' },
|
||||
remove: { type: 'string' },
|
||||
'user-ids': { type: 'string' },
|
||||
help: { type: 'boolean', short: 'h' }
|
||||
}
|
||||
});
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
Manage task members/assignees
|
||||
|
||||
Options:
|
||||
--task-id Task GUID (required)
|
||||
--add Comma-separated names to add
|
||||
--remove Comma-separated names to remove
|
||||
--user-ids Comma-separated user_ids directly (use with --add or --remove)
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
node manage-task-members.mjs --task-id "xxx" --add "RK,jc"
|
||||
node manage-task-members.mjs --task-id "xxx" --remove "jc"
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!values['task-id']) {
|
||||
console.error('Error: --task-id is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!values.add && !values.remove) {
|
||||
console.error('Error: Either --add or --remove is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const taskId = values['task-id'];
|
||||
|
||||
if (values.add) {
|
||||
const names = values.add.split(',').map(s => s.trim()).filter(Boolean);
|
||||
const { resolved, unresolved } = resolveNames(names);
|
||||
|
||||
if (values['user-ids']) {
|
||||
resolved.push(...values['user-ids'].split(',').map(s => s.trim()).filter(Boolean));
|
||||
}
|
||||
|
||||
if (unresolved.length > 0) {
|
||||
console.warn(`Warning: Could not resolve names: ${unresolved.join(', ')}`);
|
||||
}
|
||||
|
||||
if (resolved.length === 0) {
|
||||
console.error('No valid members to add');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Adding members: ${resolved.map(id => getDisplayNameSync(id)).join(', ')}`);
|
||||
await addTaskMembers(taskId, resolved);
|
||||
console.log('✅ Members added successfully!');
|
||||
}
|
||||
|
||||
if (values.remove) {
|
||||
const names = values.remove.split(',').map(s => s.trim()).filter(Boolean);
|
||||
const { resolved, unresolved } = resolveNames(names);
|
||||
|
||||
if (unresolved.length > 0) {
|
||||
console.warn(`Warning: Could not resolve names: ${unresolved.join(', ')}`);
|
||||
}
|
||||
|
||||
if (resolved.length === 0) {
|
||||
console.error('No valid members to remove');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Removing members: ${resolved.map(id => getDisplayNameSync(id)).join(', ')}`);
|
||||
await removeTaskMembers(taskId, resolved);
|
||||
console.log('✅ Members removed successfully!');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed:', error.message);
|
||||
if (error.larkResponse) {
|
||||
console.error('Lark response:', JSON.stringify(error.larkResponse, null, 2));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
83
skills/lark-calendar/scripts/update-event.mjs
Normal file
83
skills/lark-calendar/scripts/update-event.mjs
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Update a calendar event
|
||||
*
|
||||
* Usage:
|
||||
* node update-event.mjs --event-id "xxx" --title "New Title"
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'util';
|
||||
import { updateEvent, DEFAULT_CALENDAR_ID, DEFAULT_TIMEZONE } from '../lib/calendar.mjs';
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
'event-id': { type: 'string' },
|
||||
title: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
start: { type: 'string' },
|
||||
end: { type: 'string' },
|
||||
location: { type: 'string' },
|
||||
timezone: { type: 'string', default: DEFAULT_TIMEZONE },
|
||||
calendar: { type: 'string', default: DEFAULT_CALENDAR_ID },
|
||||
help: { type: 'boolean', short: 'h' }
|
||||
}
|
||||
});
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
Update a Lark calendar event
|
||||
|
||||
Options:
|
||||
--event-id Event ID to update (required)
|
||||
--title New event title
|
||||
--description New event description
|
||||
--start New start time: YYYY-MM-DD HH:MM:SS
|
||||
--end New end time: YYYY-MM-DD HH:MM:SS
|
||||
--location New event location
|
||||
--timezone IANA timezone (default: Asia/Singapore)
|
||||
--calendar Calendar ID
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
node update-event.mjs --event-id "xxx" --title "Updated Meeting"
|
||||
node update-event.mjs --event-id "xxx" --start "2026-02-03 15:00:00" --end "2026-02-03 16:00:00"
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!values['event-id']) {
|
||||
console.error('Error: --event-id is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log(`Updating event: ${values['event-id']}`);
|
||||
|
||||
const event = await updateEvent({
|
||||
eventId: values['event-id'],
|
||||
title: values.title,
|
||||
description: values.description,
|
||||
startTime: values.start,
|
||||
endTime: values.end,
|
||||
location: values.location,
|
||||
timezone: values.timezone,
|
||||
calendarId: values.calendar
|
||||
});
|
||||
|
||||
console.log('✅ Event updated successfully!');
|
||||
console.log('');
|
||||
console.log('Updated Event:');
|
||||
console.log(` Title: ${event.summary}`);
|
||||
console.log(` Event ID: ${event.event_id}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to update event:', error.message);
|
||||
if (error.larkResponse) {
|
||||
console.error('Lark response:', JSON.stringify(error.larkResponse, null, 2));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
75
skills/lark-calendar/scripts/update-task.mjs
Normal file
75
skills/lark-calendar/scripts/update-task.mjs
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Update a task
|
||||
*
|
||||
* Usage:
|
||||
* node update-task.mjs --task-id "xxx" --title "New Title"
|
||||
*/
|
||||
|
||||
import { parseArgs } from 'util';
|
||||
import { updateTask } from '../lib/task.mjs';
|
||||
import { DEFAULT_TIMEZONE } from '../lib/calendar.mjs';
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
'task-id': { type: 'string' },
|
||||
title: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
due: { type: 'string' },
|
||||
timezone: { type: 'string', default: DEFAULT_TIMEZONE },
|
||||
help: { type: 'boolean', short: 'h' }
|
||||
}
|
||||
});
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
Update a Lark task
|
||||
|
||||
Options:
|
||||
--task-id Task GUID to update (required)
|
||||
--title New task title
|
||||
--description New task description
|
||||
--due New due time: YYYY-MM-DD HH:MM:SS
|
||||
--timezone IANA timezone (default: Asia/Singapore)
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
node update-task.mjs --task-id "xxx" --title "Updated Task"
|
||||
node update-task.mjs --task-id "xxx" --due "2026-02-06 18:00:00"
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!values['task-id']) {
|
||||
console.error('Error: --task-id is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log(`Updating task: ${values['task-id']}`);
|
||||
|
||||
const task = await updateTask({
|
||||
taskId: values['task-id'],
|
||||
title: values.title,
|
||||
description: values.description,
|
||||
dueTime: values.due,
|
||||
timezone: values.timezone
|
||||
});
|
||||
|
||||
console.log('✅ Task updated successfully!');
|
||||
console.log('');
|
||||
console.log('Updated Task:');
|
||||
console.log(` Title: ${task.summary}`);
|
||||
console.log(` Task ID: ${task.guid}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to update task:', error.message);
|
||||
if (error.larkResponse) {
|
||||
console.error('Lark response:', JSON.stringify(error.larkResponse, null, 2));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user