Files
email-assistant/openspec/changes/contacts-caldav-server/tasks.md
T

4.8 KiB
Raw Blame History

Tasks: CardDAV-сервер для синхронизации контактов

1. Адресная книга в Radicale

  • 1.1 Создать адресную книгу «Контакты» на ФС: mkdir -p /opt/hermes/email-assistant/radicale/data/collections/collection-root/estorozhenko/Контакты и проверить, что Radicale видит её как addressbook: curl -u estorozhenko:$RADICALE_PASS -X PROPFIND -H 'Depth: 0' http://127.0.0.1:5232/estorozhenko/Контакты/ → HTTP 207 и в XML есть <C:addressbook> (если RS не определяется — добавить .Radicale.props с addressbook и повторить).
  • 1.2 Положить тестовую vCard (test.vcf) в коллекцию и проверить, что она отдаётся: curl ... /estorozhenko/Контакты/test.vcf → 200 + vCard; затем удалить тестовую карточку.

2. Синк в contacts_extractor.py

  • 2.1 Рефакторинг: вынести генерацию vCard 4.0 из существующей generate_vcard() в отдельную функцию contact_to_vcard(contact) -> str, чтобы переиспользовать для CardDAV-карточек. Проверка: скрипт запускается без ошибок, contacts.vcf генерируется как раньше.
  • 2.2 Добавить функцию sync_contacts_to_caldav(contacts_dir, base_url, user, password, prune=False): читает contacts.json, строит карту uid→(ETag, href) через PROPFIND Depth:1, PUT создаёт/обновляет vCard, при prune=True DELETE удаляет лишние. Использовать urllib + Basic Auth. Проверка: юнит-запуск с тестовым Radicale (см. 3.x).
  • 2.3 CLI-флаги: --sync-caldav, --prune-caldav, --caldav-url, --caldav-user, --caldav-pass (или env CALDAV_PASS). По умолчанию синк выключен. Проверка: python3 scripts/contacts_extractor.py --help показывает все флаги; без --sync-caldav поведение прежнее.
  • 2.4 ETag-конфликты: при PUT с If-Match и ответе 412 — записать caldav-sync.log (контакт, conflict) и продолжить. Проверка: ручной тест — изменить vCard на сервере, запустить синк, увидеть conflict в логе.

3. Сквозной тест sync

  • 3.1 Запустить синк с реальной базой: python3 scripts/contacts_extractor.py --sync-caldav (или отдельный скрипт) → в Radicale появились карточки (счётчик PROPFIND/cards): curl ... PROPFIND Depth:1 /estorozhenko/Контакты/ показывает N карточек ≈ количеству контактов в contacts.json с email.
  • 3.2 Повторный запуск — количество карточек не растёт (идемпотентность).
  • 3.3 Изменить контакт в contacts.json (добавить телефон) → повторный синк обновляет карточку (TEL появился, ETag изменился).
  • 3.4 --prune-caldav: удалить контакт из contacts.json → карточка удалена с сервера.

4. Интеграция в cron и документация

  • 4.1 Обновить config/contacts-cron.sh: добавить --sync-caldav и подтянуть пароль из radicale/.env (env CALDAV_PASS). Проверка: запуск cron-скрипта вручную синкает контакты без ошибок.
  • 4.2 Обновить README/STATUS: раздел «CardDAV (контакты)» — как подключить на Android (DAVx5, URL http://cal.nixg.ru:5232 или cal.nixg.ru, логин estorozhenko), порты, флаги синка.
  • 4.3 openspec validate contacts-caldav-server → valid.
  • 4.4 Git commit и push (gitea.nixg.ru/hermes/email-assistant).

Verification

  • V1: curl -X PROPFIND -u estorozhenko:PASS http://127.0.0.1:5232/estorozhenko/Контакты/ → 207 + addressbook
  • V2: после синка количество vCard в адресной книге == числу контактов с email в contacts.json
  • V3: повторный синк → 0 новых карточек
  • V4: python3 scripts/contacts_extractor.py --sync-caldav из cron-обёртки завершается кодом 0 и пишет caldav-sync.log