2016年10月21日金曜日

ニフティクラウドタイマーから mobile backend のスクリプト機能を定期的に呼び出す

概要

ニフティクラウドタイマー (以下タイマー) を使って定期的に mobile backend (以下 NCMB) のスクリプト機能を呼び出す方法を紹介します
データを集計したり、定期的に通知したりするのに使えると思います

環境

  • Ruby 2.2.4p230 (シグネチャを生成するのに利用)
    • bundler
  • タイマー 2016/10/18 時点
  • NCMB 2016/10/18 時点

NCMB での作業

まずは NCMB 側で作業を行います

事前準備

NCMB のコントロールパネルからアプリを生成をしておいてください
アプリ作成後「アプリケーションキー」と「クライアントキー」を使用します
timer_and_ncmb_getting_keys.png

スクリプトの作成と登録

今回は以下のサンプル (sample.js) を使用します
どんなリクエストが来ても hello と応答するだけの簡単なサンプルです

module.exports = function(req, res) {
  res.send("hello");
}

スクリプトの内容はあとから変更しても同じリクエストが使えるので、必要があれば適宜変更してください
作成できたらコントロールパネルからスクリプトをアップロードしましょう
timer_and_ncmb_upload_script.png

アップロードが完了すればとりあえず OK です
コンパネからテストできるので試しに手動で実行してみても OK です

リクエストの生成

タイマーからコールするためのリクエストを生成しましょう
NCMB では認証に Signature 方式を採用しているため Signature の生成を行う必要があります
さすがに手動だと厳しいのでプログラムから生成したいと思います

  • bundle init
  • vim Gemfile
gem "ruby-hmac", ">= 0.4.0"
  • bundle install
  • vim sig.rb
# encoding: utf-8
require 'time'
require 'hmac'
require 'hmac-sha2'
require 'base64'

def sig(script_name, access_identifier, secret_key)
  # paramters
  ncmb_uri = 'script.mb.api.cloud.nifty.com'
  ncmb_endpoint = "https://#{ncmb_uri}/"
  ncmb_version = "2015-09-01"
  method = "POST"
  path = "/script/#{script_name}"
  timestamp = Time.now.utc.xmlschema.gsub(":", "%3A").gsub("Z", ".456Z")
  common_params = {
    'SignatureMethod' => 'HmacSHA256',
    'SignatureVersion' => '2',
    'X-NCMB-Application-Key' => access_identifier,
    'X-NCMB-Timestamp' => timestamp,
  }
  # creating signature
  canonical_querystring = common_params.sort.collect { |key, value| [key, value].join('=') }.join('&')
  string_to_sign = "#{method}\n#{ncmb_uri}\n/#{ncmb_version}#{path}\n#{canonical_querystring}"
  hmac = HMAC::SHA256.new(secret_key)
  hmac.update(string_to_sign)
  signature = Base64.encode64(hmac.digest.to_s).chomp
  # show result
  cmd="curl -X \"#{method}\" -H \"X-NCMB-Application-Key: #{access_identifier}\" -H \"X-NCMB-Timestamp: #{timestamp}\" -H \"X-NCMB-Signature: #{signature}\" #{ncmb_endpoint}#{ncmb_version}#{path}"
  puts cmd
end

def main
  sig(ARGV[0], ARGV[1], ARGV[2])
end

main

実行方法は引数の 1 つ目がスクリプトの名前で 2 つ目がアプリケーションキー 3 つ目がクライアントキーになります

  • bundle exec ruby sig.rb sample.js access_key client_key

すると curl 用のコマンドを生成してくれます
この curl を実行しても OK ですが、これをタイマーに実行させます
今回のプログラムは NCMB のスクリプト用に作成したものなので、他でも使えるように汎用性はございません

タイマーでの作業

では、生成したリクエスト情報をタイマーに登録しましょう
タイマーの新規作成時の詳細設定でタイプに「HTTP」を選択してください
そしたら、生成した curl の情報を入力していましょう

access_key と timestamp, signature は生成したものを入力してください
以下のようにタイマーのコンパネで入力すれば OK です
timer_and_ncmb_setting_timer.png

タイマーを定期実行させる設定はお好きなように設定すれば OK です
とりあえず手動で実行できるので手動実行で動作確認してみましょう

動作確認

では、動作確認してみましょう
作成したタイマーを選択して「リクエストの実行」を選択します
タイマーの実行履歴を表示して「success」になっていることを確認しましょう
timer_and_ncmb_timer_ret.png

次に NCMB のコンパネに戻りスクリプトのログも確認してみましょう
タイマーから実行したログが確認できると思います
timer_and_ncmb_script_ret.png

ResponseStatus がとりあえず 200 になっていれば成功です

ちょっと残念なのはタイマーでもスクリプトのログでもレスポンスボディの内容 (今回の場合は「hello」)を確認することができません
なので、レスポンスボディの内容の確認は curl を使ってとりあえず確認してください

ちょっと応用

スクリプトの内容を変更して別の処理をできるようにしてみます

スクリプトを変更して IFTTT の Maker API をコールしてみる

スクリプトから Maker の Webhook をコールすることで通知機能を追加してみます
まず、IFTTT 側で Maker チャネルを使ったレシピを作成しておきましょう
今回は Maker + Gmail のレシピを作成しました
timer_and_ncmb_sample_maker.png

レシピを作成したらスクリプトを修正しましょう
以下のようなスクリプトにすることで Maker チャネルが発行した Webhook 用の URL をコールすることができます

  • vim sample.js
module.exports = function(req, res) {
  var request = require('superagent');
  body = {
    "value1": "hello"
  };
  request
    .post('https://maker.ifttt.com/trigger/your_maker_event/with/key/your-maker-token')
    .type('json')
    .send(body)
    .end(function(saerr, sares){
      if (saerr) {
        console.error('error requesting ifttt: ' + saerr.stack);
      }
      res.status(200).json(body);
    });
}

your_maker_event と yoru-maekr-token は各自で払い出された Maker チャネルの情報に書き換えてください
body で value1, value2, value3 を設定すると Maker 側で設定された値を使用することができます
例えば、上記の場合 value1 に設定された「hello」という文字列を送信する Gmail の本文などで使用することができます

これでタイマーを実行してみましょう
問題なく実行できて Gmail が届くと思います
ポイントはタイマー側の設定を何も変更しなくてもスクリプトを実行できるところです
タイマー側はそのままでスクリプトを自由に変更できるので、一度タイマー側を設定すれば好きなスクリプトを実行することができます

また、Webhook のリクエストは superagent を使いました
NCMB スクリプトでは require できるライブラリが決まっているので用途に合わせて利用してください
knex などもあるので、データベースへのアクセスをすることもできると思います

最後に

ニフティクラウドタイマーと NCMB スクリプトを連携してみました
応用では IFTTT と連携してスクリプトから通知できるようにもしてみました

今回の構成は自前のサーバで cron + nodejs を使っても全然できます
が、今回のようにサービスだけを使って実現することもでき、そうすることでサーバの運用をしなくて済むのが嬉しい点かなと思います