17
9

More than 1 year has passed since last update.

LINE APIでオーキードーキー博士とポケモンGETリクエストしようぜ!

Last updated at Posted at 2022-03-23

企画意図

初心者のプログラミングスキルで、最低限の面白さを表現するために、人気IPである〇〇モン(デジモンじゃない方)のデータを呼び出せるAPIの力を全力で借りて、オリジナルLINEBotの実装を目指します。

今回使用する、APIに関しては、こちらのシンプルにAPIが体験できるリストをまとめたページから選びました。初心者の方は参考にしてみてください。(僕には全然シンプルじゃなかったけどね!)

環境

Node.js
axios
Express
ngrok

<使用API>
LINE Messaging API SDK for nodejs
PokeAPI

作成するオーキードーキー博士BOTの説明

IMG_20220323_175131_2.jpg

何か親しみを感じるおじさんの顔が見えますね。紹介します、オーキードーキー博士です。(N社に怒られませんように)

今回実装する「オーキードーキー博士Bot」は、「ポケモン」という言葉を聞くと、初代ポケットモンスターに登場した151のポケモンの中から、あなたにぴったりなポケモンを選び、本日のラッキーモンスターとして提案してくれます。

それ以外の会話には、お前の話はつまらんと言わんばかりに話を遮り、「ポケモン」の話を促してきます。なかなか、頑固な性格のようです。自分の話だけしたがる方、時々いますよね。

(実装力がないばかりに、頑固な性格にしてしまってごめんよ、博士…。)

実際のBotの挙動

オーキードーキー博士のLINEBotと、ともだちになりたい方はこちら

717wplxf (1).png

※博士は気難しいので、時間帯によって既読スルーをしたり、明後日な返答をすることがあります。

ソースコード

まずは、全体のソースコードです。

'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 sampleFunction = async (event) => {
  // 1〜151の数をランダムに吐き出す
 let a = Math.floor(Math.random() * 151)
 let pushData = {};
 let replyText = '';

 if (event.message.text === 'ポケモン') {
  // axiosでpokeAPIを叩きます
  const res = await axios.get('https://pokeapi.co/api/v2/pokemon-form/' + a);
  console.log(res.data);
  // 画像を送るメッセージを作る
  pushData = {type: 'image',
  originalContentUrl: res.data.sprites.front_default,
  previewImageUrl: res.data.sprites.front_default};
  return client.replyMessage(event.replyToken,pushData)
  }
 else {
  replyText  = 'その話題はつまらん。わしはオーキードーキー博士じゃ。正確に「ポケモン」と入力すると、今日のラッキーモンスターを教えてやるぞ!';
  return client.replyMessage(event.replyToken, {
    type: 'text',
    text: replyText})
 }
  
 ;
 };
 
// ########## ▲▲▲ サンプル関数 ▲▲▲ ##########

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

各部の解説 ①(乱数の設定)

では、細かい要素を説明していきます。

  // 1〜151の数をランダムに吐き出す
 let a = Math.floor(Math.random() * 151)

PokeAPIは、IDでポケモンを呼び出せます。そのため、初代のポケモンが割り振られている1〜151の数字を吐き出すように「a」という関数をあらかじめ設定しておきます。(ゲームボーイの初代しかやったことがない。)

各部の解説 ②(関数をAPI内に呼び出す)

 const res = await axios.get('https://pokeapi.co/api/v2/pokemon-form/' + a);
  console.log(res.data);

そしてaxiosでPokeAPIを呼び出すURLに、先程の乱数を生み出す関数「a」を入れこみます。こうすることで、毎回ランダムに数字が入るようになり、色々なポケモンのデータが呼び出されるようになります。

各部の解説 ③(ポケモンの画像を呼び出す)

先程の、コードでランダムに呼び出されたポケモン一体のいろいろなデータが呼び込まれているので、その中から、さらにポケモンの画だけを指定し(front_default)image形式で吐き出すようにしておきます。

pushData = {type: 'image',
  originalContentUrl: res.data.sprites.front_default,
  previewImageUrl: res.data.sprites.front_default};

各部の解説 ④(LINEプラットフォームに送る)

先程の関数pushDataの中に、ポケモンの画像が入っているので、下記のコードでLINEプラットフォームに戻します。後は、LINEがいい感じに「ポケモン」と送ってきた、ユーザーのところに、ポケモンの画像を送り届けてくれます。

return client.replyMessage(event.replyToken,pushData)

つまずいたポイント

その①
let pushData = {};
letで関数を指定しているときに、その関数はletのある{}の中でしか効かなくなるようです。関数を指定する場所は気をつけましょう。

その②

必要のない箇所を””で囲んでしまっていたので、ただの文字として認識されてしまっていました。

<不正解>

originalContentUrl: "res.data.sprites.front_default"

<正解>

originalContentUrl: res.data.sprites.front_default,

正しいコードを書いていなかったので、結果何度も深夜にポケモンと叫び続けることになりました。みなさま、コードは正確に!

本当はやりたかったこと

「もっと優しい博士にしたかった。」
「オーキードーキー博士はポケモンの画像を返してくれるが、それにあわせてポケモンの名前や、少しフレンドリーなセリフも戻したかった。」

 return client.replyMessage(event.replyToken,pushData)
 
 return client.replyMessage(event.replyToken, {
 type: 'text',
 text: '今日の君のラッキーモンスターは**じゃ。いい日になりそうじゃのう。'})

こんな感じのコードで(これは、動きません)

ただ、JavaScriptは、returnで一つの値しか返せないらしく、それを解決する方法もあるらしいのですが、時間切れとなり、現状の石頭タイプのオーキードーキー博士に仕上がりました。

やはり今のままだと、やり取りにそっけない感じがあり、まだまだ物足りなさがあります。妻にも、実際にオーキードーキー博士と戯れてもらいましたが、フーンと言う感じでした。「あんなに夜作業してるのにこの程度ですか」と思われていないだろか…。やりたいことと、企画に手が追いつかない悔しさよ…。

そして博士!!プログラミングの勉強をちゃんとして、いつか、やさしくてひょうきんな博士に戻してやるからな!!

次回予告

名称未設定のデザイン (3).png

次回 #protoout 「やさしくなったオーキードーキー博士!?」
みんなも、俺と一緒にポケモンGETリクエストだぜ!

それでは、次の課題で会いましょう!

17
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
9