1. okinakamasayoshi

    Posted

    okinakamasayoshi
Changes in title
+デブ活必需品!? お菓子の虜LINE bot
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,168 @@
+## とにかく甘いお菓子が好き🍭
+ おしゃれなスイーツも、手作りケーキもおいしいけれど、私は断固「お菓子」推し!!
+ なんと数百円で楽園へひとっとび…わかる人にはわかりますよね・・・?
+ ![お菓子.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/aee61234-4d5f-fb19-0aad-295ed5bd82fc.png)
+
+ https://twitter.com/okinakamasayos1/status/1447864486598103041
+ https://twitter.com/okinakamasayos1/status/1423594038947500036
+## 私の神サイト[「お菓子の虜」](https://sysbird.jp/toriko/)🍫
+ メーカーが書いた記事じゃなく、実際に食べ歩いたレビューがなんと2,600種類以上!
+ お菓子好きにはたまらない「新商品」「期間限定商品」を重点的に紹介してくれます。
+ 短くも美しく、想像力を掻き立てるレビューは必見ですよ~例えば[こちら](https://sysbird.jp/toriko/2021/10/07/%e3%82%ab%e3%83%ac%e3%83%bb%e3%83%89%e3%83%bb%e3%82%b7%e3%83%a7%e3%82%b3%e3%83%a9%e3%83%94%e3%82%b9%e3%82%bf%e3%83%81%e3%82%aa/)
+ 「マロン」「梨」「ココア」など永遠にキーワード検索していられます。。。
+
+
+## APIで「お菓子の虜LINE bot」を作る🍓
+ そんな神サイトにWebAPIを発見!覚えたてのLINEbotの技術を組み合わせて、
+ <font color="Red">**キーワードを打ち込むと最新のお菓子情報が返信されるLINEbotを作りました!**</font>
+ チョコ?ピスタチオ? ふっと浮かんだキーワードから、
+  瞬時にあなたを最新お菓子レビューへ誘います!
+
+ 完成品・コードははこちら<br>
+<iframe width="853" height="480" src="https://www.youtube.com/embed/grNKWPTL2so" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
+<br>
+<details><summary>サンプルコード <font color="Red">**(クリックで表示)**</font></summary><div><br><br>
+
+
+```js
+
+'use strict';
+
+// ########################################
+// 初期設定など
+// ########################################
+
+// パッケージを使用します
+const express = require('express');
+const line = require('@line/bot-sdk');
+const axios = require('axios');
+
+// ローカル(自分のPC)でサーバーを公開するときのポート番号です
+const PORT = process.env.PORT || 3000;
+
+// Messaging APIで利用するクレデンシャル(秘匿情報)です。
+const config = {
+ channelSecret: 'チャンネルシークレット',
+ channelAccessToken: 'アクセストークン'
+};
+
+
+const getQiitaTag = async (userId, tag) => {
+ let result = '';
+ try {
+ // axiosでお菓子のAPIを叩きます
+ const res = await axios.get('https://sysbird.jp/webapi/?apikey=guest&keyword=' + encodeURIComponent(tag)+'&max=1&format=json');
+ const item = res.data;
+ result = '最新の「' + tag + '」関連お菓子は、' + item.item.regist + '紹介、\r\n「' + item.item.name + '」\r\n!詳しくはこちら(^^♪ \r\n' + item.item.url + '!';
+
+ // ターミナルにも検索結果を出しておきます
+ console.log(`「${tag}」の検索結果:${item.item.name}`);
+ // 正常に取得できればここで終了
+ } catch (error) {
+ result = '「' + tag + '」のお菓子はまだないみたい。\r\n開発者のつもりで想像してみて♪\r\n私の一押しはこれ!https://sysbird.jp/toriko/2021/10/04/%e8%b4%85%e6%b2%a2%e3%83%ab%e3%83%9e%e3%83%b3%e3%83%89/';
+
+ }
+
+ // リプライではなく「プッシュ」を送ります
+ // Botからユーザーへ一方的に通知を送ることができる機能です
+ await client.pushMessage(userId, {
+ type: 'text',
+ text: result,
+ });
+}
+
+const sampleFunction = async (event) => {
+
+ getQiitaTag(event.source.userId, event.message.text);
+
+ // こちらが先に返事を返します
+ // ユーザーからのメッセージに対する「リプライ」です
+ // リプライは、受信したメッセージ1つにつき1回しか使えません
+ return client.replyMessage(event.replyToken, {
+ type: 'text',
+ text: 'あま~く詮索中……🍫🍭🍎🍊'
+ });
+};
+
+// ########################################
+// LINEサーバーからのWebhookデータを処理する部分
+// ########################################
+
+// LINE SDKを初期化します
+const client = new line.Client(config);
+
+// LINEサーバーからWebhookがあると「サーバー部分」から以下の "handleEvent" という関数が呼び出されます
+async function handleEvent(event) {
+ // 受信したWebhookが「テキストメッセージ以外」であればnullを返すことで無視します
+ if (event.type !== 'message' || event.message.type !== 'text') {
+ return Promise.resolve(null);
+ }
+ // サンプル関数を実行します
+ return sampleFunction(event);
+}
+
+// ########################################
+// Expressによるサーバー部分
+// ########################################
+
+// expressを初期化します
+const app = express();
+
+// HTTP POSTによって '/webhook' のパスにアクセスがあったら、POSTされた内容に応じて様々な処理をします
+app.post('/webhook', line.middleware(config), (req, res) => {
+
+ // 検証ボタンをクリックしたときに飛んできたWebhookを受信したときのみ以下のif文内を実行
+ if (req.body.events.length === 0) {
+ res.send('Hello LINE BOT! (HTTP POST)'); // LINEサーバーに返答します(なくてもよい)
+ console.log('検証イベントを受信しました!'); // ターミナルに表示します
+ return; // これより下は実行されません
+ } else {
+ // 通常のメッセージなど … Webhookの中身を確認用にターミナルに表示します
+ console.log('受信しました:', req.body.events);
+ }
+
+ // あらかじめ宣言しておいた "handleEvent" 関数にWebhookの中身を渡して処理してもらい、
+ // 関数から戻ってきたデータをそのままLINEサーバーに「レスポンス」として返します
+ Promise.all(req.body.events.map(handleEvent)).then((result) => res.json(result));
+});
+
+// 最初に決めたポート番号でサーバーをPC内だけに公開します
+// (環境によってはローカルネットワーク内にも公開されます)
+app.listen(PORT);
+console.log(`ポート${PORT}番でExpressサーバーを実行中です…`);
+```
+</div></details>
+
+## 甘いだけじゃない苦労話🍋
+ **①日本語tag検索どうすればいいのか問題**
+  ` + encodeURIComponent(tag)+`を入力することで解決
+ 
+ **②JSON形式ではなかった問題**
+  ` &format=json`をAPIの最後に入力することで表記がJSONに
+
+ **③画像が表示できない問題(未解決)**
+  JSONではjpegでデータを取得できているが、LINEで表示させられず、今回は断念。
+
+ **④長いURLではなくサムネイルだけ表示させたい(未解決)**
+  レビューサイトの長ったらしいURLではなく、サムネイル画像だけを表示させ
+  クリックするとレビューサイトへ飛べるようにしたかったが、辿り着けなかった。
+
+ **⑤検索結果が「0」だのときのリプライ問題**
+  `try...catch文`で「0」をエラーとして検知し、別のメッセージを表示させた。
+  当初catch文の中にif文で組んでいたがうまくいかず、
+  結果シンプルに下記のコードで実行できた。
+  `{ status: 'OK', count: '0' }`というJSONデータが帰ってきており、
+  これをどのような理由で「error」と検知しているのか、今の自分にはわからなかった。
+
+```js
+ } catch (error) {
+ result = '「' + tag + '」のお菓子はまだないみたい。
+```
+
+## 努力は夢中に勝てない🍎
+ 実はLINE botを作るのは今回が2回目。自分の大好きなテーマで制作したので
+ 難しいながらも夢中で取り組め、理解も進んだと思う。今後は業務にも結び付けたいが、
+ いつも自分の「好き」や「やってみたい」に真摯に向き合っていたいな~と
+ お菓子を食べながら振り返る深夜1時30分でした🍫
+
+ ![お菓子楽しみ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/f0eb0881-4de1-d5b3-2092-a1a4978e6169.png)