質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

LINE Messaging API

LINE Messaging APIは、メッセージの送信・返信ができるAPIです。Web APIを経由しアプリケーションサーバとLINEのAPIでやり取りが可能。複数のメッセージタイプや分かりやすいAPIリファレンスを持ち、グループチャットにも対応しています。

kintone

kintone(キントーン)とは、サイボウズ社が提供する業務改善プラットフォームです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

1320閲覧

LINE公式アカウントの応答モードをチャットモードで行ったトーク履歴を、kintoneへ登録したい

okayuki1029

総合スコア5

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

LINE Messaging API

LINE Messaging APIは、メッセージの送信・返信ができるAPIです。Web APIを経由しアプリケーションサーバとLINEのAPIでやり取りが可能。複数のメッセージタイプや分かりやすいAPIリファレンスを持ち、グループチャットにも対応しています。

kintone

kintone(キントーン)とは、サイボウズ社が提供する業務改善プラットフォームです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2020/08/20 05:38

編集2020/08/20 08:19

普段は見る専門だったのですが、この度初めてteratailへ質問させていただきます。
不足分等ありましたらご指摘いただけたら幸いです。
何卒よろしくお願いいたします。

前提・実現したいこと

LINE公式アカウントと友達ユーザーとのトーク履歴をFirebaseで取得し、
kintoneに保存するプログラムを作っています。

<システムフロー>
0. 企業のLINE公式アカウントで友達とトークのやり取り
0. LINEMessagingAPIのWebhookを使用してトークをトリガーとしてFirebaseにデータを渡す
0. FirebaseのfunctionでLINEのJSONデータを取得
0. kintoneに登録するためのJSONデータを生成し、kintoneへPOST

発生している問題

LINEの仕様で、2の際、応答モードがbotモードでないとWebhookを使用できない仕様ということが
わかりました。。
そのため、企業アカウントとユーザーとの直接やり取り(応答モード:チャットモード)でのやり取りが
Firebaseで取得できません。

Webhookイベントは、ユーザーがボットとやり取りするとトリガーされます。

https://developers.line.biz/ja/glossary/#webhook-url

(※取り急ぎbotモードでは取得に成功したため既存ソースとして展開いたします。)

知りたいこと

今回は上記のようなフローで実装しておりましたが、先述の問題が発生したことにより、回避策を考えております。
何か別の方法を経由、もしくは抜本的に別の方法を用いて実装などによってLINEのトーク履歴を取得する方法を探しているのですが、
どうしても分からないため質問させていただきます。

試したこと

まずbotモードで正常にkintoneへPOSTできるか実装致しました。(下記のソースになります)
こちらの方法は成功しております。
kintone側への登録画面も添付いたします。

既存のソースコード

JavaScript

