diff --git a/skills/calendar-invite/SKILL.md b/skills/calendar-invite/SKILL.md index 890b0b4..75fcc54 100644 --- a/skills/calendar-invite/SKILL.md +++ b/skills/calendar-invite/SKILL.md @@ -27,7 +27,7 @@ Calendar invites are outbound emails. Follow the workspace email rules: ## Owner Auto-Attendee -When sending invites, `mail@luyx.org` (owner's SimpleLogin alias) is **always added as an attendee automatically**. This ensures the owner receives every invite and can Accept/Decline from their own email client. No need to include it in `--to` — it's added by the script. +When sending invites, `mail@luyx.org` (owner's SimpleLogin alias) is **always added as an attendee automatically**. All invites include a **1-day reminder** (VALARM) by default. This ensures the owner receives every invite and can Accept/Decline from their own email client. No need to include it in `--to` — it's added by the script. When accepting or tentatively accepting a received invite, the original invite is **automatically forwarded to `mail@luyx.org`** so the event lands on the owner's calendar too. @@ -113,7 +113,7 @@ $SKILL_DIR/scripts/calendar-invite.sh send \ ## Replying to Invites ```bash -# Accept by himalaya message ID +# Accept by himalaya envelope ID $SKILL_DIR/scripts/calendar-invite.sh reply \ --envelope-id 42 \ --action accept @@ -135,7 +135,7 @@ $SKILL_DIR/scripts/calendar-invite.sh reply \ | Flag | Required | Description | |-----------------|----------|-----------------------------------------------------| | `--action` | Yes | `accept`, `decline`, or `tentative` | -| `--envelope-id` | * | Himalaya message ID containing the .ics attachment | +| `--envelope-id` | * | Himalaya envelope ID containing the .ics attachment | | `--ics-file` | * | Path to an .ics file (alternative to `--envelope-id`) | | `--from` | No | Your email (default: `youlu@luyanxin.com`) | | `--account` | No | Himalaya account name | diff --git a/skills/calendar-invite/scripts/calendar_invite.py b/skills/calendar-invite/scripts/calendar_invite.py index cab6686..2f73f07 100644 --- a/skills/calendar-invite/scripts/calendar_invite.py +++ b/skills/calendar-invite/scripts/calendar_invite.py @@ -14,14 +14,14 @@ import argparse import subprocess import sys import uuid -from datetime import datetime +from datetime import datetime, timedelta, timezone from pathlib import Path from email.mime.base import MIMEBase from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText -from icalendar import Calendar, Event, vCalAddress, vText +from icalendar import Alarm, Calendar, Event, vCalAddress, vText # --------------------------------------------------------------------------- # Config @@ -38,24 +38,6 @@ PRODID = "-//OpenClaw//CalendarInvite//EN" # Helpers # --------------------------------------------------------------------------- -def _himalaya(*args): - """Run a himalaya command and return stdout.""" - result = subprocess.run( - ["himalaya", *args], - capture_output=True, text=True, check=True, - ) - return result.stdout - - -def _himalaya_with_account(account, *args): - """Run a himalaya command with optional account flag.""" - cmd = ["himalaya"] - if account: - cmd += ["--account", account] - cmd += list(args) - result = subprocess.run(cmd, capture_output=True, text=True, check=True) - return result.stdout - def _sync_calendar(): """Sync local calendar to CalDAV server via vdirsyncer.""" @@ -123,7 +105,7 @@ def cmd_send(args): event = Event() event.add("uid", uid) - event.add("dtstamp", datetime.utcnow()) + event.add("dtstamp", datetime.now(timezone.utc)) event.add("dtstart", start, parameters={"TZID": args.timezone}) event.add("dtend", end, parameters={"TZID": args.timezone}) event.add("summary", args.summary) @@ -151,6 +133,13 @@ def cmd_send(args): "RSVP": "TRUE", }) + # 1-day reminder + alarm = Alarm() + alarm.add("action", "DISPLAY") + alarm.add("description", f"Reminder: {args.summary}") + alarm.add("trigger", timedelta(days=-1)) + event.add_component(alarm) + cal.add_component(event) ics_bytes = cal.to_ical() @@ -286,7 +275,7 @@ def cmd_reply(args): reply_event = Event() reply_event.add("uid", uid) - reply_event.add("dtstamp", datetime.utcnow()) + reply_event.add("dtstamp", datetime.now(timezone.utc)) # Copy timing from original if original_event.get("dtstart"):