Перейти к основному содержимому

Как создать плагин Slack на Java

· 7 мин. чтения

1. Введение

Slack — это популярная система чата, которой пользуются люди и компании по всему миру. Одна из вещей, которая делает его таким популярным, — это возможность писать собственные настраиваемые плагины, которые могут взаимодействовать с людьми и каналами в рамках одного Slack. Это использует их HTTP API.

Slack не предлагает официального SDK для написания плагинов с Java. Однако есть официально одобренный сообществом SDK , который мы собираемся использовать. Это дает нам доступ почти ко всему Slack API из кодовой базы Java без необходимости вникать в точные детали API.

Мы воспользуемся этим для создания небольшого бота для мониторинга системы. Это будет периодически извлекать дисковое пространство для локального компьютера и предупреждать людей, если какие-либо диски переполняются.

2. Получение учетных данных API

Прежде чем мы сможем что-то сделать со Slack, нам нужно создать новое приложение и бота и подключить его к нашим каналам .

Во-первых, давайте посетим https://api.slack.com/apps . Это база, откуда мы управляем нашими приложениями Slack. Отсюда мы можем создать новое приложение.

./d65f4813f7a86cfef4048a53267162e2.png

Когда мы это делаем, нам нужно ввести имя для приложения и рабочее пространство Slack, в котором оно будет создано.

./89612edc8b8496c355a38333cf8ba0eb.png

Как только мы это сделали, приложение было создано и готово для работы. Следующий экран позволяет нам создать бота. Это поддельный пользователь, от имени которого будет действовать плагин.

./387a1b459e3dca46f132e299021eaff2.png

Как и любому обычному пользователю, нам нужно дать ему отображаемое имя и имя пользователя. Это настройки, которые другие пользователи в рабочей области Slack увидят для этого пользователя-бота, если они когда-либо взаимодействуют с ним.

./7b56e5fd078f1a5f899c7b7a20c4c56e.png

Теперь, когда мы это сделали, мы можем выбрать «Установить приложение» в боковом меню и добавить приложение в наше рабочее пространство Slack . Как только мы это сделали, приложение может взаимодействовать с нашим рабочим пространством.

./e007398fc788c2d563f3dba0562599b1.png

Это даст нам токены, которые нужны нашему плагину для связи со Slack.

./ca89619eaeab9949a9ae4323e37b3e65.png

У каждого бота, взаимодействующего с другим рабочим пространством Slack, будет свой набор токенов. Нашему приложению требуется значение «Токен доступа OAuth пользователя бота» при его запуске.

Наконец, нам нужно пригласить бота на все каналы, в которых он должен участвовать . Это работает, просто отправив сообщение с канала — в данном случае @system_monitoring .

3. Добавление Slack в наш проект

Прежде чем мы сможем его использовать, нам сначала нужно добавить зависимости Slack SDK в наш файл pom.xml :

<dependency>
<groupId>com.hubspot.slack</groupId>
<artifactId>slack-base</artifactId>
<version>${slack.version}</version>
</dependency>
<dependency>
<groupId>com.hubspot.slack</groupId>
<artifactId>slack-java-client</artifactId>
<version>${slack.version}</version>
</dependency>

3. Структура приложения

Ядром нашего приложения является возможность проверки на наличие ошибок в системе. Мы представим это с помощью концепции средства проверки ошибок. Это простой интерфейс с одним методом, запускаемым для проверки ошибок и сообщения о них:

public interface ErrorChecker {
void check();
}

Мы также хотим иметь возможность сообщать обо всех обнаруженных ошибках. Это еще один простой интерфейс, который возьмет описание проблемы и сообщит о нем соответствующим образом:

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

Использование интерфейса здесь позволяет нам иметь различные способы сообщения о проблемах. Например, у нас может быть тот, который отправляет электронные письма, связывается с системой отчетов об ошибках или отправляет сообщения в нашу систему Slack, чтобы люди получали немедленное уведомление.

Смысл этого в том, что каждому экземпляру ErrorChecker предоставляется свой собственный ErrorReporter для использования. Это дает нам возможность использовать разные отчеты об ошибках для разных средств проверки, потому что некоторые ошибки могут быть более важными, чем другие. Например, если диски заполнены более чем на 90%, может потребоваться сообщение в канал Slack, но если они заполнены более чем на 98%, вместо этого мы можем захотеть отправлять личные сообщения определенным людям.

