Saltearse al contenido

Cauce en ejemplos

Cada ejemplo muestra el archivo y el grafo que describe, uno al lado del otro. Se van sumando de a una cosa por vez: si entendés el primero, el último no tiene nada nuevo salvo más líneas.

Todos son archivos válidos. Se pueden pegar en un .toml y pasarlos por reply2fb cauce validar tal cual están.

1. Lo mínimo que vale

Una fuente, un destino, y un flujo entre las dos.

formato_version = 1
credenciales = "ausentes"
[[cuentas]]
handle = "gss"
plataforma = "instagram"
rol = "lectura"
id_remoto = "17841400000000000"
[[cuentas]]
handle = "sumud"
plataforma = "mastodon"
rol = "escritura"
instancia_url = "https://mastodon.cl"
max_por_hora = 4
[[flujos]]
clave = "gss-a-sumud"
origen = "gss"
destino = "sumud"
activa = true
auto_publica = false

Eso describe esto:

gss-a-sumud

gss

instagram · lectura

sumud

mastodon · escritura

4 por hora

formato_version y credenciales son obligatorios y van primero. El primero es lo que se mira antes de intentar entender el resto; el segundo dice si esto es un respaldo o una descripción — y de eso depende que alguien archive un archivo creyendo que puede restaurar con él.

max_por_hora va en la cuenta que RECIBE, no en el flujo. El límite es de quien recibe: si mañana tres flujos apuntan a sumud, el techo lo sigue poniendo Mastodon. En el flujo, tres rutas «de 4 por hora» harían 12.

2. Con filtro: sólo videos recientes

Se agrega una línea al flujo.

[[flujos]]
clave = "gss-a-sumud"
origen = "gss"
destino = "sumud"
activa = true
auto_publica = false
condicion = { tipo = ["VIDEO"], tag = ["palestina"], desde_dias = 30 }

pasa

no pasa:

se archiva igual

gss

filtro

tipo: VIDEO

tag: palestina

últimos 30 días

sumud

archivo

Los tres criterios se cumplen A LA VEZ. «Videos sobre Palestina de los últimos 30 días» quiere las tres cosas. Con un O, este flujo prendería con muchísimo más de lo que su autora pidió.

Y es fail-closed: un ítem sin tags no pasa un filtro por tag. No sabemos de qué habla, así que no afirmamos que hable de eso.

desde_dias acota lo que se EMITE, no lo que se archiva. El histórico completo sigue entrando al archivo — la flecha punteada del diagrama. Lo que esta ventana evita es que un rescate de dos años se convierta en dos años de publicaciones.

3. Una suscripción a cuenta pública

Una cuenta que dio permiso pero no puede entregar un token de la API. Se lee entrando a su perfil con un navegador.

[[cuentas]]
handle = "colectivo"
plataforma = "instagram"
rol = "lectura"
id_remoto = "colectivo"
via = "navegador"
poll_horas = 12

con token

sin token

colectivo

via = navegador

gss

Graph API

navegador headless

entra al perfil público

API de Meta

archivo

via es explícito y no se infiere de que falte la credencial. Inferirlo convertiría un token revocado en un scrapeo de un perfil público, sin que nadie lo decidiera. Y sin este campo en el archivo, exportar y volver a importar convertía la suscripción en una cuenta normal: exige token, no lo tiene, y no trae nada — en silencio.

4. Un feed RSS

La URL del feed va en id_remoto. No lleva instancia_url, que nombra el servidor de una cuenta federada.

[[cuentas]]
handle = "sitio-propio"
plataforma = "rss"
rol = "lectura"
id_remoto = "https://ejemplo.org/feed.xml"
poll_horas = 1
[[flujos]]
clave = "rss-a-telegram"
origen = "sitio-propio"
destino = "canal"
activa = true
auto_publica = false
condicion = { autor = ["Redacción"] }

autor existe para las fuentes que distinguen autor de cuenta: el feed de un sitio donde escribe mucha gente, o un canal de Telegram con firmas. En una cuenta de Instagram, autor y cuenta son lo mismo y el criterio no sirve de nada.

5. El sitio propio como destino

Una cuenta web es un sitio: se lee de él y se publica en él.

[[cuentas]]
handle = "sitio"
plataforma = "web"
rol = "ambos"
id_remoto = "sitio-propio"
[cuentas.sitio]
api_url = "http://127.0.0.1:8181"
sitio_url = "https://ejemplo.org"
uid_servicio = "160451ec-828f-4a5b-b78c-04ff5c44fcab"
tipos = ["post", "articulo"]

api_url

127.0.0.1:8181

los posts salen

a nombre de uid_servicio

el enlace usa

sitio_url

