1c4a4b9259
Cinco funciones nuevas para soportar DuckDB como fuente de verdad del project osint:
Grupo duckdb (escritura, complementan a duckdb_query_readonly):
- duckdb_execute_py_infra (impure): ejecuta INSERT/UPDATE/DELETE/DDL en read-write, commit, {status,rowcount}. 6 tests.
- duckdb_upsert_py_infra (impure): UPSERT ON CONFLICT actualizando solo update_cols → ownership selectivo (un re-upsert no pisa columnas excluidas). 7 tests.
Grupo dav (libretas de contactos + vCard multi-valor):
- dav_make_addressbook_py_infra (impure): crea una libreta CardDAV nueva via extended MKCOL (RFC 5689). Idempotente. 12 tests.
- dav_list_addressbooks_py_infra (impure): lista las libretas del contacts-home (PROPFIND Depth:1). 7 tests.
- build_vcard_py_core (pure): serializa un contacto a vCard 3.0 multi-valor (N TEL/EMAIL/ADR + X-OSINT-*). 5 tests.
Paginas de capacidad duckdb.md y dav.md actualizadas.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.0 KiB
6.0 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | params | output | tested | tests | test_file_path | file_path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| dav_make_addressbook | function | py | infra | 1.0.0 | impure | def dav_make_addressbook(base_url: str, username: str, password: str, contacts_home: str, slug: str, display_name: str = "", description: str = "", *, timeout_s: float = 20.0, verify_tls: bool = True) -> dict | Crea una nueva coleccion de contactos CardDAV (una libreta/agenda de contactos nueva) bajo el contacts-home de un principal via MKCOL extendido (RFC 5689), declarando el resourcetype como addressbook y fijando el displayname y la descripcion (addressbook-description) en el propio cuerpo XML. La coleccion se crea en <contacts_home><slug>/. El slug se sanea a [a-z0-9_-] (minusculas, espacios->guion); si queda vacio devuelve error de validacion. Idempotente: 201 Created es exito; 405/301 (ya existe) devuelve {status:'ok', existed:True}. Escapa display_name/description para XML. Construye Authorization: Basic base64(user:pass) a mano. Maneja errores sin lanzar (salvo validacion de args). Solo stdlib (urllib, base64, re, ssl, xml.sax.saxutils). Probado contra Xandikos. Analoga de dav_make_calendar para CardDAV. |
|
false |
|
|
dict. En exito: {status:'ok', http_status:int, href:str} y, si la coleccion ya existia, ademas existed:True. En error (sin lanzar): {status:'error', http_status:int|None, href:str, error:str}. href es la ruta de la coleccion (contacts_home + slug saneado + '/'). | true |
|
python/functions/infra/dav_make_addressbook_test.py | python/functions/infra/dav_make_addressbook.py |
Ejemplo
import sys
sys.path.insert(0, "python/functions")
from infra.pass_get_secret import pass_get_secret
from infra.dav_make_addressbook import dav_make_addressbook
pw = pass_get_secret("dav/xandikos-enmanuel")["value"] # NO logear
res = dav_make_addressbook(
base_url="https://dav-eedeb681c4ab89ab8e444ac9.organic-machine.com",
username="enmanuel",
password=pw,
contacts_home="/enmanuel/contacts/",
slug="trabajo",
display_name="Trabajo",
)
print(res)
# {'status': 'ok', 'http_status': 201, 'href': '/enmanuel/contacts/trabajo/'}
# Volver a llamar con el mismo slug:
# {'status': 'ok', 'http_status': 405, 'href': '/enmanuel/contacts/trabajo/', 'existed': True}
Cuando usarla
Cuando el usuario quiere una libreta/agenda de contactos nueva ademas de la
principal: una coleccion CardDAV separada ("Trabajo", "Personal", "Familia") con
su propio nombre visible, bajo el contacts-home del principal. Es la analoga de
dav_make_calendar para CardDAV. El href devuelto es la ruta de la coleccion
que luego usas para escribir vCards (PUT de cada contacto) o para listarla en el
selector de libretas.
Gotchas
- Impura: requiere red + Basic auth contra el servidor DAV. El password viene de
pass, no se logea ni se hardcodea. - Idempotente: si la coleccion ya existe en ese path el servidor responde 405
(Method Not Allowed) o 301; ambos se traducen a
{status:'ok', existed:True}en vez de error, asi que es seguro reintentar. - A diferencia de los calendarios (que tienen el metodo HTTP dedicado
MKCALENDAR), CardDAV NO define un "MKADDRESSBOOK". La creacion se hace con
MKCOL extendido (RFC 5689): metodo HTTP
MKCOLcon un cuerpo XML que declara elresourcetypecomoD:collection+C:addressbook. Probado contra Xandikos, que lo soporta. - Fallback para servidores sin MKCOL extendido: algunos servidores CardDAV viejos
no aceptan cuerpo en MKCOL y devuelven 415/400. En ese caso el patron es
MKCOLsimple (sin cuerpo) para crear la coleccion + unPROPPATCHposterior que fije elresourcetypeaddressbook, eldisplaynamey laaddressbook-description. Esta funcion implementa solo el camino extendido (un request); si te topas con un servidor que no lo soporta, anade el fallback MKCOL+PROPPATCH antes de promoverlo. - El
slugse sanea a[a-z0-9_-](minusculas, espacios->guion, resto fuera). Un slug que queda vacio tras sanear (p.ej. solo simbolos) devuelve error de validacion sin tocar la red. Eldisplay_namey ladescriptionse escapan para XML, pero elslugque va en la URL ya esta restringido al charset seguro.