search
LoginSignup
21

More than 3 years have passed since last update.

posted at

〇〇したらLINE WORKSへ通知する、それIFTTTで

今回のお題

年末に同僚とランチしていた時に、こんな相談を受けました。
image.png

「TwitterでLINE WORKSについて呟かれたら、LINE WORKSへ通知する」を実現してみようと思います。IFTTTを使って!!!!

こんなTweetがあったら、
image.png

こんな感じで、LINE WORKSへ通知したいと思います。
image.png

同様の手順で下記のような要件にも対応可能です!:smiley:

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へ通知することが可能です!!
image.png
image.png

 構成

毎回一緒ですが、、BotサーバーはHeroku上でNode.jsで構築します。
IFTTTからはWebhookを使って、BotサーバーへデータをPOSTします。
image.png

構築の流れ

構築の流れは下記のStepになります。
1、2、4、5は「LINE WORKSで初めてのBot開発!」という記事で詳しく紹介しているので、そちらでご確認ください。
リンクを貼っておきます。

  1. LINE WORKS Developer Consoleの設定
  2. Botサーバーの用意
  3. Botプログラミング
  4. Herokuへデプロイ
  5. Botを公開
  6. 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にて、モジュールをインポートしておきます。

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は推測されにくい複雑なものを設定しましょう

全て設定するとこんな感じになります。

設定したら、プログラムから利用できるよう変数として定義しておきましょう。

index.js
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認証に対応したいと思います。

index.js
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を取得

それぞれ実装のサンプルコードは下記となります。詳細な仕様についてはこちらを参照してください。

index.js
    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の詳細な仕様はこちらを参照してください。
実装サンプルコードは下記となります。

index.js
    //サーバートークンを取得し、メッセージ送信関数を呼び出す
    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に全てのコードを記述しています。必要に応じて、モジュール化を検討してください。

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]をクリックします。
image.png
②[Choose a service]でTwitterを選びます。
image.png
③[Choose trigger]で[New tweet from search]をクリックします。
image.png
④[Complete trigger fields]でSearch for欄に「"#lineworks"」と入力し、[Create trigger]ボタンをクリックします。
image.png
⑤[+that]をクリックします。
image.png
⑥[Choose action service]から「Webhooks」を選びます。
image.png
⑦[Choose action]で[Make a web request]を選びます。
image.png
⑧[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]をクリックします。
image.png

動作確認

Twitterにアクセスし、#lineworksハッシュタグをつけて投稿してみましょう!
LINE WORKSでLINE WORKS通知BotからTwitterに投稿したメッセージを受信できたら完成です!
image.png

 応用編

今回は、IFTTTからBotサーバーへWebhookを投げましたが、IFTTT以外にも、Webhookさえ投げられるシステムであれば、Microsoft Flow、Zapier、Zabbixなどでも応用可能です。

色々な連携を試してみていただけると嬉しいです!
その時は、是非、Twitterで#lineworksハッシュタグをつけて投稿してください!:heart_eyes:

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
21