Comandi con barra

Un comando con barra personalizzato consente di digitare /qualcosa nella casella di messaggio per chiamare il proprio servizio. Antimatter invia il comando all'URL specificato e mostra la risposta, destinata solo a chi ha digitato il comando o a tutto il canale.

Come funziona un comando con barra

  1. Qualcuno digita /weather Paris e invia. Il testo non viene pubblicato.
  2. Antimatter invia una richiesta HTTP all'URL del comando, includendo chi l'ha digitato, dove e il testo dopo la parola di esecuzione.
  3. Il servizio risponde entro il timeout della richiesta (30 secondi di default) con un messaggio.
  4. Antimatter mostra la risposta: solo a quella persona (effimere) o nel canale per tutti.

I comandi appartengono a una community e la parola di esecuzione è unica all'interno di essa. I comandi integrati come /join, /msg o /away non possono essere sostituiti. Le app (plugin) possono registrare comandi; vedere La parte server.

Creare un comando

I comandi con barra personalizzati sono abilitati di default (Abilita Comandi Slash Personalizzati in Console di Sistema › Integrazioni › Gestione integrazioni, ServiceSettings.EnableCommands). Gli amministratori di community e gli amministratori di sistema possono crearli di default.

  1. Apri il tuo avatar in alto a destra, poi Integrazioni › Comandi con barra, poi Aggiungere Comando Slash.
  2. Compila il Titolo e la Descrizione (visualizzati nelle pagine delle integrazioni).
  3. Inserisci la Parola di esecuzione del comando, senza la barra e senza spazi, ad esempio weather.
  4. Inserisci l'URL di richiesta e scegli il Metodo Richiesta: POST (il default) o GET.
  5. Facoltativamente imposta un Nome utente risposta e un'Icona di risposta. Vengono utilizzati solo quando il server consente alle integrazioni di sovrascrivere nomi e icone (vedere Nome e icona).
  6. Spunta Completamento automatico per elencare il comando quando le persone digitano /, con un Suggerimento per l'auto-completamento (i suoi argomenti, come [city]) e una Descrizione Autocompletamento.
  7. Scegli Salva e copia il token visualizzato. Il tuo servizio lo usa per verificare che le richieste provengano dal tuo server.

Con l'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"}. Il metodo è P per POST o G per GET. PUT /api/v4/commands/{command_id}/regen_token emette un nuovo token.

La richiesta ricevuta dal servizio

Un comando POST invia un corpo form-encoded (application/x-www-form-urlencoded); un comando GET invia gli stessi campi nella query string. Il token è presente anche nell'intestazione Authorization: Token <token>.

CampoValore
tokenIl token del comando. Verificalo in ogni richiesta.
commandIl trigger con la barra, ad esempio /weather.
textTutto ciò che segue il trigger, ad esempio Paris.
user_id, user_nameChi lo ha eseguito.
channel_id, channel_nameDove è stato eseguito.
team_id, team_domainL'ID e il nome URL della community.
root_idIl thread, se è stato eseguito nella casella di risposta di un thread.
trigger_idPermette alla risposta di aprire un dialogo (vedi Dialoghi). È valido solo per un breve periodo.
response_urlUn URL per pubblicare altre risposte in seguito (vedi Risposte ritardate).
user_mentions, user_mentions_ids, channel_mentions, channel_mentions_idsLe persone e i canali pubblici menzionati nel testo, se presenti. I canali vengono conteggiati indipendentemente dal fatto che siano scritti #channel-name o ~channel-name.
L'URL del sito del server deve essere impostato affinché i comandi personalizzati possano essere eseguiti: Antimatter costruisce response_url a partire da questo.

La risposta

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

