LCL Engineers' Blog

バス比較なび・格安移動・バスとりっぷを運営する LCLの開発者ブログ

プレミアムフライデーにヨガLINE botを作った話

フロントエンドエンジニアの岡田です。 先週の金曜日は、プレミアムフライデーでしたね。 LCLでも従業員全員が15時に退社しました。 premium-friday.go.jp

私は今回はどこへも出かけられなかったのですが、せっかく時間ができたので、LINE botをつくってみました。 先日こちらでご紹介したとおり、LCLにはヨガ部があるので、 今回はおすすめのヨガ動画を返してくれるbotを作ることにしました。 f:id:lcl-engineer:20170227051900p:plain

機能

現時点のbotの機能は以下のとおりです。

  • ユーザーがキーワードを送る
  • botはそのキーワードを含む動画をYoutubeから検索して返す
  • 動画は特定のチャンネル内から検索して返す。いつもヨガ部で見ている以下のチャンネル内から返すようになっています。 www.youtube.com

環境

Node.js + Heroku + LINE BUSINESS アカウント

以下のチュートリアルにならって作りました。Part3までで環境は整います。 qiita.com 今回はAIは入ってないですが、AI入りのbotもおもしろいです。こちらの記事はとてもわかりやすいのでおすすめです。

Google Developers Console

Youtube APIに使います。以下の記事が参考になりそうです。
YouTube APIとは:Data API v3を使って動画情報を取得してみた。 | D2Cスマイル

実際のコード

環境ができたら、index.jsを以下のように書き換えると完成です。

// -----------------------------------------------------------------------------
// 定数の設定
const LINE_CHANNEL_ACCESS_TOKEN = 'あなたのChannl Access Token';
const GOOGLE_API_KEY = 'あなたのGOOGLE API KEY';
const DOMAIN = 'あなたのサーバーのドメイン: https://xxxxxxxx.herokuapp.com/';

// -----------------------------------------------------------------------------
// モジュールのインポート
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();

// -----------------------------------------------------------------------------
// ミドルウェア設定
app.use(bodyParser.json());

// -----------------------------------------------------------------------------
// Webサーバー設定
var port = (process.env.PORT || 3000);
var server = app.listen(port, function() {
  console.log('Node is running on port ' + port);
});

// -----------------------------------------------------------------------------
// ルーター設定
app.get('/', function(req, res, next) {
  res.send('Node is running on port ' + port);
});

app.post('/webhook', function(req, res, next) {
  res.status(200).end();
  for (var event of req.body.events) {
    if (event.type == 'message') {
      var requestHeaders = {
        'Content-Type': 'application/json',
        'referer': DOMAIN
      }
      //オプションを定義
      var options = {
        url: 'https://www.googleapis.com/youtube/v3/search?key=' + GOOGLE_API_KEY + '&part=snippet&channelId=UCd0pUnH7i5CM-Y8xRe7cZVg&q=' + encodeURI(event.message.text),
        method: 'GET',
        headers: requestHeaders,
        json: true
      }
      console.log(options);

      var youtubeMovieUrl;
      //リクエスト送信
      request(options, function(error, response, responseBody) {
        //コールバックで色々な処理
        youtubeMovieUrl = 'https://www.youtube.com/watch?v=' + responseBody.items[0].id.videoId;
        console.log(youtubeMovieUrl);
        var body = {
          replyToken: event.replyToken,
          messages: [{
            type: 'text',
            text: youtubeMovieUrl
          }]
        }
        var url = 'https://api.line.me/v2/bot/message/reply';
        var headers = {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + LINE_CHANNEL_ACCESS_TOKEN
        }
        request({
          url: url,
          method: 'POST',
          headers: headers,
          body: body,
          json: true
        });
      })
    }
  }
});

2017/03/19 追記 Google Cloud PlatformのAPIキーの制限に「HTTP リファラー(ウェブサイト)」を使えるように、上記ソースコードのrequest時にrefererを追加しました。

youtubeの動画取得については、以下の記事を参考にさせていただきました。 http://xoyip.hatenablog.com/entry/2014/01/24/212903xoyip.hatenablog.com

はまったところ

Youtubeのキーワードをエンコード(encodeURI)しないとうまく結果が表示されません。 以下のような状態だったため解決に時間がかかってしまいました。

  • ブラウザからリクエストした場合はエンコードしなくても正しい結果が返る
  • キーワードによってはそれらしい結果が返ってくる

まとめ

3時間でできるところはこのへんまででしたが、まだまだ改良できるので育てていこうと思います。