Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9409

【kintone×LINE Bot】餃子検定[非公式]を作ってみた

$
0
0
はじめに 本格的に寒くていよいよ暖房を入れました、私です! アドベントカレンダー = ネタ披露 という脳内変換がされたので、書きに来ました! 何を作ったのか 私は、餃子を食べることを「自主練」と呼んでいるのですが、今年は自主練が月1の時もあり、 「そんな自主練の頻度で、本当に餃子好きと言えるのか?」「ビジネス餃子ではないのか?」と周囲の方々からのありがたい手厳しいフィードバックを頂きまして、「私の餃子好きが分かるものを作るぞ!」ということでLINE BOTを作成してみました! 自主練はサボり気味ですが、 日々、餃子の知識をインプットしている私の作った最強の(?)餃子検定を受験して下さい。 みなさま、対戦よろしくお願いします! デモ まずは、何はともあれ触ってみると早いかと思います! 早速ですが、良かったらLINE BOTと友達になって餃子検定問題に回答して頂けると嬉しいです。 10問解答すると、自分の餃子レベルが分かります。 https://lin.ee/znPnwXn 全体像 構成図 開発に必要なもの LINEアカウント Messaging APIの設定 Herokuアカウント デプロイ先のServerに利用する kintoneアプリ 餃子検定問題[非公式] 問題、選択肢、解答を管理するアプリ 餃子検定ランク 正解数に合わせた餃子ランク、メッセージを管理するアプリ 餃子検定挑戦者 問題と回答を管理するアプリ 餃子に関する問題 地味に問題作るのは時間がかかる... ざっくり解説 1. LINE BOTを作成する LINE Developer Consoleにログイン プロバイダーやMessaging APIを使用したチャネルを登録 ※後で使う: チャネルアクセストークン ※後で使う:チャネルシークレット ※後で更新する: Webhook URL リッチメニューを作成する 今回はLINE Official Account Manager 画面から作成しました。 画面上で、 表示期間 メニューで表示したい画像 メニューをクリックした時のアクション を設定すれば完成。 2. kintone 各種アプリの作成と、REST APIで利用したいためトークンを発行しておく。 kintoneアプリ 餃子検定問題集[非公式] 餃子検定ランク 餃子検定挑戦者 3. コード解説 使用したSDK LINE Messaging API SDK kintone REST API Client ①LINEからデータを受け取る ユーザーがLINE上でアクションをすると、LINEのPlatformがアクションを検知し、設定したWebhook URLにデータが送信されます。データを受け取ったサーバー(今回はHeroku)は、handleEvent関数の引数(event)にLINEから送信されたデータを受け取り、関数内のコードを実行していきます。 index.js // webhookのhandler設定 app.post('/callback', line.middleware(config), (req, res) => { Promise .all(req.body.events.map(handleEvent)) .then((result) => res.json(result)) .catch((err) => { console.error(err); res.status(500).end(); }); }); async function handleEvent(event) { let reply_msg; switch (event.type){ // ************************** // メッセージイベント受信時に実行 // ************************** case "message": reply_msg = await func.messageFunc(event); console.log(reply_msg) break; // ************************** // 問題の返信(postback)イベント受信時に実行 // ************************** case "postback": reply_msg = await func.postbackFunc(event); break; } if (reply_msg !== undefined) { return client .replyMessage(event.replyToken, reply_msg) .catch((err) => { console.error(err); }) } } ②「餃子検定を受験する」を受け取った場合 「餃子検定を受験する」文字列を受け取った場合は、 1. event.messageが'message' 2. event.message.typeが'text' 3. event.message.textが'餃子検定を受験する'と判断されて、最終的に、getGyozaQuizFunc(関数)を実行します。 // ************************** // メッセージの内容毎に返信を変える // ************************** async function messageFunc(event) { let message; switch (event.message.type) { case 'text': message = await messageTextFunc(event); break; case 'image': case 'sticker': message = { type: 'sticker', packageId: conf.package_id, stickerId: conf.stickers[Math.floor(Math.random() * conf.stickers.length)] }; break; } return message; } // ************************** // メッセージのテキストを判断して返信内容を変更する // ************************** async function messageTextFunc(event) { let message; switch (event.message.text) { case ('餃子検定を受験する'): message = await getGyozaQuizFunc(event); break; case ('おすすめの餃子'): console.log('おすすめの餃子'); message = { type: 'text', text: 'おすすめのお店を紹介します!' + conf.gyoza_stores[Math.floor(Math.random() * conf.gyoza_stores.length)] }; break; //省略 //: //: default: console.log(event); message = { type: 'text', text: event.message.text }; break; } return message; } getGyozaQuizFunc関数は、kintoneの餃子検定問題アプリからランダムに問題を1問取得、 kintoneの餃子検定挑戦者アプリにデータを登録する仕組みになっています。 // ************************** // 餃子問題を取得する関数 // ************************** async function getGyozaQuizFunc(event) { const min = 1; const max = 10; // ランダムで1問取得 const result = await kintone_client.record.getRecord({ app: kintoneGyozaQuizAppId, id: Math.floor(Math.random() * (max + 1 - min)) + min }); const current_user_data = await kintone_user_client.record.getRecords({ app: kintoneGyozaUserAppId, query: `user_id="${event.source.userId}" order by $id desc limit 1`, }); // ログインしているユーザーのクイズ数を確認 // 最新のレコードが0,10問の時は新規レコード,10問以内は更新 if (current_user_data.records[0].length === 0 || current_user_data.records[0].table.value.length === max) { const postUser = await postGyozaQuizChallengerRecord(event, result.record); } else { let params_obj = []; current_user_data.records[0].table.value.forEach(element => { let table_id = { id: element.id }; params_obj.push(table_id); }); const postUser = await updateGyozaQuizChallengerRecord(event, result.record, current_user_data.records[0].$id.value, params_obj); } const correct_arry = []; const correct_radio = result.record.answer.value; result.record.table.value.forEach(sub_table => { let val = (correct_radio === sub_table.value.select_radio.value) ? '正解' : '-'; correct_arry.push(val); }); let message = { type: "flex", altText: "解答を表示", contents: { "type": "bubble", "body": { "type": "box", "layout": "vertical", "contents": [ { "type": "text", "text": "問題", "weight": "bold", "size": "xl" }, { "type": "text", "text": result.record.question.value, "size": "md", "wrap": true }, { "type": "button", "action": { "type": "postback", "label": "A:" + result.record.table.value[0].value.select_answer.value, "data": correct_arry[0] }, "height": "sm", "margin": "sm", "style": "primary", "color": "#87ceeb" }, { "type": "button", "action": { "type": "postback", "label": "B:" + result.record.table.value[1].value.select_answer.value, "data": correct_arry[1] }, "height": "sm", "margin": "sm", "style": "primary", "color": "#87ceeb" }, { "type": "button", "action": { "type": "postback", "label": "C:" + result.record.table.value[2].value.select_answer.value, "data": correct_arry[2] }, "height": "sm", "margin": "sm", "style": "primary", "color": "#87ceeb" } ] } } } return message; } 💡ポイント Botの返信メッセージをmessage変数に入れていますが、今回のようにFLEX MESSAGEを利用したい場合は、FLEX MESSAGE SIMULATORを利用してデータを作成してから、コーディングすると簡単に実装することができます。 ③Botの返信メッセージをreturnする 最終的にreply_msg変数に、kintnoeから取得した問題データが代入され、Botの返信メッセージを送信する仕組みです。 if (reply_msg !== undefined) { return client .replyMessage(event.replyToken, reply_msg) .catch((err) => { console.error(err); }) } 4. Heroku 最終的に、Herokuにデプロイする。 デプロイの詳細手順は、公式ドキュメントを参考にすると良いです! Herokuでサンプルボットを作成する デプロイが終わったら、LINE Developer ConsoleのWebhook URLをデプロイした https://~~~.herokuapp.com/callback に修正する。 ※今回は、Webhookのエンドポイントを/callbackとしているため、 /callback を忘れずに! index.js // webhookのhandler設定 app.post('/callback', line.middleware(config), (req, res) => { Promise .all(req.body.events.map(handleEvent)) .then((result) => res.json(result)) .catch((err) => { console.error(err); res.status(500).end(); }); }); ソースコード 全ての解説はしませんでしたが、全体がどのような実装になっているのか気になる方は、 GitHubで管理しているので、参考にしてみて下さい。 今後 Lambdaに移行する 問題10問を重複しないようにしたい(現状はランダムのため重複してしまう) 「結果をシェアする」 アクションを実装? APIリクエストしすぎ問題 10問解き終わったら画像を返す 自分の中でも課題がまだあるので、時間を見て追加・改修して行けたら良いな〜 終わりに 餃子検定の結果は、いかがでしたか? 私はもちろん... これで本物の「餃子好き」と認めてもらえること間違いなしですね!? 問題も回答も自分で作成したので、当たり前の結果ですが...(笑) ということで、餃子検定に出題して欲しい問題を大募集中です。 今回は、kintoneとLINE Botを利用して、餃子検定(クイズ)アプリを作成しました。 一見、クソアプリに見えるかもしれませんが、 勉強や資格の問題を貯めておいて暇な時に使ったり、複数のメンバーで問題を作成し合って使う... なんてことができたら、面白いかもしれませんね? 皆様も、良き餃子ライフで今年を締めくくりましょう!

Viewing all articles
Browse latest Browse all 9409

Trending Articles