Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What are the problem?
Organization

デブ活必需品!? お菓子の虜LINE bot

とにかく甘いお菓子が好き🍭

 おしゃれなスイーツも、手作りケーキもおいしいけれど、私は断固「お菓子」推し!!
 なんと数百円で楽園へひとっとび…わかる人にはわかりますよね・・・?
 お菓子.PNG

 https://twitter.com/okinakamasayos1/status/1447864486598103041
 https://twitter.com/okinakamasayos1/status/1423594038947500036

私の神サイト「お菓子の虜」🍫

 メーカーが書いた記事じゃなく、実際に食べ歩いたレビューがなんと2,600種類以上!
 お菓子好きにはたまらない「新商品」「期間限定商品」を重点的に紹介してくれます。
 短くも美しく、想像力を掻き立てるレビューは必見ですよ~例えばこちら
 「マロン」「梨」「ココア」など永遠にキーワード検索していられます。。。

APIで「お菓子の虜LINE bot」を作る🍓

 そんな神サイトにWebAPIを発見!覚えたてのLINEbotの技術を組み合わせて、
 キーワードを打ち込むと最新のお菓子情報が返信されるLINEbotを作りました!
 チョコ?ピスタチオ? ふっと浮かんだキーワードから、
  瞬時にあなたを最新お菓子レビューへ誘います!

 完成品・コードははこちら




サンプルコード (クリックで表示)



'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サーバーを実行中です…`);

甘いだけじゃない苦労話🍋

 ①日本語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」と検知しているのか、今の自分にはわからなかった。

    } catch (error) {
            result = '' + tag + '」のお菓子はまだないみたい。

努力は夢中に勝てない🍎

 実はLINE botを作るのは今回が2回目。自分の大好きなテーマで制作したので
 難しいながらも夢中で取り組め、理解も進んだと思う。今後は業務にも結び付けたいが、
 いつも自分の「好き」や「やってみたい」に真摯に向き合っていたいな~と
 お菓子を食べながら振り返る深夜1時30分でした🍫

 お菓子楽しみ.PNG

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
4
Help us understand the problem. What are the problem?