Help us understand the problem. What is going on with this article?

いらすとやの画像付きのメッセージをSlackに投稿する(Puppeteerでランダムに画像を取得)

More than 1 year has passed since last update.

概要

  1. 定刻になったら、いらすとやの画像付きのメッセージをSlackのチャンネルに投稿する。
  2. トリガーワードがSlackに投稿されたら、いらすとやの画像付きのメッセージで返信する。

なお、画像はランダムで指定されるため、何が出てくるかはお楽しみです:relaxed:

※本記事は、すでにSlack Botを運用されている前提で書いていますので、Node環境の準備やSlackのAPI Tokenの払い出しなどの情報は割愛していますので、ご了承ください:bow:

Slackへの投稿イメージ

1のパターン: 毎時00分でスケジュール指定した場合
スクリーンショット 2018-09-24 22.12.15.png

2のパターン: "いらすとや"というワードに反応した場合
スクリーンショット 2018-09-24 0.35.41.png

必要なノードモジュールは3つ

npm install -S botkit
npm install -S puppeteer
npm install -S node-cron

メインのスクリプト

index.js
const botkit = require('botkit');
const puppeteer = require('puppeteer');
const cron = require('node-cron');

if (!process.env.SLACK_TOKEN) {
  console.log('Error: Specify token in environment');
  process.exit(1);
}

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

const bot = controller.spawn({
  token: process.env.SLACK_TOKEN,
}).startRTM();

// Bot起動時のSlack疎通確認用
controller.hears(['ping'], 'direct_message,direct_mention,mention,ambient', function (bot, message) {
  bot.reply(message, 'PONG');
});

// --------------------------------------------------
//  いらすとや画像をSlackに投稿する
// --------------------------------------------------

function postIrasutoya(channel){

  (async () => {
    const browser = await puppeteer.launch({ headless: true });
    const page = await browser.newPage();
    await page.goto('https://www.irasutoya.com/2016/04/blog-post_890.html');
    await page.click('a[href="#random"]');
    await page.waitForNavigation({ waitUntil: 'domcontentloaded' });

    const image = await page.$('#post .entry img');
    const src = await image.getProperty('src');
    const url = await src.jsonValue();
    const title = await page.$eval('#post h2', item => {
      return item.innerText;
    });

    bot.say({
      channel: channel,
      text: '休憩しようぜ!<' + url + '|' + title + '>',
      as_user: false,
      username : 'いらすとや',
      icon_emoji: ':+1:',
    }, function(err, res) {
      if (err) {
        bot.botkit.log('Failed to postMessage', err);
      }
    });
    await browser.close();
  })();
}

// トリガーワードで実行する
controller.hears(['いらすとや'], 'direct_message,direct_mention,mention,ambient', function(bot, message) {
  postIrasutoya(message.channel);
});

// cronでスケジュール実行する(月曜〜金曜の12時と15時)
cron.schedule('0 0 12,15 * * 1-5', () => {
  postIrasutoya('#general');  // #generalチャンネルに投稿
});

解説1: いらすとやの画像をランダムに取得する

スクリーンショット_2018-09-24_0_16_34.png

  1. いらすとやの画像ページを開き、下部にあるランダムボタンをクリックする。
  2. クリック後に表示されたページの画像のURLとタイトルを取得する。
  3. Slackに画像のタイトルとURLを投稿する。

解説2: トリガーワードで実行する

controller.hearsの第一引数が、トリガーワードになります。
複数指定や正規表現指定も可能です。

controller.hearsの第二引数は、反応するメッセージイベントの種類を指定します。

イベントの種類 説明
direct_message ユーザーからのダイレクトメッセージに反応します。
direct_mention チャンネル内でのダイレクトメンションのメッセージに反応します。
mention チャンネル内でのメンション付きのメッセージに反応します。
ambient チャンネル内でのメンションがないメッセージに反応します。

※@メンションがメッセージの先頭についているのがダイレクトメンションです。(direct_mention)
スクリーンショット 2018-09-24 0.32.42.png

※それ以外のメンション付きメッセージ(mention)
スクリーンショット 2018-09-24 0.33.25.png

※メンションがないメッセージ(ambient)
スクリーンショット 2018-09-24 0.34.33.png

解説3: cronでスケジュール実行する

cron.scheduleの引数で、スケジュールを指定します。
引数の中の左から「秒、分、時、日、月、曜日」で指定することができます。
'0 0 12,15 * * 1-5'の場合は、1-5が月曜〜金曜を意味しており、月曜〜金曜の間の12時0分0秒と15時0分0秒を意味しています。

詳細は、merencia/node-cronのREADME.mdのCron Syntaxをご参照ください。

どうしてこれを作ったか

  • 作業に集中していると、休憩も忘れて没頭しがちなので、休憩を喚起(歓喜)したかった。
  • 最初はSlackの/remindで休憩メッセージを出していたが、テキストだけだと無機質で事務的に感じるようになってしまった。
  • 休憩する、という空気感(和む、安らぐ)を出したかったので画像付きを試みました。
  • 最初はlgtm.inの画像を出そうと思ったが、ランダムに出てくる画像のほとんどに、LGTMさを感じられず、当初の目的の休憩する空気感に沿わないと判断して、いらすとやの画像を採用しました。

※この記事を書いている時に知ったのですが、lgtm.inのサイトは閉じるようですね。(2018年9月23日に確認した時点)
スクリーンショット 2018-09-24 0.46.02.png

参考

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away