SlackBotをGUIでポチポチしていい感じにするツールを作ってる

  • JavaScript
  • Nuxt.js
  • フロントエンド
  • ツール
  • Vue.js

年末年始の休みぐらいから、SlackBotをGUIでポチポチするだけでいい感じに作れるようなツールを作ってる。

画面でポチポチ作ると

こんな感じで動く

とりあえずある程度動くようになったのでリポジトリ公開しといた

https://github.com/mugi-uno/botpot

動機

SlackBotについて考えてみたときに、以下のようなことだけ簡単に実現できて自由に組み合わせることが出来れば、全部じゃなくとも80%くらいのやりたいことは実現できるんじゃね?とある日思った。

何らかのキーワードで実行(@bot 次の予定 みたいな)

トリガーで処理すること

最後にやること

すでにBotを構築するツールはいっぱいあると思うけど、GUIでポチポチやって簡単に作れたら楽だな〜というのと、なんでもいいのでNuxt.jsを使ってなんか作りたかった、というのがあって、作ってみることにした。

使ったもの

でだいたい動いてる。

深い意味や理由はまったくないが、全部jsで書いてみようと思ったのでexpressとかを使ってる。

概念的な話

以下のような名前をつけて取り扱ってる

ActionやFinisherは1つまえに実行されたものから何らかのパラメータを受け取って自由に扱う。

たとえば上に貼った画像の例ではToyama.rbのイベント情報をチャンネルに返してるが、これはActionで行ったaxiosのレスポンスが次のFinisherに渡されてるので可能になってる。

(ちなみにFinisherではlodash#template形式で雑にテンプレートを書けるようにしてみた)

Slackへの依存をいかに切り出すか

Slack以外のツールにも対応させたいな〜みたいな思いがあったので、Slackに依存する部分とのやりとりはすべて events 経由で間接的に行ってる。

具体的には、Botの動作全体を管理するクラスでは


module.exports = class Bot {
  constructor (client) {
    this.client = client;
  }

  start (configuration) {
    this.client.start(configuration);
  }

  stop () {
    this.client.stop();
  }

  bindMessageTriggerFlow (flow) {
    this.client.on('messageReceived', (data) => {
      if (!data.actionName || data.actionName !== flow.trigger.data.word) return;

      this.executeAllActions(flow, data);
    });
  }

  ...

みたいにして、client がSlackかどうかは関係なく、特定のinterfaceを持ってるかどうかだけ気にするようにしてみた。

client自体は

const EventEmitter = require('events').EventEmitter;

module.exports = class BaseClient extends EventEmitter {
  start (state) {
    throw new Error('not implements error');
  }

  stop () {
    throw new Error('not implements error');
  }

  emitMessageReceived (message = {}) {
    this.emit('messageReceived', message);
  }

  sendMessage () {
    throw new Error('not implements error');
  }
};

みたいなBaseクラスを継承させていて、Chatサービスに依存する実装はサブクラスに丸投げしてる。

定期実行の方法

cron形式で定期実行できるようにしたかったんだけど、その実現に node-schedule を利用させてもらった。

https://github.com/node-schedule/node-schedule

さくっと動いて便利だった。

気をつけないといけなかったのが、当たり前だけど、Botを止めてもScheduleは止まらない。そのあたりの実装忘れてて、テスト用チャンネルが地獄みたいなことになってた。

これから作ろうと思ってるもの

冷静に考えると最後のActionをFinisherにすればそれでいいので、Finisherなんていらんかったんや、ってこのエントリ書いてて気づいた。

ランダムなURLを発行して、それをTriggerにする 認証

他のChatツールに対応したい

まだ途中だけど、作ってる感想としてはNuxt.jsがとても楽でいい感じ。 router書かなくて良いのは最高です。