621e8895c9
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
100 lines
5.2 KiB
Markdown
100 lines
5.2 KiB
Markdown
---
|
|
name: matrix_message_send
|
|
kind: function
|
|
lang: go
|
|
domain: infra
|
|
version: "0.1.0"
|
|
purity: impure
|
|
signature: |
|
|
func MatrixSendText(ctx context.Context, client *mautrix.Client, roomID id.RoomID, body string) (id.EventID, error)
|
|
func MatrixSendMarkdown(ctx context.Context, client *mautrix.Client, roomID id.RoomID, markdown string) (id.EventID, error)
|
|
func MatrixSendReply(ctx context.Context, client *mautrix.Client, roomID id.RoomID, replyTo id.EventID, body string) (id.EventID, error)
|
|
func MatrixEditMessage(ctx context.Context, client *mautrix.Client, roomID id.RoomID, eventID id.EventID, newBody string) (id.EventID, error)
|
|
func MatrixSendReaction(ctx context.Context, client *mautrix.Client, roomID id.RoomID, targetEventID id.EventID, key string) (id.EventID, error)
|
|
description: "Envía mensajes Matrix con todas las variantes del compositor: texto plain, markdown con HTML sanitizado, reply con m.in_reply_to, edit (m.replace) y reaction (m.annotation). Si el room es E2EE y client.Crypto está configurado via matrix_crypto_init, mautrix cifra automáticamente."
|
|
tags: [matrix, mautrix, send, message, markdown, reply, edit, reaction, infra, matrix-mas]
|
|
params:
|
|
- name: ctx
|
|
desc: "Context para cancelación y timeout de la petición HTTP a Synapse."
|
|
- name: client
|
|
desc: "*mautrix.Client autenticado. Debe tener AccessToken, UserID y DeviceID. Si es nil, error inmediato."
|
|
- name: roomID
|
|
desc: "ID del room Matrix destino. Formato: !xxx:server."
|
|
- name: body / markdown / newBody
|
|
desc: "Contenido del mensaje. Para MatrixSendMarkdown se parsea con goldmark y se sanitiza con bluemonday UGCPolicy."
|
|
- name: replyTo / eventID / targetEventID
|
|
desc: "ID del evento referenciado (para reply, edit y reaction)."
|
|
- name: key
|
|
desc: "Emoji unicode raw para reaction (ej. '👍'). No shortcodes (:thumbsup:)."
|
|
output: "id.EventID del evento enviado por Synapse + error. El EventID permite referenciar el mensaje para edits, replies o reactions posteriores."
|
|
uses_functions: []
|
|
uses_types: []
|
|
returns: []
|
|
returns_optional: false
|
|
error_type: "error_go_core"
|
|
imports:
|
|
- "context"
|
|
- "bytes"
|
|
- "fmt"
|
|
- "github.com/microcosm-cc/bluemonday"
|
|
- "github.com/yuin/goldmark"
|
|
- "maunium.net/go/mautrix"
|
|
- "maunium.net/go/mautrix/event"
|
|
- "maunium.net/go/mautrix/id"
|
|
tested: true
|
|
tests:
|
|
- "SendText body correcto y EventID parseado"
|
|
- "SendMarkdown bold convierte a HTML strong y sanitiza script"
|
|
- "SendReply m.relates_to m.in_reply_to presente"
|
|
- "EditMessage rel_type m.replace y m.new_content"
|
|
- "SendReaction tipo m.reaction con m.annotation y key"
|
|
- "SendText client nil devuelve error"
|
|
- "SendMarkdown client nil devuelve error"
|
|
- "SendReply client nil devuelve error"
|
|
- "EditMessage client nil devuelve error"
|
|
- "SendReaction client nil devuelve error"
|
|
test_file_path: "functions/infra/matrix_message_send_test.go"
|
|
file_path: "functions/infra/matrix_message_send.go"
|
|
---
|
|
|
|
## Ejemplo
|
|
|
|
```go
|
|
import (
|
|
"context"
|
|
infra "fn-registry/functions/infra"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
ctx := context.Background()
|
|
roomID := id.RoomID("!abc123:organic-machine.com")
|
|
|
|
// Texto plain
|
|
evID, err := infra.MatrixSendText(ctx, client, roomID, "Hola")
|
|
|
|
// Markdown: **bold**, `code`, > quote -> HTML sanitizado
|
|
evID, err = infra.MatrixSendMarkdown(ctx, client, roomID, "**bold** + `code`")
|
|
|
|
// Reply a un evento existente
|
|
evID, err = infra.MatrixSendReply(ctx, client, roomID, id.EventID("$orig:server"), "Si, totalmente")
|
|
|
|
// Edit de un mensaje ya enviado
|
|
evID, err = infra.MatrixEditMessage(ctx, client, roomID, id.EventID("$msg:server"), "texto corregido")
|
|
|
|
// Reaction emoji
|
|
evID, err = infra.MatrixSendReaction(ctx, client, roomID, id.EventID("$msg:server"), "👍")
|
|
```
|
|
|
|
## Cuando usarla
|
|
|
|
Llamar desde el compositor del cliente Matrix (`matrix_client_pc`) tras inicializar el cliente con `matrix_client_init`. Si el room es E2EE, llamar primero a `matrix_crypto_init` para que `client.Crypto` esté configurado — el cifrado es transparente, no requiere código extra en estas funciones.
|
|
|
|
## Gotchas
|
|
|
|
- **Markdown sanitization**: goldmark puede emitir tags HTML arbitrarios si el input los contiene. Esta función aplica `bluemonday.UGCPolicy()` + allowlist extra (`details`, `summary`, `code`, `pre`). Tags fuera de la allowlist como `<script>`, `<iframe>`, `<style>` son eliminados. El texto interno puede quedar como texto plano.
|
|
- **Edits sobre mensajes cifrados**: mautrix-go cifra el `m.new_content` también. Receivers que no tengan acceso a la session megolm no verán el edit — verán el mensaje original.
|
|
- **Reactions** son evento separado `m.reaction`, NO `m.room.message`. Algunos clientes Matrix viejos las ignoran. No se cifran aunque el room sea E2EE (limitación de mautrix-go).
|
|
- **Reply quote v0.1.0**: esta función NO inserta el texto del mensaje original en el body. Es responsabilidad del caller construir la cita si la necesita. v0.2.0 podría hacer fetch del original via state cache.
|
|
- **Edit racing**: si dos edits llegan al mismo tiempo al servidor, gana el de timestamp mayor (regla Matrix server-side). No hay protección contra races en esta función.
|
|
- **client nil**: todas las funciones validan `client != nil` y retornan error inmediato. No hacen validación del formato de `roomID` — Synapse responderá con error si es inválido.
|