Node.js
Twitter
glitch

TwitterのAccount Activity APIとwebhookでDM自動応答Botを作成する

前回まででTwitterのAccount Activity APIおよびwebhookが使用可能になったので、DMに対して自動で返信するBotを作成してみます。あくまでもサンプルということで、ここでは「あいう」などとDMを受信したら「『あいう』は理解できません。」と、ほぼそのまま返信するBotを作成します。前回はwebhook受け取り先としてglitchのWebアプリを登録したので、glitchでのスクリプトの例を示します。

Botのスクリプト

webhookが使用できるようになるまでの手順が大変だったのに比べて、DMの送受信は拍子抜けするほど簡単です。webhookにはイベントに関するさまざまな情報がJSONで付加されてきますので、そこから必要な情報を取り出すだけです。ここでは、さまざまなイベントのうち(詳細は公式ドキュメント参照)、DMのイベント(direct_message_events)のみを処理しています。

なお、client.jsindex.htmlなどのファイルはwebhookの処理とは関係ないので初期状態のまま放置です。package.jsondependencies:に必要なパッケージを記載し(この例ではrequest)、.envにコンシューマーキーなどの秘密情報を定義しておきます。下の例では、OAuth用の4つのキー(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET)と、自分自身のtwitter ID(MYSELF)を定義しています。webhookでDMを受け取るだけなら認証は必要ありません。認証情報はDMの送信用です。

以下、server.jsファイルのサンプルです。

// init project
var express = require('express');
var request = require('request');
const crypto = require('crypto');
var bodyParser = require('body-parser');

var app = express();

// OAuth1.0認証に必要なキーを.envから読み込んで設定
var twitter = {};
twitter.oauth = {
  consumer_key: process.env.CONSUMER_KEY,
  consumer_secret: process.env.CONSUMER_SECRET,
  token: process.env.ACCESS_TOKEN,
  token_secret: process.env.ACCESS_SECRET
}

app.use(express.static('public'));

// webhookの処理には関係ないので、ルートの処理は初期状態のまま放置
app.get("/", function (request, response) {
  response.sendFile(__dirname + '/views/index.html');
});

// TwitterのCRCテストにパスするための処理。作成したHMACをJSONで返す
// CRCテストはGETで行われる
app.get("/webhook", function (request,response) {
  var hmac = crypto.createHmac('sha256', process.env.CONSUMER_SECRET).update(request.query.crc_token).digest('base64');
  response.send('{"response_token":"sha256='+hmac+'"}');
});

// POSTされたデータをパースして使用する
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// Twitterからのwebhookを受け取る
// webhookはPOSTで行われる
app.post("/webhook", function (request, response) {
  response.setHeader('Content-Type', 'text/plain');

  // webhookされたイベントがDMの送受信の場合だけ処理する
  if (request.body.direct_message_events) {
    // DMの送信者のIDを取得
    var sender = request.body.direct_message_events[0].message_create.sender_id;
    // DMのメッセージ本文を取得
    var message_txt = request.body.direct_message_events[0].message_create.message_data.text;

    // 送信者が自分自身でない場合のみ自動返信
    // 自分のユーザーIDは.envで「MYSELF」として定義済
    if (sender !=process.env.MYSELF){
        autoReply(sender, '「'+ message_txt +'」は理解できません。');
      }
  }
  response.sendStatus(200);  
});

// listen for requests :) ← この部分も初期状態のまま
var listener = app.listen(process.env.PORT, function () {
  console.log('Your app is listening on port ' + listener.address().port);
});

// 自動応答
function autoReply(userid, message){
  // まずはDM返信用のオブジェクトを作成
  var message_obj =new Object();
    message_obj = {
      "event": {
        "type": "message_create",
        "message_create": {
          "target": {
            "recipient_id":userid
          },
          "message_data": {
            "text": message
          }
        }
      }
    } 

  // DMをPOSTするための認証情報その他を設定
  var request_options = {
    url: 'https://api.twitter.com/1.1/direct_messages/events/new.json',
    oauth: twitter.oauth,
    json: true,
    headers: {
      'content-type': 'application/json'
    },
    body: message_obj
  }
  // POSTで送信
  request.post(request_options, function (error, response, body) {
  })
}