SlackとLINEを連携する(3) Slack→LINE
前回はLINEからSlackへ通知できるようにしたので、今回はSlackからLINEへ通知できるようにします。
新しくGoogle Apps Script(以下GAS)ファイルを作成してプログラムを作っていきます。
長いので要点だけ解説します。
ソースコード
/** * @fileoverview Slackのgeneralチャンネルに通知されたメッセージをLINEボットに転送する。 * @author smp */ // LINEトークン var LINE_TOKEN = "(秘密)"; // LINEチャンネルアクセストークン var LINE_ACCESS_TOKEN = "(秘密)"; // LINEメッセージプッシュ用APIのURL var LINE_MESSAGE_PUSH_URL = "https://api.line.me/v2/bot/message/push"; // SLACKトークン var SLACK_TOKEN = '(秘密)'; // GoogleドライブディレクトリID var GOOGLE_DRIVE_DIR_ID = '(秘密)' // LINEユーザ一覧ファイル名 var LINE_USER_LIST_FILENAME = 'LineUserList.json'; /** * @summary Postリクエスト処理。 * Slack Outgoing WebhookからPOSTで通知された場合に実行する関数。 * イベントに含まれるチャンネル名、ユーザ名、本文をLINEに通知する。 * @param e Slackから通知されるメッセージ */ function doPost(e) { // 1.各種情報を取得 // (1)チャンネル名 var chName = e.parameter.channel_name; // (2)ユーザ名 var userName = e.parameter.user_name; // (3)本文 var text = e.parameter.text; // (4)Slackトークン var slackToken = e.parameter.token; // 2.メッセージの組み立て var msg = 'Slack投稿通知\n' + 'チャンネル : ' + chName + '\n' + '発言者 : ' + userName + '\n' + '内容 : ' + text; // 3.送信 switch (slackToken) { case SLACK_TOKEN: pushToLine(msg); break; default: // do nothing } } /** * @name LINEへメッセージ送信 * @summary LINEユーザ一覧ファイルにある宛先へメッセージを送信する。 * @param {string} text 本文 */ function pushToLine(text) { // LINEユーザ一覧を読み込む。 var lineUserList = getLineUserIdList(); // 全LINEユーザに対して繰り返し処理を実行する。 for (i in lineUserList) { var lineUserId = lineUserList[i]; try { pushToLineOneUser(text, lineUserId); } catch (err) { console.log(err); } } } /** * @name LINEへメッセージ送信(1ユーザ) * @summary 指定したメッセージを、指定したLINEユーザID宛に送信する。 * @param {string} text 本文 * @param {string} lineUserId LINEユーザID */ function pushToLineOneUser(text, lineUserId) { // ヘッダデータ作成。 var headers = { 'Content-Type': 'application/json; charset=UTF-8', 'Authorization': 'Bearer ' + LINE_ACCESS_TOKEN, }; // POSTリクエストデータ作成。 var postData = { 'to': lineUserId, 'messages': [ { 'type': 'text', 'text': text, } ] }; // 送信データを作成。 var options = { 'method': 'post', 'headers': headers, 'payload': JSON.stringify(postData) }; var response = UrlFetchApp.fetch(LINE_MESSAGE_PUSH_URL, options); return response; } /** * @name LINEユーザID一覧取得 * @summary LINEユーザ一覧ファイルからLINEユーザIDの一覧を取得する。 * @returns LINEユーザリスト */ function getLineUserIdList() { var jsonData = readJson(LINE_USER_LIST_FILENAME); var userIdList = []; // ユーザ一覧作成 if (jsonData.list) { for (var i in jsonData.list) { userIdList.push(jsonData.list[i].userId); } } return userIdList; } /** * @name Google Drive内ファイル取得 * @summary Google Driveのディレクトリパスとファイル名から、ファイルを取得する。 * 存在しない場合は新しく作成する。 * @param {string} dirId ディレクトリID * @param {string} fileName ファイル名 * @returns ファイルオブジェクト */ function getGoogleDriveFile(dirId, fileName) { var dir = DriveApp.getFolderById(dirId); var file = dir.getFilesByName(fileName); if (file.hasNext()) { // 存在する場合 return file.next(); } else { // 存在しない場合 return dir.createFile(fileName, ''); } } /** * @name jsonファイル読み込み * @summary jsonファイルをGoogle Driveから読み込む。 * jsonファイルを読み込み、パースして返す。 * jsonファイルがない場合、新しくjsonファイルを作成する。 * @param {string} jsonPath Google Drive内jsonファイルパス * @returns {object} 読み込んだjsonデータ */ function readJson(jsonPath) { var file = getGoogleDriveFile(GOOGLE_DRIVE_DIR_ID, jsonPath); var content = file.getBlob().getDataAsString(); if (!content) { // ファイルの内容が空の場合 return {}; } else { var json = JSON.parse(content); return json; } }
Postリクエスト受信と制御
今回もメッセージ受信にはdoPost
関数を使用します。
ただし、引数e
にはLINEからのメッセージではなくSlackからのメッセージが格納されています。
まずはeからLINEに通知したい各種情報を取得します。 今回はメッセージ用にチャンネル名、ユーザ名、本文を取得しました。 また、送信元が正しいか確認するためにSlackトークンも取得しておきます。
function doPost(e) { // 1.各種情報を取得 // (1)チャンネル名 var chName = e.parameter.channel_name; // (2)ユーザ名 var userName = e.parameter.user_name; // (3)本文 var text = e.parameter.text; // (4)Slackトークン var slackToken = e.parameter.token; // 2.メッセージの組み立て var msg = 'Slack投稿通知\n' + 'チャンネル : ' + chName + '\n' + '発言者 : ' + userName + '\n' + '内容 : ' + text; // 3.送信 switch (slackToken) { case SLACK_TOKEN: pushToLine(msg); break; default: // do nothing } }
LINEへ通知
LINEへの通知データの中にはLINEのユーザIDが必要です。 そのため、getLineUserIdList関数を作りGoogle DriveのLineUserList.jsonから情報を取得します。
取得したすべてのLINE IDに対しループさせ、メッセージを送ります。
function pushToLine(text) { // LINEユーザ一覧を読み込む。 var lineUserList = getLineUserIdList(); // 全LINEユーザに対して繰り返し処理を実行する。 for (i in lineUserList) { var lineUserId = lineUserList[i]; try { pushToLineOneUser(text, lineUserId); } catch (err) { console.log(err); } } }
確認
ウェブアプリケーションとして導入し、Slackのgeneralチャンネルにメッセージを投稿するとLINEに届きました。
課題
これで一通りSlackとLINEのメッセージのやり取りができるようになりました。しかしまだ以下のような課題があります。
- ログをファイルとして保存しておきたい。画面からの確認はタイムラグがある(?)し、ちょっと使いづらい。
- LINEで同時にブロック・ブロック解除すると、LineUserList.jsonに反映されない場合がある(競合している)。
対処したらまた記事にします。