Files
fn_registry/python/functions/metabase/notifications.py
T
egutierrez cb392a48ee feat(metabase): nuevos modulos — snippets, notifications, dashboard_filters
Tres modulos nuevos con funciones CRUD completas:
- snippets: list, get, create, update, archive (SQL reutilizable)
- notifications: list, create_card_alert, create_dashboard_subscription, update, delete
- dashboard_filters: add_dashboard_filter (parameter_mappings sobre cards existentes)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 19:03:08 +02:00

244 lines
8.0 KiB
Python

"""CRUD de notificaciones de Metabase (alertas y suscripciones).
Dos tipos:
- Card alerts (notification/card): alertas cuando una card tiene resultados,
supera un goal, etc. Cron configurable.
- Dashboard subscriptions (notification/dashboard): envio periodico de un
dashboard completo por email/slack.
API: /api/notification (Metabase 0.57+, reemplaza el antiguo /api/pulse).
"""
from .client import MetabaseClient
def metabase_list_notifications(
client: MetabaseClient,
card_id: int = 0,
dashboard_id: int = 0,
) -> list[dict]:
"""Lista notificaciones activas de Metabase.
Endpoint: GET /api/notification.
Permite filtrar por card o por dashboard. Si no se pasan filtros,
retorna todas las notificaciones accesibles por el usuario autenticado.
Args:
client: Cliente autenticado.
card_id: Si > 0, filtra notificaciones de tipo notification/card
asociadas a esta card.
dashboard_id: Si > 0, filtra notificaciones de tipo
notification/dashboard asociadas a este dashboard.
Returns:
Lista de dicts con: id, active, payload_type, payload,
subscriptions, handlers, created_at, updated_at.
Example:
>>> # Todas las notificaciones
>>> notifs = metabase_list_notifications(client)
>>> # Solo alertas de una card especifica
>>> alerts = metabase_list_notifications(client, card_id=7711)
>>> for a in alerts:
... print(a["id"], a["payload_type"], a["active"])
"""
params: dict = {}
if card_id > 0:
params["card_id"] = card_id
if dashboard_id > 0:
params["dashboard_id"] = dashboard_id
return client.request("GET", "/api/notification", params=params)
def metabase_create_card_alert(
client: MetabaseClient,
card_id: int,
cron_schedule: str,
recipients: list[dict],
send_condition: str = "has_result",
send_once: bool = False,
) -> dict:
"""Crea una alerta sobre los resultados de una card.
Endpoint: POST /api/notification.
Envia un email cuando la card cumple la condicion especificada
(tiene resultados, supera un goal, etc.) segun el cron configurado.
Args:
client: Cliente autenticado.
card_id: ID de la card que dispara la alerta.
cron_schedule: Expresion cron de 5 campos (ej: "0 9 * * 1" = lunes 9am).
recipients: Lista de destinatarios. Cada dict puede ser:
- Usuario Metabase: {"type": "notification-recipient/user", "user_id": 1}
- Email externo: {"type": "notification-recipient/raw-value",
"details": {"email": "x@y.com"}}
send_condition: Condicion que dispara el envio:
"has_result" (tiene filas), "goal_above" (supera goal),
"goal_below" (cae bajo goal). Default: "has_result".
send_once: Si True, se envia una sola vez y se desactiva.
Default: False.
Returns:
Dict con la notificacion creada: id, active, payload_type,
payload, subscriptions, handlers, created_at.
Example:
>>> alert = metabase_create_card_alert(
... client,
... card_id=7711,
... cron_schedule="0 9 * * 1",
... recipients=[
... {"type": "notification-recipient/user", "user_id": 1},
... {"type": "notification-recipient/raw-value",
... "details": {"email": "team@aurgi.com"}},
... ],
... send_condition="has_result",
... )
>>> print(alert["id"], alert["active"])
"""
body = {
"payload_type": "notification/card",
"payload": {
"card_id": card_id,
"send_condition": send_condition,
"send_once": send_once,
},
"subscriptions": [
{
"type": "notification-subscription/cron",
"cron_schedule": cron_schedule,
}
],
"handlers": [
{
"channel_type": "channel/email",
"recipients": recipients,
}
],
"active": True,
}
return client.request("POST", "/api/notification", json=body)
def metabase_create_dashboard_subscription(
client: MetabaseClient,
dashboard_id: int,
cron_schedule: str,
recipients: list[dict],
) -> dict:
"""Crea una suscripcion periodica a un dashboard.
Endpoint: POST /api/notification.
Envia el dashboard completo por email segun el cron configurado.
Args:
client: Cliente autenticado.
dashboard_id: ID del dashboard a enviar.
cron_schedule: Expresion cron de 5 campos (ej: "0 8 * * 1-5" = lun-vie 8am).
recipients: Lista de destinatarios. Cada dict puede ser:
- Usuario Metabase: {"type": "notification-recipient/user", "user_id": 1}
- Email externo: {"type": "notification-recipient/raw-value",
"details": {"email": "x@y.com"}}
Returns:
Dict con la suscripcion creada: id, active, payload_type,
payload, subscriptions, handlers, created_at.
Example:
>>> sub = metabase_create_dashboard_subscription(
... client,
... dashboard_id=42,
... cron_schedule="0 8 * * 1",
... recipients=[
... {"type": "notification-recipient/user", "user_id": 5},
... ],
... )
>>> print(sub["id"], sub["payload"]["dashboard_id"])
"""
body = {
"payload_type": "notification/dashboard",
"payload": {
"dashboard_id": dashboard_id,
},
"subscriptions": [
{
"type": "notification-subscription/cron",
"cron_schedule": cron_schedule,
}
],
"handlers": [
{
"channel_type": "channel/email",
"recipients": recipients,
}
],
"active": True,
}
return client.request("POST", "/api/notification", json=body)
def metabase_update_notification(
client: MetabaseClient,
notification_id: int,
**fields,
) -> dict:
"""Actualiza una notificacion existente (alerta o suscripcion).
Endpoint: PUT /api/notification/:id.
Permite modificar campos como active, handlers, subscriptions,
payload, etc. Solo se envian los campos proporcionados.
Args:
client: Cliente autenticado.
notification_id: ID de la notificacion a modificar.
**fields: Campos a actualizar. Ejemplos:
active=False para desactivar.
handlers=[...] para cambiar destinatarios.
subscriptions=[...] para cambiar el cron.
Returns:
Dict con la notificacion actualizada: id, active, payload_type,
payload, subscriptions, handlers, updated_at.
Example:
>>> # Desactivar una alerta
>>> updated = metabase_update_notification(client, 99, active=False)
>>> # Cambiar destinatarios
>>> updated = metabase_update_notification(
... client,
... 99,
... handlers=[{
... "channel_type": "channel/email",
... "recipients": [
... {"type": "notification-recipient/user", "user_id": 2},
... ],
... }],
... )
>>> print(updated["active"])
"""
return client.request("PUT", f"/api/notification/{notification_id}", json=fields)
def metabase_delete_notification(
client: MetabaseClient,
notification_id: int,
) -> None:
"""Elimina una notificacion (alerta o suscripcion) de Metabase.
Endpoint: DELETE /api/notification/:id.
La operacion es irreversible. Afecta tanto a alertas de cards
como a suscripciones de dashboards.
Args:
client: Cliente autenticado.
notification_id: ID de la notificacion a eliminar.
Returns:
None.
Example:
>>> metabase_delete_notification(client, 99)
>>> # La notificacion ya no existe
"""
client.request("DELETE", f"/api/notification/{notification_id}")