{
  "response_type": "in_channel",
  "text": "Paris: 18 °C, light rain",
  "attachments": []
}
CampoSignificato
response_typeephemeral (valore predefinito): solo la persona che ha eseguito il comando vede la risposta, che non viene conservata dopo un ricaricamento. in_channel: la risposta viene pubblicata nel canale.
text, attachmentsIl messaggio, come per i webhook: testo Markdown e allegati, inclusi pulsanti e menu.
username, icon_urlIl nome e l'immagine da mostrare, se sono consentite le sostituzioni. Le impostazioni del comando stesso hanno la precedenza su queste.
channel_idPubblica la risposta in un altro canale, di cui la persona deve essere membro.
goto_locationUn URL da aprire una volta eseguito il comando.
props, typeProprietà aggiuntive e un tipo di post personalizzato, come per i webhook.
extra_responsesAltre risposte, ciascuna con gli stessi campi, pubblicate dopo la prima.
skip_slack_parsingtrue mantiene il testo così com'è, senza convertire link e menzioni in stile Slack.

Una risposta che non è in JSON viene visualizzata come messaggio temporaneo con il corpo come testo. 204 No Content non mostra nulla. Qualsiasi stato diverso da 200–299 mostra un errore alla persona.

Servizio di esempio

Un servizio di comando minimale in Python, utilizzando solo la libreria standard:

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()

Se il servizio viene eseguito su un indirizzo di rete privato, un amministratore di sistema deve autorizzarlo in Consenti connessioni interne non verificate a (ServiceSettings.AllowedUntrustedInternalConnections).

Risposte ritardate

Per le attività che richiedono più tempo del timeout, rispondi immediatamente (ad esempio con un messaggio temporaneo "Ci sto lavorando…"), quindi invia la risposta effettiva tramite POST a response_url. Accetta lo stesso JSON della risposta e funziona fino a 5 volte entro 30 minuti dal comando.

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

Esegui un comando tramite l'API

Gli script e i bot possono eseguire qualsiasi comando, integrato o personalizzato, come se lo avessero digitato:

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 elenca i comandi che gli utenti possono completare automaticamente in una community.

Completamento automatico

I comandi creati nelle pagine di integrazione vengono completati automaticamente con il trigger, l'indicazione e la descrizione. I comandi registrati dalle app possono descrivere in dettaglio i sottocomandi e gli argomenti con AutocompleteData, a partire da model.NewAutocompleteData(trigger, hint, helpText):

  • AddCommand(sub) aggiunge un sottocomando, anch'esso un AutocompleteData.
  • AddTextArgument(helpText, hint, pattern) aggiunge testo libero.
  • AddStaticListArgument(helpText, required, items) offre un elenco fisso di AutocompleteListItem{Item, Hint, HelpText}.
  • AddDynamicListArgument(helpText, url, required) richiede suggerimenti alla tua app mentre gli utenti digitano. L'URL è una route della tua app, ad esempio /plugins/com.example.weather/cities. Riceve l'utente, il canale e la community, e restituisce un elenco JSON di {"Item", "Hint", "HelpText"}.

Le varianti Named… (AddNamedTextArgument e altre) aggiungono flag --name value. Entrambi gli interfacce web mostrano questi suggerimenti.

Mentre qualcuno digita un comando, Fusion mostra il comando e ciascuno dei suoi argomenti come un blocco, con quello in fase di digitazione evidenziato insieme al relativo testo di aiuto. Gli argomenti provengono da AutocompleteData o, in sua assenza, dall'indicazione: in un'indicazione come @[username]... #[channel], le parole che iniziano con @ vanno all'argomento persone e quelle che iniziano con # all'argomento canale, indipendentemente dall'ordine; ... indica che l'argomento si ripete, e l'ultimo argomento riceve il resto del testo.

Canali negli argomenti

Negli argomenti di un comando, @ suggerisce le persone, # suggerisce i canali e li completa come #channel-name, e ~ li completa come ~channel-name. L'interfaccia web e l'app mobile di Antimatter scrivono i link ai canali con #, quindi un comando che accetta un canale dovrebbe accettare entrambe le forme: i comandi integrati /join, /mute e /invite lo fanno, e i loro suggerimenti indicano #[channel].