4. Проверка места на диске

Наша программа проверки ошибок проверит объем дискового пространства в локальной системе. Любая файловая система, которая имеет меньше определенного процента свободного места, считается ошибкой и будет сообщено как таковая.

Мы будем использовать API-интерфейс NIO2 FileStore , представленный в Java 7, для получения этой информации кросс-платформенным способом.

Теперь давайте посмотрим на нашу программу проверки ошибок:

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);
}
});
}
}

Здесь мы получаем список всех хранилищ файлов в локальной системе, а затем проверяем каждое из них по отдельности. Любой, который имеет меньше установленного нами предела в качестве полезного пространства, сгенерирует ошибку, используя наш отчет об ошибках.

5. Отправка ошибок в Slack-каналы

Теперь нам нужно иметь возможность сообщать о наших ошибках. Нашим первым репортером будет тот, который отправляет сообщения в канал Slack. Это позволяет любому пользователю канала увидеть сообщение в надежде, что кто-то на него отреагирует.

При этом используется SlackClient из Slack SDK и имя канала для отправки сообщений. Он также реализует наш интерфейс ErrorReporter , поэтому мы можем легко подключить его к любому средству проверки ошибок, которое захочет его использовать:

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. Подключение приложений

Теперь мы можем подключить приложение и заставить его контролировать нашу систему. Для этого руководства мы собираемся использовать Java Timer и TimerTask , которые являются частью основной JVM, но мы могли бы так же легко использовать Spring или любую другую среду для создания этого.

На данный момент у него будет один DiskSpaceErrorChecker , который сообщает о любых дисках, которые используются менее чем на 10%, в наш «общий» канал и который запускается каждые 5 минут:

public class MainClass {
public static final long MINUTES = 1000 * 60;

public static void main(String[] args) throws IOException {
SlackClientRuntimeConfig runtimeConfig = SlackClientRuntimeConfig.builder()
.setTokenSupplier(() -> "<Your API Token>")
.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);
}
}

Нам нужно заменить «<Your API Token>» на токен, который был получен ранее, и тогда мы готовы к запуску. Как только мы это сделаем, если все правильно, наш плагин проверит локальные диски и сообщит Slack, если есть какие-либо ошибки.

./3d0b2d4257f6aff6e1c95d35a34f0c86.png

7. Отправка ошибок в виде личных сообщений

Далее мы добавим отчет об ошибках, который вместо этого отправляет личные сообщения. Это может быть полезно для более срочных ошибок, так как он немедленно пропингует конкретного пользователя, вместо того, чтобы полагаться на то, что кто-то в канале отреагирует .

Наш отчет об ошибках здесь более сложен, потому что ему нужно взаимодействовать с одним целевым пользователем:

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

Что нам нужно сделать здесь, так это найти пользователя, которому мы обмениваемся сообщениями — искать по адресу электронной почты, поскольку это единственная вещь, которую нельзя изменить. Затем мы открываем канал обмена мгновенными сообщениями для пользователя, а затем отправляем сообщение об ошибке на этот канал .

Затем это можно подключить к основному методу, и мы будем оповещать одного пользователя напрямую:

ErrorReporter slackUserErrorReporter = new SlackUserErrorReporter(slackClient, "testuser@foreach.com");

ErrorChecker diskSpaceErrorChecker2pct = new DiskSpaceErrorChecker(slackUserErrorReporter, 0.02);

timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
diskSpaceErrorChecker2pct.check();
}
}, 0, 5 * MINUTES);

После этого мы можем запустить это и также получать личные сообщения об ошибках.

./669de418b8f20f9b00e8cc6c9c8c87fa.png

8. Заключение

Здесь мы увидели, как мы можем включить Slack в наши инструменты, чтобы мы могли отправлять отзывы либо всей команде, либо отдельным членам. С помощью Slack API мы можем сделать гораздо больше, так почему бы не посмотреть, что еще мы можем добавить.

Как обычно, исходный код этой статьи можно найти на GitHub .