Comandos con barra diagonal

Un comando con barra diagonal personalizado permite a las personas escribir /algo en el cuadro de mensajes para invocar tu servicio. Antimatter envía el comando a tu URL y muestra tu respuesta, ya sea solo para esa persona o para todo el canal.

Cómo funciona un comando con barra diagonal

  1. Alguien escribe /weather Paris y lo envía. El texto no se publica.
  2. Antimatter envía una solicitud HTTP a la URL del comando, con quién lo escribió, dónde y el texto después de la palabra que lo dispara.
  3. Tu servicio responde dentro del tiempo de espera de la solicitud (30 segundos por defecto) con un mensaje.
  4. Antimatter muestra la respuesta: solo para esa persona (efímera) o en el canal para todos.

Los comandos pertenecen a una comunidad, y la palabra que los dispara es única dentro de ella. Los comandos integrados, como /join, /msg o /away, no se pueden reemplazar. Las aplicaciones (plugins) también pueden registrar comandos; consulta La parte del servidor.

Crear un comando

Los comandos con barra diagonal personalizados están habilitados por defecto (Habilitar Comandos de Barra Personalizados en Consola de sistema › Integraciones › Gestión de Integraciones, ServiceSettings.EnableCommands). Los administradores de la comunidad y los administradores del sistema pueden crearlos por defecto.

  1. Abre el menú de la comunidad, luego Configuración del equipo, haz clic en Integraciones al final de sus pestañas, luego en Comandos con barra diagonal y en Agregar Comandos de Barra.
  2. Completa el Título y la Descripción (se muestran en las páginas de integraciones).
  3. Introduce la Palabra que disparan el Comando, sin la barra diagonal y sin espacios, por ejemplo weather.
  4. Introduce la URL de Solicitud y elige el Método de Solicitud: POST (el predeterminado) o GET.
  5. Opcionalmente, establece un Nombre de usuario de Respuesta y un Icono de Respuesta. Solo se usan cuando el servidor permite que las integraciones sobrescriban nombres e iconos (consulta Nombre e icono).
  6. Marca Autocompletar para listar el comando cuando las personas escriben /, con una Pista del Autocompletado (sus argumentos, como [city]) y una Descripción del Autocompletado.
  7. Elige Guardar y copia el token mostrado. Tu servicio lo usa para verificar que las solicitudes provienen de tu servidor.

Con la API: POST /api/v4/commands con {"team_id", "trigger", "url", "method": "P", "display_name", "description", "auto_complete": true, "auto_complete_hint", "auto_complete_desc", "username", "icon_url"}. El método es P para POST o G para GET. PUT /api/v4/commands/{command_id}/regen_token emite un nuevo token.

La solicitud que recibe tu servicio

Un comando POST envía un cuerpo codificado en formulario (application/x-www-form-urlencoded); un comando GET envía los mismos campos en la cadena de consulta. El token también se encuentra en la cabecera Authorization: Token <token>.

CampoValor
tokenEl token del comando. Verifícalo en cada solicitud.
commandEl disparador con su barra diagonal, por ejemplo /weather.
textTodo lo que sigue al disparador, por ejemplo Paris.
user_id, user_nameQuién lo ejecutó.
channel_id, channel_nameDónde se ejecutó.
team_id, team_domainEl ID y el nombre de URL de la comunidad.
root_idEl hilo, cuando se ejecutó en la caja de respuestas de un hilo.
trigger_idPermite que tu respuesta abra un diálogo (ver Diálogos). Solo es válido por un tiempo breve.
response_urlUna URL para publicar más respuestas más tarde (ver Respuestas diferidas).
user_mentions, user_mentions_ids, channel_mentions, channel_mentions_idsLas personas y los canales públicos mencionados en el texto, si los hay. Los canales se cuentan tanto si se escriben como #channel-name como ~channel-name.
La URL del Sitio del servidor debe estar configurada para que los comandos personalizados funcionen: Antimatter construye response_url a partir de ella.

La respuesta

Responde 200 con JSON (Content-Type: application/json):

{
  "response_type": "in_channel",
  "text": "Paris: 18 °C, light rain",
  "attachments": []
}
CampoSignificado
response_typeephemeral (el valor predeterminado): solo la persona que ejecutó el comando ve la respuesta, y esta no se conserva tras una recarga. in_channel: la respuesta se publica en el canal.
text, attachmentsEl mensaje, como en los webhooks: texto en Markdown y adjuntos, incluidos botones y menús.
username, icon_urlEl nombre y la imagen a mostrar, cuando se permiten reemplazos. La configuración propia del comando tiene prioridad sobre estos.
channel_idPublica la respuesta en otro canal, del cual la persona debe ser miembro.
goto_locationUna URL para abrir una vez que el comando se ha ejecutado.
props, typePropiedades adicionales y un tipo de publicación personalizado, como en los webhooks. Una respuesta publicada en un canal de foro necesita props.am_thread_title; de lo contrario, se rechaza.
extra_responsesMás respuestas, cada una con los mismos campos, publicadas después de la primera.
skip_slack_parsingtrue mantiene el texto tal como está, sin convertir enlaces y menciones de estilo Slack.

