Créer une API pour une slash command sur Slack

Auteur du billet de blog : Nicolas Hilaire - Neotech Solutions

Nicolas Hilaire

Consultant .NET
  Publié le vendredi 9 septembre 2016

Artisan logiciel particulièrement intéressé par les technologies .NET. Polyvalent et curieux, je suis néanmoins à l'écoute des autres technologies du marché. MVP (Microsoft Most Valuable Professional) de 2007 à 2014, je suis également auteur d'un ouvrage pour apprendre le C#, à destination des débutants et de plusieurs MOOCs sur le C#, Windows Phone ou ASP.NET MVC...

Nous avons vu dans un précédent billet comment utiliser le bot framework de Microsoft pour créer un bot que nous avons déployé sur Slack. Malheureusement, ce bot ne fonctionne pas avec les commandes slash de Slack qui sont très pratiques pour effectuer une intégration. Nous allons voir dans ce billet comment y remédier.

Et en fait, c’est très simple. Une commande slash, c’est simplement l’appel à une API en ligne avec un certain formalisme ; et vu que nous avons déjà une API Web disponible sur Azure grâce au précédent billet, nous allons l’améliorer pour créer une commande slash qui aura pour but d’appeler un générateur de meme aléatoire. Oui, car depuis le précédent billet, j’ai rajouté plusieurs meme dans mon précédent bot. Mais finalement, peu importe ce que fait le code qu’il y a derrière, ce qui est important c’est la mécanique générale utilisée ici pour répondre à la commande slash.

Commençons par aller sur l’url qui permet de définir les intégrations, https://votre-team.slack.com/apps/manage/custom-integrations, puis ajoutez une slash commands :

 

Cliquez sur Add Configuration :

 

Il faut maintenant choisir le nom d’une commande, commençant par / :

 

 

J’utilise ici /random pour démarrer ma commande. Et puis à partir de maintenant, c’est très simple. Il vous explique tout ce qu’il faut faire. Il faut mettre l’url de notre route, disons que nous allons créer une route qui sera /api/memecommand :

 

 

Ensuite vous avez le choix entre utiliser cette API en GET ou en POST. Là, franchement, c’est vous qui choisissez, c’est aussi simple l’un que l’autre. Disons que je pars sur du GET.

Autre élément important en dessous, il s’agit du token de vérification. Notez-le, vous en aurez besoin lors de la création de votre API afin d’être sûr que c’est bien slack qui vous appelle. Cela permettra de filtrer les indiscrets qui tomberaient sur votre route par hasard…

Ce qu’on peut voir également dans la doc, c’est que slack va nous envoyer une requête avec ces paramètres :

 

 

Ceux qui nous intéressent pour l’instant sont :

  • token (pour la vérification)
  • text (pour connaitre le texte après la commande)
  • response_url (pour renvoyer notre réponse)
  • command (pour connaitre le nom de la commande, même si on la connait déjà)

Il y a ensuite plusieurs solutions pour traiter la réponse car nous pouvons lire qu’il faut être soit en mesure de répondre en moins de 3 secondes, soit utiliser la response_url pour renvoyer ultérieurement notre réponse si on dépasse 3 secondes de traitement. Comme ici nous sommes dépendant d’une tierce API dont je ne connais pas le SLA, je vais partir directement sur la solution moins risquée où nous renverrons notre réponse à slack par l’intermédiaire de la response_url.

Voici le code de l’API :

Du coup, ici rien de sorcier. Si le token n’est pas bon, je renvois une erreur 400 et sinon je démarre ma tâche en arrière-plan et je renvoi tout de suite une réponse 200 pour dire que j’ai pris en compte la demande. Tout le boulot est à faire dans la méthode en arrière-plan :

Je vous passe les détails du code métier. Et je dois renvoyer ma réponse à la response_url avec du JSON qui a cette tête :

Donc, pour créer ce JSON, le plus simple est de créer un petit objet qui a la bonne tête que nous sérialiserons en JSON :

Et comme on le voit dans le code, j’ai choisi de préfixer l’url de l’image par le nom de la commande, histoire de rappeler la commande utilisée pour générer le meme. Et voilà, c’est tout. Il n’y a plus qu’à déployer sur azure et à tester :