CardDAV: двусторонний синк контактов с Radicale (push+pull) + docs DAVx5/Caddy

- scripts/contacts_caldav_sync.py: push 81 контакт → vCard (Radicale :5232),
  pull правок/создания/удаления с телефона → contacts.json (ETag сверка,
  soft-delete, конфликты 412 → приоритет телефону, лог caldav-sync.log)
- fix(contacts_extractor): перестройка by_email-индексов после sort()
- STATUS.md: раздел DAVx5 + Caddy (Authorization/handle_path/X-Script-Name),
  Задача 3 (синхронизация с телефоном) = следующая сессия
- tasks.md: отмечены 1.x-3.x/V (реализовано и протестировано), добавлен
  раздел 5 (Caddy + DAVx5 + jtx board) для следующей сессии
This commit is contained in:
2026-09-13 17:21:51 +00:00
parent 17252ebfa9
commit 8ea022f5c0
5 changed files with 698 additions and 25 deletions
+3
View File
@@ -308,6 +308,8 @@ def get_date_from_path(path):
def save_progress(contacts_db, contacts_dir, processed_uids, processed_emails):
"""Инкрементальное сохранение контактов и last_scan."""
contacts_db["contacts"].sort(key=lambda c: c.get("email", ""))
# Перестроить by_email — он хранит ИНДЕКСЫ позиций; после сортировки они сдвигаются
contacts_db["by_email"] = {c.get("email", ""): i for i, c in enumerate(contacts_db["contacts"])}
save_json(contacts_dir / "contacts.json", contacts_db)
save_json(contacts_dir / "index.json", contacts_db.get("by_email", {}))
generate_vcard(contacts_dir, contacts_db["contacts"])
@@ -485,6 +487,7 @@ def scan(limit=0):
if save_counter >= 5:
save_counter = 0
contacts_db["contacts"].sort(key=lambda c: c.get("email", ""))
contacts_db["by_email"] = {c.get("email", ""): i for i, c in enumerate(contacts_db["contacts"])}
save_json(contacts_dir / "contacts.json", contacts_db)
save_json(contacts_dir / "index.json", contacts_db.get("by_email", {}))
generate_vcard(contacts_dir, contacts_db["contacts"])