LoginSignup
1
0

More than 5 years have passed since last update.

はじめてnodejsを使った。はじめてチャットリレーbotを作った話。

Last updated at Posted at 2017-12-03

これは何

nodejsを使ってslack botを作った話。
インフラエンジニアだけどコードもかけるようになりたい、といって少しだけ時間をもらってbotを作る仕事をやった。
その時のメモ的なもの。

何を使う

botkitというツールキットを使う。
hubotと何が違うの? そういうのを調べたりはしてません。お手軽にモダンな感じで作れるよ、とおすすめされたので使った見た感じ。

コード

コードは長くないのでここに貼ってしまう。

npm install --save botkit とかして、package.json作らせた(と思う)。

channel id はチャンネルがprivateの場合はhttps://api.slack.com/methods/groups.list/test で確認する。publicの場合は /channels.list/test で確認する。slackの場合。facebook messanger とかだとまた別の取得方法だと思う。

token はbot のものを使用する。https://app.slack.com/apps/new/bot から作成したもの。custom botについてはこちらを参照のこと:https://api.slack.com/bot-users。

const Botkit = require('botkit');
const os = require('os');

// 色々変数チェック。他dest,originについてはここの説明では略
if (!process.env.token) {
  console.warn('Error: Specify token in environment');
  process.exit(1);
}

const controller = Botkit.slackbot({
  debug: true,
});

controller.spawn({
  token: process.env.token,
}).startRTM();

const destChannel = process.env.destChannel;
const originChannel = process.env.originChannel;

controller.hears('.*https?://www.example.com[sS]*', 'ambient', (bot, message) => {  // [sS]* は改行含む全一致。.*だと改行入らない。ambient はbotが全発言を拾うということ(direct_messageとかもある)。 
  // 指定のチャンネルのときのみ発言を拾う
  if (message.channel === originChannel) {
    const matchMessage = message.text;
    const userId = message.user;
    bot.api.users.info({ user: userId }, (userApiError, userApiRes) => {
      const userName = userApiRes.user.profile.real_name;
      bot.api.channels.info({ channel: message.channel }, (channelApiError, channelApiRes) => {
        // private channel はchannels apiからは情報取得できない。groups apiなら取れるが、privateチャンネル名は知られなくても良い
        const channelName = (channelApiError !== 'channel_not_found') ? channelApiRes.channel.name : 'どこかprivate channel';
        bot.say(
          {
            text: `${userName}さんが作品リンクを投稿しました(in #${channelName}) \n -------------------------- \n ${matchMessage} \n --------------------------`,
            channel: destChannel,
          });
      });
    });
  }
});

起動は

originChannel='<channel_id1>' destChannel='<channel_id2>' token=<bot_token> node urlcopy_bot.js

その他

eslint 使ってみた。
明らかな表記ブレは適当に直してくれるし、コードはきれいになるし、紛らわしい表記とか教えてくれるし、割と良かった。
他のところにもlint入れてみようかなと思った。

追記

slack接続が切れてしまって(close RTMになる) botが死んだように見える現象があった。
最初は自分で close_rtmイベントをフックしてconnectするように書いていたが、botkitはデフォルトで予期せぬ接続断があったらreconnectするようになっているため、両方で接続しに行ってしまい、多重接続(このbotの場合は2回投稿してしまう動き)。参考:https://github.com/howdyai/botkit/blob/bee9c5c70dcf3c024e71f2a10bdb2e425c421988/lib/Slackbot_worker.js#L230-L233

また、その他のエラーでcloseRTMしたときにはretryEnabledがtrueならreconnectしてくれるっぽい。こちらの動作に任せることにした。参考: https://github.com/howdyai/botkit/blob/bee9c5c70dcf3c024e71f2a10bdb2e425c421988/lib/Slackbot_worker.js#L70-L86

そこで、ドキュメントの通り、

const controller = Botkit.slackbot({ retry: Infinity });

みたいにしたらちゃんと接続が切れてもreconnectしてくれるようになった。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0