Administro un foro pequeño y otros tres sitios web, y no dejaba de notar lo mismo. A la gente le gustaba chatear una vez que estaba en el foro, pero nadie va a un foro para hacer una pregunta rápida. La hacen donde ya están, o simplemente no la hacen.
Así que he creado un plugin que lleva el chat del foro a esos otros sitios. Con una sola etiqueta de script, aparece una burbuja en la esquina. Los visitantes inician sesión con la cuenta del foro que ya tienen, a través de la propia pantalla de inicio de sesión del foro, y chatean en los mismos canales que verían en el foro. Los mensajes que envían llegan al chat del foro como cualquier otro mensaje, porque lo son.
Repositorio: GitHub - capodieci/discourse-chat-bridge: Allows to install discourse chat as a plugin in other websites · GitHub (MIT)
<script src="https://forum.example.com/chat-bridge/widget.js"
data-site-key="your-site-key" defer></script>
Por qué es un plugin y no un servicio
Empecé diseñando un puente externo que se comunicaría con Discourse a través de la API, y luego leí el código fuente. Eso cambió el diseño por completo, y las razones pueden ser útiles para cualquiera que esté considerando algo similar.
El plugin de chat registra exactamente un ámbito de API granular: create_message. Cualquier cosa más allá de publicar, como leer canales, obtener el historial o abrir un mensaje directo, requiere una clave de ámbito global, y mantener una clave de ámbito global para cada usuario es una gran pila de credenciales que gestionar. Los límites de velocidad predeterminados son de 60 solicitudes por minuto en el cubo de administrador y 20 en el de usuario, lo que un cliente de chat consume sin esfuerzo. Y los webhooks de chat transportan cuatro eventos de mensaje y nada más, por lo que las reacciones, la presencia y el estado de lectura simplemente no están disponibles para reenviar.
Todos esos problemas desaparecen cuando el código se ejecuta dentro de Discourse y puede hacerle una pregunta directamente a Guardian. Sin claves, sin techo de límite de velocidad, y una única fuente de verdad en lugar de una caché que puede no coincidir con el foro.
Lo que funciona
Canales, historial de mensajes, envío, mensajes directos con búsqueda de personas, y mensajes de voz grabados en el navegador. Los mensajes de voz aparecen como un reproductor de audio normal para los miembros que leen el propio chat del foro, no como un enlace de descarga, lo cual requirió cierto cuidado para hacerlo bien.
Cada sitio web tiene su propio color de acento, esquina y título de panel, de modo que tres sitios pueden parecer tres productos diferentes en lugar de tres copias del mismo widget. Los visitantes reciben un sonido de notificación que pueden desactivar, una opción de tema claro u oscuro, y la capacidad de silenciar una conversación, lo cual se escribe en su membresía real de Discourse para que los siga de vuelta al foro.
Todo se renderiza dentro de un Shadow DOM. Esto funciona en páginas que no controlo, y el CSS de ningún lado debería poder romper el del otro.
Lo que no funciona, y por qué
No hay llamadas de voz o video. Es deliberado y está fuera del alcance.
La entrega no es instantánea. Los mensajes llegan en unos tres segundos mientras el panel está abierto. Esto merece una explicación, porque Discourse sí publica eventos de chat en MessageBus y parece que debería funcionar sin más.
Un navegador en otro dominio no puede autenticarse en el punto de acceso de MessageBus. Su política CORS permite cuatro encabezados de solicitud y ninguno de ellos transporta un token de portador, y la ruta de parámetro de consulta hacia la autenticación de Discourse está restringida a los puntos de acceso RSS y de calendario. El único encabezado que sí funciona, X-Shared-Session-Key, se resuelve en un UserAuthToken y por lo tanto autentica cualquier solicitud que lo transporte, no solo las de MessageBus. Entregar eso a una página de inserción convertiría un agujero de cross-site scripting en un sitio de marketing en una toma de control total de la cuenta del foro. Tres segundos es el mejor compromiso.
Hay una ruta más segura hacia el tiempo real documentada en el repositorio, que utiliza un canal de MessageBus cuyo nombre inagotable es en sí mismo la capacidad, acotado a una sesión de widget en lugar de a la cuenta del usuario. No lo he construido. Si alguien quiere hacerlo, el razonamiento está en docs/decisions.md.
Lo que hay que entender antes de instalar
Registrar un sitio web otorga a ese sitio web acceso cross-origin a tu foro llevando las credenciales de tus miembros. Eso no es un efecto secundario, es el mecanismo.
Si un sitio que has registrado es comprometido, un atacante que pueda ejecutar JavaScript allí puede actuar como cualquier miembro que lo visite. No solo en el chat. Cualquier cosa que ese miembro pudiera hacer en el foro.
Así que solo registra sitios que controles. Registrar el sitio de un socio o de un cliente significa aceptar su seguridad como la tuya. El plugin dice esto en la página de administración junto al campo donde escribes el origen, en lugar de en un documento que nadie abre, y SECURITY.md detalla lo que el plugin hace para limitar el radio de impacto y lo que deliberadamente no hace.
Instalación
Añádelo a tu definición de contenedor y reconstruye una vez:
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone --depth 1 https://github.com/capodieci/discourse-chat-bridge.git
env:
DISCOURSE_ENABLE_CORS: true
Luego activa chat_bridge_enabled en Administración, Configuración, y todo lo demás está en una sola página en /chat-bridge/admin, donde añades un sitio web y te entrega la etiqueta de script.
Dos notas que le ahorrarán una tarde a alguien. Los mensajes de voz necesitan formatos de audio en authorized_extensions, que por defecto no contiene ninguno, así que la página de administración te dice exactamente cuáles faltan. Y chat_allowed_groups por defecto es nivel de confianza 1, por lo que las cuentas recién creadas no pueden chatear hasta que lo ganen, lo cual el widget explica en lugar de fallar en silencio.
Compatibilidad
Probado contra Discourse 2026.9.0 y 2026.8.0, y en uso en producción en un foro.
Esto depende de objetos de servicio de chat que no son API pública, por lo que una versión de Discourse puede moverlos. El repositorio incluye un script de pre-vuelo de solo lectura que afirma que todos ellos aún existen e informa en segundos en lugar de en la primera solicitud. Vale la pena ejecutarlo después de una actualización.
Lo que me gustaría
Que alguien lo instale en un foro que no es mío y me diga qué se rompió. Todo hasta ahora está verificado contra un Discourse, en un servidor, por una persona, y eso es lo más débil de todo.
También me gustaría oír de cualquiera que sepa una mejor respuesta al problema de MessageBus que la en la que me decidí.
