Comment créer un plug-in Slack en Java

Haut Java

Je viens d'annoncer le nouveau cours Learn Spring , axé sur les principes de base de Spring 5 et Spring Boot 2:

>> VOIR LE COURS

1. Introduction

Slack est un système de chat populaire utilisé par des personnes et des entreprises du monde entier. L'une des choses qui le rend si populaire est la possibilité d'écrire nos propres plugins personnalisés qui peuvent interagir avec les personnes et les canaux dans un seul espace. Cela utilise leur API HTTP.

Slack ne propose pas de SDK officiel pour écrire des plugins avec Java. Cependant, il existe un SDK communautaire officiellement approuvé que nous allons utiliser. Cela nous donne accès à presque toutes les API Slack à partir d'une base de code Java sans que nous ayons à nous soucier des détails exacts de l'API.

Nous utiliserons cela pour créer un petit robot de surveillance du système. Cela récupérera périodiquement l'espace disque pour l'ordinateur local et alertera les gens si des lecteurs sont trop pleins.

2. Obtention des informations d'identification d'API

Avant de pouvoir faire quoi que ce soit avec Slack, nous devons créer une nouvelle application et un bot et les connecter à nos canaux .

Tout d'abord, visitons //api.slack.com/apps. C'est la base à partir de laquelle nous gérons nos applications Slack. De là, nous pouvons créer une nouvelle application.

Lorsque nous faisons cela, nous devons entrer un nom pour l'application et un espace de travail Slack pour la créer.

Une fois que nous avons fait cela, l'application a été créée et est prête à être utilisée. L'écran suivant nous permet de créer un Bot. Il s'agit d'un faux utilisateur pour lequel le plugin agira.

Comme pour tout utilisateur normal, nous devons lui donner un nom d'affichage et un nom d'utilisateur. Ce sont les paramètres que les autres utilisateurs de l'espace de travail Slack verront pour cet utilisateur de bot s'ils interagissent avec lui.

Maintenant que nous avons fait cela, nous pouvons sélectionner «Installer l'application» dans le menu latéral et ajouter l'application dans notre espace de travail Slack . Une fois que nous avons fait cela, l'application peut interagir avec notre espace de travail.

Cela nous donnera ensuite les jetons dont nous avons besoin pour que notre plugin communique avec Slack.

Chaque bot interagissant avec un espace de travail Slack différent aura un ensemble différent de jetons. Notre application a besoin de la valeur «Bot User OAuth Access Token» lorsque nous l'exécutons.

Enfin, nous devons inviter le bot sur tous les canaux dans lesquels il devrait être impliqué . Cela fonctionne simplement en envoyant un message à partir du canal - @system_monitoring dans ce cas.

3. Ajout de Slack à notre projet

Avant de pouvoir l'utiliser, nous devons d'abord ajouter les dépendances du SDK Slack à notre fichier pom.xml :

 com.hubspot.slack slack-base ${slack.version}   com.hubspot.slack slack-java-client ${slack.version} 

3. Structure de l'application

Le cœur de notre application est la capacité de vérifier les erreurs dans le système. Nous allons représenter cela avec le concept d'un vérificateur d'erreurs. Il s'agit d'une interface simple avec une seule méthode, déclenchée pour vérifier les erreurs et les signaler:

public interface ErrorChecker { void check(); }

Nous souhaitons également avoir les moyens de signaler les erreurs constatées. Ceci est une autre interface simple qui prendra une déclaration de problème et la signalera de manière appropriée:

public interface ErrorReporter { void reportProblem(String problem); }

The use of an interface here allows us to have different ways of reporting problems. For example, we might have one that sends emails, contacts an error reporting system, or sends messages to our Slack system for people to get an immediate notification.

The design behind this is that each ErrorChecker instance is given its own ErrorReporter to use. This gives us the flexibility to have different error reporters for different checkers to use because some errors might be more important than others. For example, if the disks are over 90% full that may require a message to a Slack channel, but if they are over 98% full then we might instead want to send private messages to specific people instead.

4. Checking Disk Space

Our error checker will check the amount of disk space on the local system. Any file system that has less than a particular percentage free is considered to be an error and will be reported as such.

We'll make use of the NIO2 FileStore API introduced in Java 7 to obtain this information in a cross-platform manner.

Now, let's take a look at our error checker:

public class DiskSpaceErrorChecker implements ErrorChecker { private static final Logger LOG = LoggerFactory.getLogger(DiskSpaceErrorChecker.class); private ErrorReporter errorReporter; private double limit; public DiskSpaceErrorChecker(ErrorReporter errorReporter, double limit) { this.errorReporter = errorReporter; this.limit = limit; } @Override public void check() { FileSystems.getDefault().getFileStores().forEach(fileStore -> { try { long totalSpace = fileStore.getTotalSpace(); long usableSpace = fileStore.getUsableSpace(); double usablePercentage = ((double) usableSpace) / totalSpace; if (totalSpace > 0 && usablePercentage < limit) { String error = String.format("File store %s only has %d%% usable disk space", fileStore.name(), (int)(usablePercentage * 100)); errorReporter.reportProblem(error); } } catch (IOException e) { LOG.error("Error getting disk space for file store {}", fileStore, e); } }); } }

