今回のお題
**「TwitterでLINE WORKSについて呟かれたら、LINE WORKSへ通知する」を実現してみようと思います。IFTTT**を使って!!!!
同様の手順で下記のような要件にも対応可能です!
Google Calendar(Office365カレンダー)に新しい会議が作成されたら、LINE WORKSへ通知する
TrelloにToDoが追加されたら、LINE WORKSへ通知する
Slackに通知があったら、LINE WORKSへ通知する(おっと?!)
Boxにファイルをアップロードされたら、LINE WORKSへ通知する
etc
ところで、IFTTTって?
IFTTTは、If This Then Thatの略で、Google,Twitter,box,Evernoteなど様々なSaaSをノンコーディングで連携させることができるサービスです。
使い方などは、下記のサイト等で確認してみてください。
さまざまなサービスが連携できる「IFTTT(イフト)」の使い方
IFTTTとは?業務効率化から私生活に便利を提供するサービスの全容
でも、LINE WORKSってIFTTT対応していませんよね?
はい、してません。
してなかったら、自分で作るんです。
IFTTTの「Webhook」を使うことで、LINE WORKSのBotへ通知することが可能です!!
# 構成
毎回一緒ですが、、BotサーバーはHeroku上でNode.jsで構築します。
IFTTTからはWebhookを使って、BotサーバーへデータをPOSTします。
構築の流れ
構築の流れは下記のStepになります。
1、2、4、5は「LINE WORKSで初めてのBot開発!」という記事で詳しく紹介しているので、そちらでご確認ください。
リンクを貼っておきます。
- LINE WORKS Developer Consoleの設定
- Botサーバーの用意
- Botプログラミング
- Herokuへデプロイ
- Botを公開
- IFTTTでアプレット作成
ここからは、「3.Botプログラミング」と「6.IFTTTでアプレット作成」に付いて書きます。
Botプログラミング
モジュールのインストール
下記モジュールを追加でインストールします。
$ npm install express --save
$ npm install body-parser --save
$ npm install jsonwebtoken --save
$ npm install request --save
$ npm install querystring --save
$ npm install basic-auth-connect --save
index.jsにて、モジュールをインポートしておきます。
//モジュールインポート
const express = require("express");
const bodyParser = require("body-parser");
const jwt = require('jsonwebtoken');
const https = require("https");
const request = require("request");
const qs = require("querystring");
const basicAuth = require("basic-auth-connect");//基本認証
環境変数設定
Server TokenやConsumer Keyは、Herokuの環境変数へ設定します。
Herokuの環境変数への設定はHerokuのダッシュボードから設定することができます。手順はこちらを参照してください。
今回は、下記7つの値をHerokuの環境変数として設定しましょう。
環境変数名 | Developer Consoleの表示箇所 |
---|---|
APIID | [API]メニューのAPI IDに表示されている英数字 |
CONSUMERKEY | [API]メニューのServer API Consumer KeyのKey欄に表示されている英数字 |
SERVERID | [API]メニューのServer List(ID登録タイプ)のID欄に表示されている英数字 |
PRIVATEKEY | [API]メニューのServer List(ID登録タイプ)の[認証キー再発行]ボタンからダウンロードします。 ダウンロードしたファイルに表示されている英数字 |
BOTNO | [Bot]メニューに表示されているBotをクリックし、 [Bot No.]に表示されている4桁の数字 |
BASICID | BotサーバーBasic認証のためのID |
BASICPASS | BotサーバーBasic認証のためのPASSWORD PASSWORDは推測されにくい複雑なものを設定しましょう |
全て設定するとこんな感じになります。
設定したら、プログラムから利用できるよう変数として定義しておきましょう。
const APIID = process.env.APIID;
const SERVERID = process.env.SERVERID;
const CONSUMERKEY = process.env.CONSUMERKEY;
const PRIVATEKEY = process.env.PRIVATEKEY;
const BOTNO = process.env.BOTNO;
const BASICID = process.env.BASICID;
const BASICPASS = process.env.BASICPASS;
サーバーをBasic認証対応する
Bot用のWebサーバーのEndpointはパブリックネットワークに公開する必要があります。
そのURLへ悪意を持った第三者から不正なデータが送信されることを防ぐため、最低限の対策としてBasic認証に対応したいと思います。
const express = require("express");
const server = express();
const basicAuth = require("basic-auth-connect");
const BASICID = process.env.BASICID;
const BASICPASS = process.env.BASICPASS;
:
server.use(basicAuth(
BASICID, BASICPASS
))
通知メッセージをユーザーへ送信するためのトークンを取得する
トークンは、下記の流れで取得します。
1.JWTを取得
2.JWTを使ってServer Tokenを取得
それぞれ実装のサンプルコードは下記となります。詳細な仕様についてはこちらを参照してください。
getJWT((jwttoken) => {
getServerToken(jwttoken, (newtoken) => {
//取得したnewtokenを使ってメッセージ送信
});
});
//1. JWTを取得
function getJWT(callback){
const iss = SERVER_ID;
const iat = Math.floor(Date.now() / 1000);
const exp = iat + (60 * 60); //JWTの有効期間は1時間
const cert = PRIVATEKEY;
const token = [];
const jwttoken = jwt.sign({"iss":iss, "iat":iat, "exp":exp}, cert, {algorithm:"RS256"}, (err, jwttoken) => {
if (!err) {
callback(jwttoken);
} else {
console.log(err);
}
});
}
//2.JWTを使ってServer Tokenを取得
function getServerToken(jwttoken, callback) {
const postdata = {
url: 'https://authapi.worksmobile.com/b/' + API_ID + '/server/token',
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8',
},
form: {
"grant_type" : encodeURIComponent("urn:ietf:params:oauth:grant-type:jwt-bearer"),
"assertion" : jwttoken
}
};
request.post(postdata, (error, response, body) => {
if (error) {
console.log(error);
callback(error);
} else {
const jsonobj = JSON.parse(body);
const AccessToken = jsonobj.access_token;
callback(AccessToken);
}
});
}
[注意]
Server Token(access_token)は24時間以内に利用されない場合には自動的に失効します。access_token発行時に、発行時間とaccess_tokenを保存し、Server APIを実行する際には有効期限を確認するようにしてください。有効期限内であれば保存したaccess_tokenを利用することができます。
メッセージを送信する
取得したServerTokenを使って、ユーザーへ通知メッセージを送信します。
メッセージ送信APIの詳細な仕様はこちらを参照してください。
実装サンプルコードは下記となります。
//サーバートークンを取得し、メッセージ送信関数を呼び出す
getJWT((jwttoken) => {
getServerToken(jwttoken, (newtoken) => {
sendMessage(newtoken, accountId, message);
});
});
//メッセージ送信関数
function sendMessage(token, accountId, message) {
const postdata = {
url: 'https://apis.worksmobile.com/' + API_ID + '/message/sendMessage/v2',
headers : {
'Content-Type' : 'application/json;charset=UTF-8',
'consumerKey' : CONSUMERKEY,
'Authorization' : "Bearer " + token
},
json: {
"botNo" : Number(BOTNO),
"accountId" : accountId,
"content" : {
"type" : "text",
"text" : message
}
}
};
request.post(postdata, (error, response, body) => {
if (error) {
console.log(error);
}
console.log(body);
});
}
** [注意]**
Botから1人のユーザーに対しメッセージを送信する場合は、上記のようになります。
トークルームに対しメッセージを送信する場合は、下記のようにaccountIdをnullにして、その代わりにroomIdを送信してください。
サンプルのJSONデータ
{
"botNo" : Number(BOTNO),
"accountId" : null,
"roomId" : roomId,
"content" : {
"type" : "text",
"text" : message
}
##最終的なサンプルコード
完成したindex.jsのサンプルコードは下記のようになります。
注意
今回は、わかりやすいようにindex.jsに全てのコードを記述しています。必要に応じて、モジュール化を検討してください。
"use strict";
// モジュールインポート
const express = require("express");
const server = express();
const bodyParser = require("body-parser");
const jwt = require('jsonwebtoken');
const https = require("https");
const request = require("request");
const qs = require("querystring");
const basicAuth = require("basic-auth-connect");
//変数
const APIID = process.env.APIID;
const SERVERID = process.env.SERVERID;
const CONSUMERKEY = process.env.CONSUMERKEY;
const PRIVATEKEY = process.env.PRIVATEKEY;
const BOTNO = process.env.BOTNO;
const BASICID = process.env.BASICID;
const BASICPASS = process.env.BASICPASS;
//基本認証
server.use(basicAuth(
BASICID, BASICPASS
))
server.use(bodyParser.json());
// Webアプリケーション起動
server.listen(process.env.PORT || 3000);
// サーバー起動確認
server.get('/', (req, res) => {
res.send('Hello World!');
});
// IFTTTからメッセージを受け取る
server.post('/webhook', (req, res) => {
res.sendStatus(200);
const message = req.body.message;
const roomId = req.body.roomId;
const accountId = req.body.accountId;
getJWT((jwttoken) => {
getServerToken(jwttoken, (newtoken) => {
sendMessage(newtoken, accountId, message);
});
});
});
//サーバーAPI用JWT取得
function getJWT(callback){
const iss = SERVERID;
const iat = Math.floor(Date.now() / 1000);
const exp = iat + (60 * 60); //JWTの有効期間は1時間
const cert = PRIVATEKEY;
const token = [];
const jwttoken = jwt.sign({"iss":iss, "iat":iat, "exp":exp}, cert, {algorithm:"RS256"}, (err, jwttoken) => {
if (!err) {
callback(jwttoken);
} else {
console.log(err);
}
});
}
function getServerToken(jwttoken, callback) {
const postdata = {
url: 'https://authapi.worksmobile.com/b/' + APIID + '/server/token',
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8',
},
form: {
"grant_type" : encodeURIComponent("urn:ietf:params:oauth:grant-type:jwt-bearer"),
"assertion" : jwttoken
}
};
request.post(postdata, (error, response, body) => {
if (error) {
console.log(error);
callback(error);
} else {
const jsonobj = JSON.parse(body);
const AccessToken = jsonobj.access_token;
callback(AccessToken);
}
});
}
function sendMessage(token, accountId, message) {
const postdata = {
url: 'https://apis.worksmobile.com/' + APIID + '/message/sendMessage/v2',
headers : {
'Content-Type' : 'application/json;charset=UTF-8',
'consumerKey' : CONSUMERKEY,
'Authorization' : "Bearer " + token
},
json: {
"botNo" : Number(BOTNO),
"accountId" : accountId,
"content" : {
"type" : "text",
"text" : message
}
}
};
request.post(postdata, (error, response, body) => {
if (error) {
console.log(error);
}
console.log(body);
});
}
通知用Botプログラミングはこれで完了です。
続きの手順は、下記となります。
4. Herokuへデプロイ
5. Botを公開
ここまでで、通知Botは完成です!
ここからは通知Botへメッセージを送るIFTTTのアプレットを作成しましょう。
IFTTTでアプレット作成
Twitterで#lineworksハッシュタグの新しい投稿があったら、LINE WORKSへ通知するという動きにします。
①[+this]をクリックします。
②[Choose a service]でTwitterを選びます。
③[Choose trigger]で[New tweet from search]をクリックします。
④[Complete trigger fields]でSearch for欄に「"#lineworks"」と入力し、[Create trigger]ボタンをクリックします。
⑤[+that]をクリックします。
⑥[Choose action service]から「Webhooks」を選びます。
⑦[Choose action]で[Make a web request]を選びます。
⑧[Complete action fields]では下記のように設定します。設定が完了したら、[Create action]をクリックします。
通知先のBotサーバーはBasic認証をかけてますので、URLの前にHerokuの環境変数として設定したIDとPASSWORDを付与します。
項目名 | 設定値 |
---|---|
URL | https://<Basic認証のID>:<Basic認証のPASSWORD>@<herokuアプリケーション名>.herokuapp.com/webhook |
Method | POST |
Content Type | application/json |
Body | {"message":"LINE WORKSに関連するツイートがあったようです。\n {{Text}}\n {{UserName}}\n {{LinkToTweet}}", "accountId":"<通知先のユーザーのLINE WORKS ID>" } |
⑨[Review and finish]で内容を確認し、[Finish]をクリックします。
動作確認
Twitterにアクセスし、#lineworksハッシュタグをつけて投稿してみましょう!
LINE WORKSでLINE WORKS通知BotからTwitterに投稿したメッセージを受信できたら完成です!
# 応用編
今回は、IFTTTからBotサーバーへWebhookを投げましたが、IFTTT以外にも、Webhookさえ投げられるシステムであれば、Microsoft Flow、Zapier、Zabbixなどでも応用可能です。
色々な連携を試してみていただけると嬉しいです!
その時は、是非、Twitterで#lineworksハッシュタグをつけて投稿してください!