feat(dav,obsidian): grupo dav completo (CardDAV/CalDAV client + split vcf/ics + import pipelines) + build_obsidian_graph + dav_list_calendars
Funciones reutilizables creadas esta sesion para el sistema self-hosted de contactos/calendario (Xandikos) y la app osint_web: - grupo dav (infra): split_vcards, split_vevents_to_vcalendars, extract_or_make_uid, carddav_put_vcard, caldav_put_event, dav_list_resources, dav_get_resource, dav_list_calendars - pipelines: import_vcf_to_carddav, import_ics_to_caldav - obsidian: build_obsidian_graph (grafo agregado del vault)
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
---
|
||||
name: dav_get_resource
|
||||
kind: function
|
||||
lang: py
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "def dav_get_resource(base_url: str, username: str, password: str, resource_path: str, *, timeout_s: float = 20.0, verify_tls: bool = True) -> dict"
|
||||
description: "Descarga (HTTP GET) el contenido de un recurso DAV individual (un VCARD o un VCALENDAR) con HTTP Basic auth. Construye el header Authorization: Basic base64(user:pass) a mano con stdlib. El resource_path puede ser un href absoluto (como los que devuelve dav_list_resources) o una URL completa. verify_tls=True por defecto. Maneja errores sin lanzar. Solo stdlib (urllib, base64, ssl). Probado contra Xandikos."
|
||||
tags: [dav, carddav, caldav, get, download, http, infra]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [base64, ssl, urllib.error, urllib.request]
|
||||
params:
|
||||
- name: base_url
|
||||
desc: "URL base del servidor DAV. Se ignora si resource_path ya es una URL absoluta."
|
||||
- name: username
|
||||
desc: "usuario para HTTP Basic auth (p.ej. 'enmanuel')."
|
||||
- name: password
|
||||
desc: "contrasena para HTTP Basic auth. Resolver desde pass con pass_get_secret, nunca hardcodear."
|
||||
- name: resource_path
|
||||
desc: "href absoluto (p.ej. '/enmanuel/contacts/addressbook/x.vcf') o URL completa del recurso a descargar. Acepta directamente los hrefs que devuelve dav_list_resources."
|
||||
- name: timeout_s
|
||||
desc: "timeout de la peticion HTTP en segundos. Default 20.0."
|
||||
- name: verify_tls
|
||||
desc: "si True (default) verifica el certificado TLS. No desactivar salvo entorno de prueba."
|
||||
output: "dict. En exito: {status:'ok', http_status:int, text:str, url:str} donde text es el cuerpo del recurso (VCARD o VCALENDAR). En error (sin lanzar): {status:'error', error:str, http_status:int|None}."
|
||||
tested: true
|
||||
tests:
|
||||
- "test_construye_request_get_con_auth"
|
||||
- "test_resource_path_relativo_se_resuelve_con_base_url"
|
||||
- "test_resource_path_absoluto_se_respeta"
|
||||
- "test_devuelve_texto_del_recurso"
|
||||
- "test_httperror_devuelve_status_error"
|
||||
test_file_path: "python/functions/infra/dav_get_resource_test.py"
|
||||
file_path: "python/functions/infra/dav_get_resource.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
import sys
|
||||
sys.path.insert(0, "python/functions")
|
||||
from infra.pass_get_secret import pass_get_secret
|
||||
from infra.dav_list_resources import dav_list_resources
|
||||
from infra.dav_get_resource import dav_get_resource
|
||||
|
||||
base = "https://dav-eedeb681c4ab89ab8e444ac9.organic-machine.com"
|
||||
pw = pass_get_secret("dav/xandikos-enmanuel")["value"] # NO logear
|
||||
|
||||
listing = dav_list_resources(base, "enmanuel", pw, "/enmanuel/contacts/addressbook/")
|
||||
first = listing["resources"][0]["href"]
|
||||
res = dav_get_resource(base, "enmanuel", pw, first)
|
||||
print(res["text"][:13]) # BEGIN:VCARD
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando quieres leer el contenido de un recurso concreto cuyo href ya conoces
|
||||
(por `dav_list_resources` o porque lo construyes tu). Util para hacer backup de
|
||||
una coleccion (listar + get cada uno), validar que un import quedo bien escrito,
|
||||
o comparar etags en un sync. Acepta directamente los hrefs del listing sin
|
||||
reconstruir la URL.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Lectura remota real sobre TLS; password de `pass`, no se logea.
|
||||
- Decodifica el cuerpo como UTF-8 con `errors='replace'`: bytes invalidos se
|
||||
sustituyen por el caracter de reemplazo en vez de fallar.
|
||||
- Si resource_path es relativo se concatena a base_url; si es absoluto
|
||||
(http/https) se usa tal cual y base_url se ignora.
|
||||
- `verify_tls=False` solo en pruebas; abre MITM.
|
||||
Reference in New Issue
Block a user