Here, we're obtaining the list of all file stores on the local system and then checking each one individually. Any that has less than our defined limit as usable space will generate an error using our error reporter.

5. Sending Errors to Slack Channels

We now need to be able to report our errors. Our first reporter will be one that sends messages to a Slack channel. This allows anyone in the channel to see the message, in the hope that somebody will react to it.

This uses a SlackClient, from the Slack SDK, and the name of the channel to send the messages to. It also implements our ErrorReporter interface so that we can easily plug it into whichever error checker wants to use it:

public class SlackChannelErrorReporter implements ErrorReporter { private SlackClient slackClient; private String channel; public SlackChannelErrorReporter(SlackClient slackClient, String channel) { this.slackClient = slackClient; this.channel = channel; } @Override public void reportProblem(String problem) { slackClient.postMessage( ChatPostMessageParams.builder() .setText(problem) .setChannelId(channel) .build() ).join().unwrapOrElseThrow(); } }

6. Application Wiring

We are now in a position to wire up the application and have it monitor our system. For the sake of this tutorial, we're going to use the Java Timer and TimerTask that are part of the core JVM, but we could just as easily use Spring or any other framework to build this.

For now, this will have a single DiskSpaceErrorChecker that reports any disks that are under 10% usable to our “general” channel, and which runs every 5 minutes:

public class MainClass { public static final long MINUTES = 1000 * 60; public static void main(String[] args) throws IOException { SlackClientRuntimeConfig runtimeConfig = SlackClientRuntimeConfig.builder() .setTokenSupplier(() -> "") .build(); SlackClient slackClient = SlackClientFactory.defaultFactory().build(runtimeConfig); ErrorReporter slackChannelErrorReporter = new SlackChannelErrorReporter(slackClient, "general"); ErrorChecker diskSpaceErrorChecker10pct = new DiskSpaceErrorChecker(slackChannelErrorReporter, 0.1); Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { diskSpaceErrorChecker10pct.check(); } }, 0, 5 * MINUTES); } }

We need to replace “” with the token that was obtained earlier, and then we're ready to run. As soon as we do, if everything is correct, our plugin will check the local drives and message the Slack if there are any errors.

7. Sending Errors as Private Messages

Next, we're going to add an error reporter that sends private messages instead. This can be useful for more urgent errors since it will immediately ping a specific user instead of relying on someone in the channel to react.

Our error reporter here is more complicated because it needs to interact with a single, targeted user:

public class SlackUserErrorReporter implements ErrorReporter { private SlackClient slackClient; private String user; public SlackUserErrorReporter(SlackClient slackClient, String user) { this.slackClient = slackClient; this.user = user; } @Override public void reportProblem(String problem) { UsersInfoResponse usersInfoResponse = slackClient .lookupUserByEmail(UserEmailParams.builder() .setEmail(user) .build() ).join().unwrapOrElseThrow(); ImOpenResponse imOpenResponse = slackClient.openIm(ImOpenParams.builder() .setUserId(usersInfoResponse.getUser().getId()) .build() ).join().unwrapOrElseThrow(); imOpenResponse.getChannel().ifPresent(channel -> { slackClient.postMessage( ChatPostMessageParams.builder() .setText(problem) .setChannelId(channel.getId()) .build() ).join().unwrapOrElseThrow(); }); } }

What we have to do here is to find the user that we are messaging — looked up by email address, since this is the one thing that can't be changed. Next, we open an IM channel to the user, and then we post our error message to that channel.

This can then be wired up in the main method, and we will alert a single user directly:

ErrorReporter slackUserErrorReporter = new SlackUserErrorReporter(slackClient, "[email protected]"); ErrorChecker diskSpaceErrorChecker2pct = new DiskSpaceErrorChecker(slackUserErrorReporter, 0.02); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { diskSpaceErrorChecker2pct.check(); } }, 0, 5 * MINUTES);

Once done, we can run this up and get private messages for errors as well.

8. Conclusion

Nous avons vu ici comment nous pouvons incorporer Slack dans nos outils afin que nous puissions envoyer des commentaires à toute l'équipe ou à des membres individuels. Nous pouvons faire beaucoup plus avec l'API Slack, alors pourquoi ne pas voir ce que nous pouvons incorporer d'autre.

Comme d'habitude, le code source de cet article se trouve à l'adresse over sur GitHub.

Fond Java

Je viens d'annoncer le nouveau cours Learn Spring , axé sur les principes de base de Spring 5 et Spring Boot 2:

>> VOIR LE COURS