ジブリAPIでLINEBotを作ってみた。

#ジブリは好きですか？
最近、自分が好きだったアニメが〇〇周年を迎えた的なニュースをよく目にします:thinking:
あの頃のアニメは名作ばっかだなぁなんておっさんじみたことを思うわけですが、コアなものを話題に出すと「ナニソレ」って言われたりして、ちょっと寂しかったりするものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122173/0d25a437-6a34-aa6e-7068-3a784e167e63.png)

でも、<font color='red'>**ジブリのタイトルであれば、みなさんもいくつかご存じではないでしょうか。**</font>
<font color='red'>**今回、ジブリAPIなるものを見つけたので、それを使ってLINEBotのゲームを作ってみました。**</font>

[Studio Ghibli API (v1.0.1)](https://ghibliapi.herokuapp.com/)

なお、僕はジブリヲタではなく雑食系のアニヲタです。あしからず:raised_hand:

#完成品
まずは完成品から！
タイトル名を打つと、「イメージ画像」×2枚,「監督名」,「公開年」を返してくれるBotです！
間違うと、バルスされちゃうので要注意:angel_tone2:

https://twitter.com/taka_xedge/status/1450292835995951105?s=20


#使い方
娯楽ツールです。オススメの用途を記載しておきます。
　
**＜ジブリヲタへ＞**
監督・年代クイズなんかに使ってやってください。
あと、画像を用いた、より変態的なクイズもオススメです。
　・ラピュタの英語圏タイトルは？（画像は英語表記）
　・キキの靴の色は何色？
　・何も見ずにサンのナイフを描いてみよう！

**＜アニヲタ・一般の方へ＞**
何タイトル知ってるか腕試ししてみましょう。最高20点です。
あと、W〇kipediaの情報量が苦手な人にもオススメ。


#対象作品
対象作品は以下の20作品です。皆さん、いくつ知っていますか？

     ・天空の城ラピュタ
     ・火垂るの墓
     ・となりのトトロ
     ・魔女の宅急便
     ・おもひでぽろぽろ
     ・紅の豚
     ・平成狸合戦ぽんぽこ
     ・耳をすませば
     、もののけ姫
     ・となりの山田くん（正式名称：ホーホケキョ となりの山田くん）
     ・千と千尋の神隠し
     ・猫の恩返し
     ・ハウルの動く城
     ・ゲド戦記
     ・崖の上のポニョ
     ・借りぐらしのアリエッティ
     ・コクリコ坂から
     ・風立ちぬ
     ・かぐや姫の物語
     ・思い出のマーニー
     ・レッドタートル（正式名称：レッドタートル ある島の物語）


そう、、、<font color='red'>**このAPI、ナウシカがないんです:thinking:</font>**
[スタジオジブリ作品一覧はこちら](https://www.ghibli.jp/works/)

調べてみたら、苦い過去がありました。
[改悪された海外版『風の谷のナウシカ』](https://ghibli.jpn.org/report/warriors-of-the-wind/)
こうした背景もあって、もしかすると海外ではあまり知られていないのかも？説。

でも、今となっては原作も世に出回っているはずですから
結論、ジブリ創設前の作品であるナウシカをジブリ作品とみなしていない
（API提供者はこだわり強めのジブリ原理主義者）と思うことにしました。いい意味で。

#ソースコード

作品ごとにIDを設定してあげないといけないので、そこはチカラワザでやりました。
もう少しシンプルにコーディングしたかったんですが、そこは今後の課題ですね。

```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: '**********************'
};


// ########## ▼▼▼ サンプル関数 ▼▼▼ ##########

let ghibli  =''

const sampleFunction = async (event) => {

// ユーザーメッセージが正しいかどうか
switch (event.message.text) {
    case '天空の城ラピュタ':
        ghibli = '2baf70d1-42bb-4437-b551-e5fed5a87abe';
        break;
    case '火垂るの墓':
        ghibli = '12cfb892-aac0-4c5b-94af-521852e46d6a';
        break;
    case 'となりのトトロ':
        ghibli = '58611129-2dbc-4a81-a72f-77ddfc1b1b49';
        break;
    case '魔女の宅急便':
        ghibli = 'ea660b10-85c4-4ae3-8a5f-41cea3648e3e';
        break;
    case 'おもひでぽろぽろ':
        ghibli = '4e236f34-b981-41c3-8c65-f8c9000b94e7';
        break;
    case '紅の豚':
        ghibli = 'ebbb6b7c-945c-41ee-a792-de0e43191bd8';
        break;
    case '平成狸合戦ぽんぽこ':
        ghibli = '1b67aa9a-2e4a-45af-ac98-64d6ad15b16c';
        break;
    case '耳をすませば':
        ghibli = 'ff24da26-a969-4f0e-ba1e-a122ead6c6e3';
        break;
    case 'もののけ姫':
        ghibli = '0440483e-ca0e-4120-8c50-4c8cd9b965d6';
        break;
    case 'となりの山田くん':
        ghibli = '45204234-adfd-45cb-a505-a8e7a676b114';
        break;
    case '千と千尋の神隠し':
        ghibli = 'dc2e6bd1-8156-4886-adff-b39e6043af0c';
        break;
    case '猫の恩返し':
        ghibli = '90b72513-afd4-4570-84de-a56c312fdf81';
        break;
    case 'ハウルの動く城':
        ghibli = 'cd3d059c-09f4-4ff3-8d63-bc765a5184fa';
        break;
    case 'ゲド戦記':
        ghibli = '112c1e67-726f-40b1-ac17-6974127bb9b9';
        break;
    case '崖の上のポニョ':
        ghibli = '758bf02e-3122-46e0-884e-67cf83df1786';
        break;
    case '借りぐらしのアリエッティ':
        ghibli = '2de9426b-914a-4a06-a3a0-5e6d9d3886f6';
        break;
    case 'コクリコ坂から':
        ghibli = '45db04e4-304a-4933-9823-33f389e8d74d';
        break;
    case '風立ちぬ':
        ghibli = '67405111-37a5-438f-81cc-4666af60c800';
        break;
    case 'かぐや姫の物語':
        ghibli = '578ae244-7750-4d9f-867b-f3cd3d6fecf4';
        break;
    case '思い出のマーニー':
        ghibli = '5fdfb320-2a02-49a7-94ff-5ca418cae602';
        break;
    case 'レッドタートル':
        ghibli = 'd868e6ec-c44a-405b-8fa6-f7f0f8cfb500';
        break;

        default:
    return client.replyMessage(event.replyToken, {
           type: 'text',
           text: 'バルス！'
        });
    }

// 「リプライ」を使って先に返事しておきます
    await client.replyMessage(event.replyToken, {
          type: 'text',
          text: '調べています……'
        });
            
    let pushText = '';

    try {
// axiosAPIを叩きます（少し時間がかかる・ブロッキングする）
const res = await axios.get('https://ghibliapi.herokuapp.com/films/' + ghibli);

// 取得できたデータを抜き出す
const ima = res.data.image;
await client.pushMessage(event.source.userId, {
type: 'image',
originalContentUrl: ima,
previewImageUrl:ima
});

const banner = res.data.movie_banner;
await client.pushMessage(event.source.userId, {
type: 'image',
originalContentUrl: banner,
previewImageUrl:banner
});

const dir = res.data.director; 
await client.pushMessage(event.source.userId, {
type: 'text',
text: 'director:' + dir,
});  
        
const date = res.data.release_date; 
await client.pushMessage(event.source.userId, {
type: 'text',
text: 'release_date:' + date,
});

} catch (error) {
pushText = '検索中にエラーが発生しました。';
// APIからエラーが返ってきたらターミナルに表示する
console.error(error);
}

} 
// ########## ▲▲▲ サンプル関数 ▲▲▲ ##########
    
// ########################################
//  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サーバーを実行中です…`);
```


#自分で使ってみた感想
ゲームは一人じゃ成立しなかった！笑

興味ない人はホント興味ないと思うんですが、
<font color='red'>**僕の場合は新作出るたびに旧作の監督が気になったりするんですよね。
「あの作品となんか似てる！監督誰だったっけ！」とか。**</font>
（ガチのジブリヲタではないので、そこらへんは覚えてない。笑）
<font color='red'>**手軽にサクっと確認出来て、無駄な情報がない**</font>、は素直に良いところだと思いました。世の中情報過多すぎる。

ぽんぽこからもう27年経つんですね～。