はじめに
LINE Botのプッシュメッセージ※を利用するためには 「userID」 が必要です。
userIDはアカウントごとに一意の値であり、
1つのBot(正確には1つのプロバイダー)から見たら、同じアカウントは同じuserIDとなります。
-> このuserIDでアカウントを特定することができる!!
-> -> 「Bot A にメッセージを送信すると、別のBot Bから返事が返ってくる」ってこともできます!!
しかし、
このuserIDは「友達登録時」「ユーザーからのメッセージ受信時」といったように、ユーザーが何かアクションをしないと取得できません
ということで、
任意のタイミングでメッセージを送るためには、あらかじめuserIDをためておくDBが必要になります!
(ってことで、)
今回は友達登録された際に kintone へuserIDを登録する方法を書きます!!
※プッシュメッセージについては こちら をご覧ください
仕組み・フロー
ユーザーの操作が「友達登録」なのか「メッセージ送信」なのかは Webhookで受け取れるイベントの中にあるtype
で判断することができます。
event.body.events[].type
このtypeは、
-
follow
-> 友達登録 (とブロック解除) -
unfollow
-> ブロック -
message
-> メッセージ送信
という感じに判断できます。なのであとはいい感じに分岐すれば良いだけです!
ちょっとまじめに流れを書いてみると、
- Webhookを受け取る
- イベントオブジェクトからtypeとuserIDを取得する
- typeが
follow
かunfollow
なら、userIDをクエリとしてkintoneのレコードを取得する -
follow
かつ該当レコードがなければ、userIDをkintoneへ登録する
(ついでにアカウント名なども一緒に) -
follow
かつ該当レコードがあれば、「ブロック解除」の処理をする
-> 取得したレコードを更新する -
unfollow
であれば、該当レコードを「ブロック中」と更新する
こんな感じかと。(4へは最初の1回だけ。あとは5or6への処理を繰り返す)
kintone側の設定
DBとしてkintoneを使います!!! (S3やDynamoでもいいじゃんは ですw)
フィールド
kintoneのフィールドは以下のようにしました
フィールド | フィールドコード | 用途 |
---|---|---|
作成日時 | create_time | Botを追加した日時 |
文字列(1行) | line_name | LINEのアカウント名 |
文字列(1行) | line_id | LINEのuserID |
チェックボックス | line_block | Botのブロック判断 |
フィールドを配置するとこんな感じです。
APIトークン
設定 > APIトークン
から 閲覧/追加/編集
にそれぞれチェックをつけてトークンを発行してください。
コード
GitHub においてあります。cloneすればとりあえず動くとは思います。
// 作業用ディレクトリへ移動
$ cd work
// リポジトリのクローン
$ git clone https://github.com/RyBB/LINE_FriendsRegist_kintone.git
// ディレクトリの移動
$ cd LINE_FriendsRegist_kintone
// node_moduleのインストール
$ npm install
中間サーバとしてLambda(とAPI Gateway)を利用しています。AWS側の細かい設定は省略!
(AWSの設定はこちらを参考にすると良いです)
const kintone = require('kintone-nodejs-sdk');
const line = require('@line/bot-sdk');
const kin_common = {
url: process.env.KINTONE_DOMAIN,
apiToken: process.env.KINTONE_APITOKEN,
appId: process.env.KINTONE_APPID,
fCode1: 'line_name',
fCode2: 'line_id',
fCode3: 'line_block',
};
const kintoneAuth = new kintone.Auth();
kintoneAuth.setApiToken(kin_common.apiToken);
const kintoneConnection = new kintone.Connection(kin_common.url, kintoneAuth);
const kintoneRecord = new kintone.Record(kintoneConnection);
// kintoneのレコードをクエリで条件取得する処理
const getRecords = (LINE_USER_ID) => {
const query = kin_common.fCode2 + ' = "' + LINE_USER_ID + '"';
return kintoneRecord.getRecords(kin_common.appId, query, ['$id'], true);
};
// kintoneのレコードを1件登録する処理
const postRecord = (LINE_USER_ID, LINE_NAME) => {
const params = {
[kin_common.fCode1]: {
'value': LINE_NAME
},
[kin_common.fCode2]: {
'value': LINE_USER_ID
},
};
return kintoneRecord.addRecord(kin_common.appId, params);
};
// kintoneのレコードを1件更新する処理
const putRecord = (LINE_USER_ID, recordid, follow) => {
const params = {
[kin_common.fCode2]: {
'value': LINE_USER_ID
},
[kin_common.fCode3]: {
'value': follow === 'follow' ? [] : ['ブロック中']
},
};
return kintoneRecord.updateRecordById(kin_common.appId, recordid, params);
};
exports.handler = async (event) => {
const res = JSON.parse(event.body);
const line_userId = res.events[0].source.userId;
const client = new line.Client({
channelAccessToken: process.env.LINE_ACCESS_TOKEN
});
let resp, line_resp;
switch(res.events[0].type) { // メッセージのタイプを判断
case 'follow': {
resp = await getRecords(line_userId);
if (resp.totalCount !== '0') {
console.log('ブロック解除された');
await putRecord(line_userId, resp.records[0].$id.value, 'follow');
break;
}
console.log('新規登録された');
line_resp = await client.getProfile(line_userId); // LINEのアカウント名を取得する
await postRecord(line_resp.userId, line_resp.displayName);
break;
}
case 'unfollow': {
resp = await getRecords(line_userId);
if (resp.totalCount !== '0') {
console.log('ブロックされた');
await putRecord(line_userId, resp.records[0].$id.value, 'unfollow');
}
break;
}
default: {
// それ以外。何もしない
}
}
};
ちょっと解説
コードをちょっとだけ解説します!
- kintone Node.js SDK
今回はkintoneへのリクエストが多い (GET/POST/PUT) ので、SDKを利用しました。
最初にコネクションを設定しないといけないですが、それ以外はかなり楽に記述できます (メソッドとか)
詳しい書き方は こちら 。
// コネクション
const kintoneAuth = new kintone.Auth();
kintoneAuth.setApiToken(kin_common.apiToken);
const kintoneConnection = new kintone.Connection(kin_common.url, kintoneAuth);
const kintoneRecord = new kintone.Record(kintoneConnection);
// メソッド (GET/POST/PUT それぞれあります)
kintoneRecord.XXXX();
- typeによる分岐
typeがfollow
かunfollow
かそれ以外
かで分岐させています。
switch(res.events[0].type) { // メッセージのタイプを判断
case 'follow': {
resp = await getRecords(line_userId);
if (resp.totalCount !== '0') {
console.log('ブロック解除された');
await putRecord(line_userId, resp.records[0].$id.value, 'follow');
break;
}
console.log('新規登録された');
line_resp = await client.getProfile(line_userId); // LINEのアカウント名を取得する
await postRecord(line_resp.userId, line_resp.displayName);
break;
}
case 'unfollow': {
resp = await getRecords(line_userId);
if (resp.totalCount !== '0') {
console.log('ブロックされた');
await putRecord(line_userId, resp.records[0].$id.value, 'unfollow');
}
break;
}
default: {
// それ以外。何もしない
}
}
- kintoneのレコード取得
kintoneのuserIDを格納するフィールド(line_id)と友達登録時(ブロック操作時)に受け取ったLINEのuserIDがマッチするレコードのみ取得するようにします。
もしマッチするレコードがあれば、すでにそのアカウントはkintoneへ登録済みってことになります!
const getRecords = (LINE_USER_ID) => {
const query = kin_common.fCode2 + ' = "' + LINE_USER_ID + '"';
return kintoneRecord.getRecords(kin_common.appId, query, ['$id'], true);
};
- kintoneのレコード更新
typeがfollow
かつレコードが存在すれば、ブロック解除したことになるので、
kintoneのチェックボックスを空にします。
逆に、typeがunfollow
であればチェックボックスに「ブロック中」と入れます。
const putRecord = (LINE_USER_ID, recordid, follow) => {
const params = {
[kin_common.fCode2]: {
'value': LINE_USER_ID
},
[kin_common.fCode2]: {
'value': follow === 'follow' ? [] : ['ブロック中']
}
};
return kintoneRecord.updateRecordById(kin_common.appId, recordid, params);
};
完成イメージ
こんな感じでkintoneにuserIDとアカウント名とブロック状況が登録されます。
おわりに
あとは任意のタイミングでkintoneからuserIDを取得してメッセージを送るだけです。
アカウント名もclient.getProfile(line_userId);
で取得しているのでデータとして扱いやすいかと!!
このくらいのDB管理であれば、むしろkintoneのほうがフォーム作ったりが簡単なのでおすすめです!
(きちんと運用する場合は「ブロックされたらレコードを削除する」などの処理のほうが良いですよ〜)
それでは!≧(+・` ཀ・´)≦