# Apple Calendar CalDAV Setup

## Prerequisites

```bash
python3 -m pip install caldav vobject feedparser
```

If pip is missing:
```bash
curl -sS https://bootstrap.pypa.io/get-pip.py | python3
python3 -m pip install caldav vobject feedparser
```

## iCloud App-Specific Password

Apple requires an **app-specific password** for CalDAV access. Your main iCloud password will NOT work.

1. Go to [appleid.apple.com](https://appleid.apple.com)
2. Sign in → **Sign-In and Security** → **App-Specific Passwords**
3. Generate a new password (format: `xxxx-xxxx-xxxx-xxxx`)
4. Use this in your `.env` file, not your real password

## .env File

Create `/home/$USER/.hermes/.env`:

```bash
APPLE_EMAIL="your@icloud.com"
APPLE_APP_PASSWORD="xxxx-xxxx-xxxx-xxxx"
```

Set permissions:
```bash
chmod 600 /home/$USER/.hermes/.env
```

## CalDAV URL

```python
CALDAV_URL = "https://caldav.icloud.com"
```

## Common Issues

### `vobject` not installed
If you see `CRITICAL:root:A vobject instance has been requested, but the vobject library is not installed`, run:
```bash
python3 -m pip install vobject
```

### `date_search` deprecated
Use `calendar.search(start=..., end=..., event=True, expand=True)` instead of `calendar.date_search()`.

### vobject summary wrapper garbage
When reading `vevent.summary` via `str(getattr(...))`, vobject may emit a wrapper like `<SUMMARY{Backend Final}>` instead of the plain text.

**Fix**: access the `.value` attribute directly:
```python
raw_summary = vevent.summary
if hasattr(raw_summary, 'value'):
    summary = raw_summary.value
else:
    summary = str(raw_summary)
```

### No calendars found
Ensure the app-specific password is correct. Main iCloud passwords are rejected silently.

### SSL / connection errors
iCloud CalDAV requires HTTPS. The `caldav` library handles this automatically.

## Minimal Working Example

```python
import caldav, datetime, os

client = caldav.DAVClient(
    url="https://caldav.icloud.com",
    username=os.environ["APPLE_EMAIL"],
    password=os.environ["APPLE_APP_PASSWORD"],
)
principal = client.principal()
calendars = principal.calendars()

today = datetime.date.today()
tomorrow = today + datetime.timedelta(days=1)
for cal in calendars:
    events = cal.search(start=today, end=tomorrow, event=True, expand=True)
    for event in events:
        vevent = event.vobject_instance.vevent
        print(f"{vevent.summary.value} at {vevent.dtstart.value}")
```