reply2social

el sitio

publicado

quien lo lee

api_url y sitio_url son distintas a propósito. La primera es por donde este proceso alcanza al sitio, y suele ser una dirección interna que no existe para nadie más. Publicar un enlace a 127.0.0.1 es publicar un enlace roto.

Va en la cuenta y no en el entorno del proceso. Antes era una variable global, o sea que una instalación servía a un sitio: con dos cuentas web, las dos publicaban en el que dijera la variable — la segunda en el sitio equivocado, sin ningún error.

6. Una instalación completa

Todo junto: dos fuentes, tres destinos, cuatro flujos.

formato_version = 1
credenciales = "ausentes"
# ── Fuentes ──────────────────────────────────────────────────────────────
[[cuentas]]
handle = "gss"
plataforma = "instagram"
rol = "lectura"
id_remoto = "17841400000000000"
poll_horas = 6
consentimiento_vigente = "mastodon+telegram"
[[cuentas]]
handle = "prensa"
plataforma = "rss"
rol = "lectura"
id_remoto = "https://ejemplo.org/feed.xml"
poll_horas = 1
# ── Destinos ─────────────────────────────────────────────────────────────
[[cuentas]]
handle = "sumud"
plataforma = "mastodon"
rol = "escritura"
instancia_url = "https://mastodon.cl"
max_por_hora = 4
max_en_vuelo = 1
video_como_imagenes = 3
[[cuentas]]
handle = "canal"
plataforma = "telegram"
rol = "escritura"
id_remoto = "-1001234567890"
# ── Flujos ───────────────────────────────────────────────────────────────
[[flujos]]
clave = "gss-a-sumud"
origen = "gss"
destino = "sumud"
nombre = "videos recientes → Mastodon"
activa = true
auto_publica = false
condicion = { tipo = ["VIDEO"], desde_dias = 30 }
[[flujos]]
clave = "gss-a-canal"
origen = "gss"
destino = "canal"
activa = true
auto_publica = false
[[flujos]]
clave = "prensa-a-sumud"
origen = "prensa"
destino = "sumud"
activa = false
auto_publica = false
condicion = { autor = ["Redacción"] }

sólo VIDEO,

últimos 30 días

todo

pausado ·

autor: Redacción

gss

instagram · 6 h

prensa

rss · 1 h

sumud

mastodon · 4/h

3 fotogramas si hay video

canal

telegram

Fijate que prensa-a-sumud va punteado: está declarado con activa = false. El grafo dibuja lo que hay, no lo que corre.

7. Un respaldo, que es otra cosa

El mismo formato, con la cabecera distinta y dos bloques más. Sale sólo por CLI, con cauce exportar --respaldo.

formato_version = 1
credenciales = "cifradas"
[cifrado]
algoritmo = "AES-256-GCM"
huella_clave = "b3f1a9c7"
[[cuentas]]
handle = "gss"
plataforma = "instagram"
rol = "lectura"
id_remoto = "17841400000000000"
credencial_cifrada = "k3JhbmRvbS1ieXRlcy1hcXVpLXF1ZS1uby1zaXJ2ZW4..."

Este archivo no se commitea. Trae las credenciales tal como están en la base. huella_clave está para saber, antes de intentar restaurar, si esta instalación tiene la clave con que se cifraron — descubrirlo al final de un desastre es tarde.

Por HTTP los tokens salen vacíos, siempre. No hay parámetro ni permiso que haga que el panel entregue esto. Es lo que deja al invariante «ningún endpoint devuelve texto cifrado» sin excepciones que recordar.

Qué dice el plan

Antes de aplicar nada, reply2fb cauce importar archivo.toml muestra qué haría:

+ prensa
= gss
= sumud
~ canal (max_por_hora)
+ prensa-a-sumud
= gss-a-sumud
· 'gss' trae anotado un consentimiento: es informativo y el import NO lo
otorga. Un permiso se afirma en el panel, con quién lo afirma y cuándo
· gss-a-sumud: viene activo. El import lo crea PAUSADO igual
cuentas: 1 nueva(s), 2 sin cambios, 1 a actualizar · flujos: 1 nuevo(s), 1 sin cambios
Esto es sólo el PLAN: no se escribió nada. Con --aplicar se aplica.
MarcaSignifica
+Se crearía
=Ya está, y queda como está
~Está, y el archivo declara otra cosa — se listan qué campos
Conflicto o falla: el plan entero se niega
·Un aviso: algo que el archivo declara y el import no va a aplicar

~ lista los campos. «Se actualizó la cuenta» no dice nada; «(max_por_hora)» deja ver que lo que cambia es el grifo, que es una decisión con consecuencia sobre cuánto sale por hora.