Una respuesta que no sea JSON se muestra como un mensaje efímero con el cuerpo como su texto. 204 No Content no muestra nada. Cualquier estado fuera del rango 200–299 muestra un error a la persona.

Servicio de ejemplo

Un servicio de comando mínimo en Python, con solo la biblioteca estándar:

import hmac
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs

TOKEN = "the token shown when you saved the command"

class Handler(BaseHTTPRequestHandler):
    def do_POST(self):
        body = self.rfile.read(int(self.headers["Content-Length"])).decode()
        form = {key: values[0] for key, values in parse_qs(body).items()}
        if not hmac.compare_digest(form.get("token", ""), TOKEN):
            self.send_response(401)
            self.end_headers()
            return
        answer = {
            "response_type": "ephemeral",
            "text": f"Hello @{form['user_name']}, you asked for: {form.get('text', '')}",
        }
        data = json.dumps(answer).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(data)

HTTPServer(("0.0.0.0", 8080), Handler).serve_forever()

Si el servicio se ejecuta en una dirección de red privada, un administrador del sistema debe permitirlo en Permitir conexiones internas no son de confianza (ServiceSettings.AllowedUntrustedInternalConnections).

Respuestas diferidas

Para el trabajo que toma más tiempo que el tiempo de espera, responde de inmediato (por ejemplo, con un mensaje efímero «Trabajando en ello…») y luego envía la respuesta real mediante POST a response_url. Acepta el mismo JSON que la respuesta y funciona hasta 5 veces dentro de los 30 minutos posteriores al comando.

curl -X POST "$RESPONSE_URL" -H 'Content-Type: application/json' \
  -d '{"response_type": "in_channel", "text": "Report ready: https://reports.example.com/42"}'

Ejecutar un comando con la API

Los scripts y los bots pueden ejecutar cualquier comando, integrado o personalizado, como si lo hubieran escrito:

curl -X POST https://chat.example.com/api/v4/commands/execute \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"channel_id": "'$CHANNEL_ID'", "command": "/weather Paris"}'

GET /api/v4/teams/{team_id}/commands/autocomplete lista los comandos que las personas pueden autocompletar en una comunidad.

Autocompletado

Los comandos creados en las páginas de integraciones se autocompletan con su disparador, pista y descripción. Los comandos registrados por las aplicaciones pueden describir en detalle sus subcomandos y argumentos con AutocompleteData, desde model.NewAutocompleteData(trigger, hint, helpText):

  • AddCommand(sub) agrega un subcomando, que a su vez es un AutocompleteData.
  • AddTextArgument(helpText, hint, pattern) agrega texto libre.
  • AddStaticListArgument(helpText, required, items) ofrece una lista fija de AutocompleteListItem{Item, Hint, HelpText}.
  • AddDynamicListArgument(helpText, url, required) solicita a tu aplicación sugerencias mientras las personas escriben. La URL es una ruta de tu aplicación, como /plugins/com.example.weather/cities. Recibe el usuario, el canal y la comunidad, y devuelve una lista JSON de {"Item", "Hint", "HelpText"}.

Las variantes Named… (AddNamedTextArgument y otras) añaden marcas --name value. Ambas interfaces web muestran estas sugerencias. Un valor con espacios puede ir entre comillas para que se autocomplete como un solo argumento, por ejemplo --name "my remote": las comillas dobles funcionan para todos los comandos, y los comandos propios de Antimatter que aceptan marcas también aceptan comillas simples o angulares.

Mientras alguien escribe un comando, Fusion muestra el comando y cada uno de sus argumentos como un bloque, resaltando el que se está escribiendo junto con su texto de ayuda. Los argumentos provienen de AutocompleteData o, en su ausencia, de la pista: en una pista como @[username]... #[channel], las palabras que comienzan con @ se asignan al argumento de personas y las que comienzan con # al argumento de canal, sin importar su orden; ... indica que el argumento se repite, y el último argumento toma el resto del texto.

Canales en los argumentos

En los argumentos de un comando, @ sugiere personas, # sugiere canales y los completa como #channel-name, y ~ los completa como ~channel-name. La interfaz web y la aplicación móvil de Antimatter escriben los enlaces de canal con #, por lo que un comando que reciba un canal debe aceptar ambas formas: los comandos integrados /join, /mute y /invite lo hacen, y sus pistas indican #[channel].