535 - Crear bots en Matrix
Como crear bots en #matrix en #linux con #docker sin utilizar las SDK de #python o #rust . Un bot es una excelente herramienta que te permite exprimir.
Por fin he completado la migración de Mattermost a Matrix. En estos últimos días he desinstalado Mattermost de mi servidor. Soy consciente que todavía tengo algún fleco pendiente, pero esto es lo de menos. Con el paso de los días, y tras una búsqueda de 404 lo iré resolviendo. Sin embargo, ha llegado el momento de meterme de lleno en el mundo de Matrix, y completar aquellas operaciones que no supe, no quise o no pude hacer en Mattermost, y que he visto, recientemente que si puedo hacer en Matrix. Básicamente me refiero a crear bots en Matrix.
Para aquel despistado, indicar, que no me refiero a nada que tenga que ver con la película, sino mas bien me refiero a la red social o al servicio Matrix. Para mi en cualquier caso, es mas servicio que red social, pero esto dependerá del uso que le estés dando.
Crear bots en Matrix
Un paseo por el pasado
Como te decía en la introducción, lo cierto es que esta migración de Mattermost a Matrix me ha llevado mas tiempo del que esperaba. Y no solo mas tiempo sino que también me ha llevado mas trabajo. Esto es precisamente, porque Mattermost antes, al igual que Matrix ahora, lo estoy utilizando de forma extensiva para exprimirlo al máximo.
Con el paso del tiempo he ido desarrollando determinados servicios para exprimir Mattermost y darle un uso algo diferente del típico que se le puede dar.
En este sentido, tengo que recordar, que desde un principio fue Ángel de uGeek, el que me habló sobre Matrix y las posibilidades que tenía. Sin embargo, por aquel entonces y después de probar en modo self hosted tanto Mattermost como Matrix finalmente me decanté por la primera.
Sin embargo, con el trascurso del tiempo y de las versiones, sin lugar a dudas Matrix, al menos para mi, se ha puesto por delante. Sobre todo desde que empecé a utilizar la versión de servidor Conduit implementada en Rust, y que le da mucha mas solidez al proyecto, que la versión Synapse o al menos, es la sensación que tengo.
Pero no solo es la parte de servidor, también está la parte de los clientes, con el paso del tiempo, han ido aflorando nuevas versiones de aplicaciones cada vez mejores y con mayores prestaciones.
Así, actualmente estoy utilizando cinny como cliente web. Y si bien, no tiene todas las prestaciones de Element, lo cierto es que funciona espectacularmente bien. Y para el caso del móvil, estoy utilizando otra aplicación que recomendó Ángel que es fluffychat, y que es sencilla, elegante y que cumple con todo lo que puedes esperar.
Instalación de Conduit y fluffychat
Actualmente tengo instalado tanto Conduit como fluffychat en un VPS utilizando docker, y en concreto con un docker-compose.yml
, que te dejo a continuación,
version: '3.7'
services:
cinny:
image: ajbura/cinny:latest
init: true
container_name: cinny
volumes:
- ./config.json:/app/config.json
networks:
- proxy
labels:
- traefik.enable=true
- traefik.http.services.cinny.loadbalancer.server.port=80
- traefik.http.routers.cinny-secure.entrypoints=https
- traefik.http.routers.cinny-secure.rule=Host(`FQDN_CINNY`)
- traefik.http.routers.cinny-secure.tls=true
- traefik.http.routers.cinny-secure.middlewares=traefik-real-ip@file,http2https@file
- traefik.http.routers.cinny-secure.tls.certresolver=myresolver
conduit:
image: matrixconduit/matrix-conduit:latest
container_name: conduit
init: true
restart: unless-stopped
volumes:
- db:/var/lib/matrix-conduit/
- ./conduit.toml:/conduit.toml
environment:
CONDUIT_CONFIG: /conduit.toml
RUST_BACKTRACE: full
networks:
- proxy
labels:
- traefik.enable=true
- traefik.http.services.conduit.loadbalancer.server.port=6167
- traefik.http.routers.conduit-secure.entrypoints=https
- traefik.http.routers.conduit-secure.rule=Host(`FQDN_MATRIX`)
- traefik.http.routers.conduit-secure.tls=true
- traefik.http.routers.conduit-secure.tls.certresolver=myresolver
- traefik.http.routers.conduit-secure.middlewares=cors-headers@docker
- traefik.http.middlewares.cors-headers.headers.accessControlAllowOriginList=*
- traefik.http.middlewares.cors-headers.headers.accessControlAllowHeaders=Origin, X-Requested-With, Content-Type, Accept, Authorization
- traefik.http.middlewares.cors-headers.headers.accessControlAllowMethods=GET, POST, PUT, DELETE, OPTIONS
well-known:
image: nginx:latest
restart: unless-stopped
volumes:
- ./nginx/matrix.conf:/etc/nginx/conf.d/matrix.conf # the config to serve the .well-known/matrix files
- ./nginx/www:/var/www/ # location of the client and server .well-known-files
networks:
- proxy
labels:
- traefik.enable=true
- traefik.http.routers.to-matrix-wellknown.rule=Host(`FQDN_MATRIX`) && PathPrefix(`/.well-known/matrix`)
- traefik.http.routers.to-matrix-wellknown.tls=true
- traefik.http.routers.to-matrix-wellknown.tls.certresolver=myresolver
- traefik.http.routers.to-matrix-wellknown.middlewares=cors-headers@docker
- traefik.http.middlewares.cors-headers.headers.accessControlAllowOriginList=*
- traefik.http.middlewares.cors-headers.headers.accessControlAllowHeaders=Origin, X-Requested-With, Content-Type, Accept, Authorization
- traefik.http.middlewares.cors-headers.headers.accessControlAllowMethods=GET, POST, PUT, DELETE, OPTIONS
volumes:
db: {}
networks:
proxy:
external: true
¿Porque crear bots para Matrix?
Hasta el momento le estaba dando a Matrix el mismo uso que le daba a Mattermost. En concreto estar informado de todo lo que sucedía en el ecosistema atareao.es. Pero evidentemente, esto lo puedes aplicar en tu caso para adaptarlo a tus necesidades. Por ejemplo,
- tengo monitorizadas las páginas web que actualmente administro, de forma que si alguna de ellas queda indisponible me llega una notificación
- esto mismo de las páginas weg, lo aplico a mis servicios que actualmente tengo en contenedores, de forma, que si alguno de los servicios queda indisponible, también me notifica
- igualmente lo utilizo para recibir los comentarios de atareao.es, al igual que algunos mensajes que van directamente. Esto me evita tener que leerlos directamente en la página web, a través del backend de WordPress.
- Otro de los usos es el de recibir los correos electrónicos. En lugar de consultarlos a través del cliente habitual, los correos me llegan también a Matrix, donde puedo consultarlos cómodamente.
- Algunas operaciones relacionadas con la domótica. Aquí por supuesto, me puedes decir que podría tener Home Assistant, pero lo cierto, es que tengo cuatro cosas domotizadas y no quiero meterme en mas lios.
Enviar un mensaje a Matrix es algo muy sencillo. Es únicamente una llamada curl
a un servidor, y listo. Sin embargo, no es esto lo que quiero hacer. Quería implementar un bot, que me permitiera exprimir al máximo las posibilidades, y hacer la relación biunívoca, no como hasta el momento que era una relación unidireccional con el servidor. Quiero hacer mas cosas, cuestiones como,
- consultar el estado de un servicio de forma activa
- hacer fotografías
- obtener datos
- relacionarme con otros servicios
- consultar el correo electrónico de forma activa, y sobre todo, algo que hecho mucho en falta, es la posibilidad de responder al correo. Esto es algo que quería hacer y hasta la fecha no había podido… ya queda menos.
¿Como crear bots en Matrix?
Comencé a mirar los distintos kits de desarrollo, los SDK de Python, el de Rust, para Matrix, y te puedo asegurar que me parecieron tremendamente complejos. De hecho, llegué a instalar un servicio Maubot que te permite crear bots para Matrix en Python. Pero de verdad, que me parece un auténtico dolor.
Hace relativamente poco, comencé a exprimir el getUpdates
de Telegram. Una opción realmente interesante para conocer todo lo que está sucediendo a un bot de Telegram en forma de pooling, pero sin realizar tantas llamadas y mucho mas práctico e inteligente, dado que se queda a la escucha.
Y me pregunté ¿existirá esto mismo para Matrix? Y efectivamente, existe. Se trata de una operación similar llamada sync. Así que, dejé de lado todos los SDK y me lancé a implementar de forma directa el bot, sin necesidad de nada mas, y lo cierto es que ha sido todo un éxito.
Hasta la fecha, me he decantado por los webhook porque me parecían una solución de lo mas elegante. Sin embargo, tienen un problema fundamental para el común de los mortales, es la necesidad de un endpoint accesible. No todos tenemos una IP disponible, aunque siempre podrías tirar de DDNS… En fin, sea como fuere, getUpdates en el caso de Telegram y sync en el caso de Matrix, vienen a resolver este problema, y es la técnica que estoy utilizando.
Mi primer Matrixbot
Así ya tengo mi primer bot en Matrix. Utilizando esto de sync de forma activa, para conocer que es lo que está sucediendo en el servidor. Pero, no te hagas ilusiones, este bot, por el momento, es capaz de hacer pocas cosas. Básicamente, y por el momento, solo le he implementado tres comandos,
!hola
que te responde con unCoca Cola
!hora
este te dice los segundos que han trascurrido desde 1970!tiempo
y este último comando te dice la situación meteorológica en mi ciudad.
Si, se que es muy básico, pero, simplemente he puesto las bases para todo lo que quiero hacer, y que te he mencionado anteriormente. Desde luego que puedes encontrar el código en el repositorio de Github. Es un bot, implementado en Rust, utilizando tokio
, del que en algunos días te contaré mas cosas.
¿Que es lo que quiero hacer?
Como te he contado, algo que quiero hacer es contestar correos. Esto es algo que investigué en Mattermost, pero que no supe o no puede hacer, porque no llegaba información de cuando se replica a un mensaje. Sin embargo, en el caso de Matrix si que es posible.
Yo puedo responder a un mensaje, y que el bot extraiga la información de este mensaje y del mensaje anterior. Esto me va a permitir responder correos electrónicos desde Matrix, con tan solo responder a un mensaje de un correo electrónico. Dado que ahí tengo toda la información necesaria.
En las próximas semanas te iré contando como ha ido avanzando todo esto, y añadiré estas características al bot, para que tu también lo puedas utilizar si así lo consideras.