1'use strict'; 2 3const functions = require('firebase-functions'); 4const express = require('express'); 5const line = require('@line/bot-sdk'); 6const kintoneRec = require('request'); 7const moment = require('moment'); 8 9const app = express(); 10 11/************************************************************ 12 * LINE設定情報 13 ***********************************************************/ 14const lineToken = '{xxxxxxxxxxxxxxx}'; 15const config = { 16 channelSecret: '{xxxxxxxxxxxxxxx}', 17 channelAccessToken: lineToken, 18}; 19 20/************************************************************ 21 * kintone共通設定情報 22 ***********************************************************/ 23const subDomain = 'ss-kintone-dev'; 24const oneRecordUrl = 'https://' + subDomain + '.cybozu.com/k/v1/record.json'; 25const someRecordsUrl = 'https://' + subDomain + '.cybozu.com/k/v1/records.json'; 26const kintoneAPPid = '{xxxxxxxxxxxxxxx}'; 27const kintoneAPPToken = '{xxxxxxxxxxxxxxx}'; 28 29/************************************************************ 30 * ここから処理スタート 31 ***********************************************************/ 32app.post('/webhook', line.middleware(config), (req, res) => { 33 34 //req.body.eventsのJSONデータは配列形式で返ってくる仕様になっている→[{・・・}] 35 //LINEから取得したJSONデータ 36 let contents = req.body.events[0]; 37 38 const LineNowDate = getNowDate(); 39 const LinelastUpdate = convIsoDate(); 40 const LineUserId = contents.source.userId; 41 const LineMessageId = contents.message.id; 42 const LineMessageText = LineNowDate + '\n' + contents.message.text + '\n-----------\n'; 43 44 /************************************************************ 45 * 現在時刻を取得(※LINEのtimestampを使用しようとすると変な文字列を取得してしまうため現在時刻で対応) 46 ************************************************************/ 47 function getNowDate() { 48 const mom = moment(); 49 let jpDate = mom.add(+9, 'h'); //海外時間となるため9時間加算 50 return jpDate.format('YYYY年MM月DD日 HH:mm'); 51 } 52 /************************************************************ 53 * 現時刻日時をkintone登録用にISO8601形式へ変換 54 ************************************************************/ 55 function convIsoDate() { 56 let now = new Date(); 57 return now.toISOString(); 58 } 59 60 /************************************************************ 61 * ここからkintone側への処理 62 * 63 ************************************************************/ 64 65 //POST用:kintoneのJSON形式に当てはめる 66 var bodyPost = { 67 'app': kintoneAPPid, 68 'record': { 69 'userID': { 70 'value': LineUserId, 71 }, 72 'lastUpdate': { 73 'value': LinelastUpdate, 74 }, 75 'talkHistory': { 76 'value': LineMessageText, 77 }, 78 }, 79 }; 80 81 // GET送信のクエリ設定 82 // (query設定の書式 => url + '?app=' + アプリID + '&query(条件)=' + ('{fieldCode} in ("' + {value} + '") ) 83 let query = ('userID in ("' + LineUserId + '")'); 84 85 // URL設定 86 let url = someRecordsUrl + '?app=' + kintoneAPPid + '&query=' + query; 87 88 // GETリクエスト送信 89 let LinePromise = sendGetKintone(url, kintoneAPPToken); 90 console.log('GET成功'); 91 92 //dataはGETリクエスト送信して返ってきた値 93 LinePromise.then(function (data) { 94 // 返ってきた値のrecordsの数を取得 95 let count = data['records'].length; 96 97 // パラメータ指定して取得できたrecordの数が1以上の場合=>更新となる=>PUST送信 98 if (count > 0) { 99 /************************************************************ 100 * PUT用JSON生成:kintoneのJSON形式に当てはめる 101 102 ************************************************************/ 103 104 // ※PUT送信した後のレスポンスデータのうち、LINEメッセージのみ抽出 105 let oldLineMessage = data['records'][0]['talkHistory']['value']; 106 107 var bodyPut = { 108 'app': kintoneAPPid, 109 'updateKey': { 110 'field': 'userID', 111 'value': LineUserId, 112 }, 113 'record': { 114 'lastUpdate': { 115 'value': LinelastUpdate, 116 }, 117 'talkHistory': { 118 'value': LineMessageText + oldLineMessage, 119 }, 120 }, 121 }; 122 123 console.log('PUT処理始めます'); 124 var kintonePutResponse = sendPutKintone(bodyPut, kintoneAPPToken); 125 126 // パラメータ指定して取得できたrecordの数が0の場合=>データが無い=>新規登録=>POST送信 127 } else { 128 // POST送信した後のレスポンスデータ格納 129 console.log('POST処理始めます'); 130 let kintoneResponse = sendPostKintone(bodyPost, kintoneAPPToken); 131 } 132 }); 133}); 134 135/************************************************************ 136* GET送信共通処理 137* 戻り値はpromise型のJson 138***********************************************************/ 139function sendGetKintone(url, token) { 140 // 全件取得 141 var params = { 142 url: url, 143 method: 'GET', 144 json: true, 145 headers: { 146 'X-Cybozu-API-Token': token, 147 }, 148 }; 149 // kintone連携 150 return commonToKintone(params); 151} 152 153/************************************************************ 154* POST送信共通処理 155* 戻り値はpromise型のJson 156***********************************************************/ 157function sendPostKintone(sendObj, token) { 158 // パラメータ設定 159 var params = { 160 url: oneRecordUrl, 161 method: 'POST', 162 json: true, 163 headers: { 164 'X-Cybozu-API-Token': token, 165 'Content-Type': 'application/json', 166 }, 167 body: sendObj, 168 }; 169 170 // kintone連携 171 return commonToKintone(params); 172} 173 174function sendPutKintone(sendObj, token) { 175 // パラメータ設定 176 var params = { 177 url: oneRecordUrl, 178 method: 'PUT', 179 json: true, 180 headers: { 181 'X-Cybozu-API-Token': token, 182 'Content-Type': 'application/json', 183 }, 184 body: sendObj, 185 }; 186 187 // kintone連携 188 return commonToKintone(params); 189} 190 191/************************************************************ 192* kintoneリクエスト(GET,POST,PUT)共通処理:パラメータを送るだけの処理 193* 戻り値はPromise型のJson 194* paramsの中にはGET, POST, PUTのそれぞれのパラメータが入っている 195***********************************************************/ 196function commonToKintone(params) { 197 //Promiseを返す。HTTPリクエストした値を保持するため 198 return new Promise(function (resolve) { 199 // kintone連携 200 kintoneRec(params, function callBack(err, resp, body) { //kintoneからGETしてきたデータがbodyに入っている 201 if (err) { //kintoneへの接続自体ができなかった場合の処理 202 console.log(err); 203 return; 204 } 205 console.log(JSON.stringify(body)); 206 207 // ファンクションの戻り値 208 resolve(JSON.parse(JSON.stringify(body))); 209 }); 210 }); 211} 212 213exports.app = functions.https.onRequest(app);

![イメージ説明
※kintone側に登録された様子

###補足(自分が調べて得た情報)
0. チャンネルトークという有料サービス使用
https://channel.io/ja/blog/line_to_channeltalk
→上記を使用すれば可能そうなのですが、今後の運用のことを考えますと自社で開発できたら良いなと思っております。。

0. グループトークへLINEbotを招待し、ユーザー同士のトークからWebhookを走らせサーバーでデータを取得
https://taupe.site/entry/line-messaging-api/
→目指したゴールには非常に近いのですが、あくまで今回はLINE公式アカウントとユーザーとの1対1のやり取りを保存したいため、
泣く泣く採用できませんでした。

0. LINEWORKS上のトーク履歴を取得しkintoneへ登録
https://developer.cybozu.io/hc/ja/articles/360000783023

→仕様としては、まさに得たいゴールだったのですが、LINEWORKSというサービスのみ違い、
泣く泣く採用できませんでした。。

###利用環境
0. VScode
0. Node.js 6.14.7
0. Windows10

以上となります。
お分かりいただける方、お知恵を拝借できたら幸いです。
何卒よろしくお願いいたします。m(_ _)m

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

私も同様の問題のため、公式のチャット管理画面のような画面を自作して対応するようにいたしました。
他にも複数社、自前で管理画面を作っている会社を知っているので、面倒ですが管理画面を自作してしまうのが現実的な解になるかと思います。

ただ履歴を保存したいというだけなら、公式管理画面をスクレイピングしてしまうのもありかもしれません。

投稿2020/08/25 18:10

Arahabica

総合スコア209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

okayuki1029

2020/09/02 00:12

>Arahabica様 ご返事が遅くなり申し訳ありません。 また、ご回答ありがとうございました。 おっしゃる通り、専用の画面を作ることが現実的ですよね…。 当方も、あの後も様々な方法を試したのですが、やはりできませんでしたので、そのとおりかと思います。 >公式管理画面をスクレイピングしてしまうのもあり なるほど…、おっしゃる通り、それも手ですね。ありがとうございます。 ただ、社内と当方自身がPythonのスキルがないことと納期の関係から少々難しいという判断に至ってしまいました。。 ご意見ありがとうございました。大変勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問