プログラミングド素人でもAPIを使えるのか試してみた

プロトアウトスタジオという、プログラミングスクールではなく、プロトタイピングをアウトプットするというスクールに参加し始めた人の記事です。

前回の投稿で、LINE bot とAPIを繋げる宿題を達成できず、講師の方に対応策をご指南いただきました。
※前回投稿：ド素人がプロトタイピングスクールに入ったらどうなったか＆宿題公開
https://qiita.com/hiromae0213

繋げ先のAPIは、「リクエストをもらったらランダムに柴犬画像を返す」というAPIを使っています。

※API：
https://shibe.online/

下記記事を参考にしています。

物知りLINE BOTを作ろうとしたらfugaしか答えない残念な奴になった話
https://qiita.com/zgw426/items/a5196ab7f26b785479ec

```js
'use strict';

const express = require('express');
const line = require('@line/bot-sdk');
const axios = require('axios');
const PORT = process.env.PORT || 3000;

const config = {
    channelSecret: 'xxxx',
    channelAccessToken: 'xxxx'
};

const app = express();

app.post('/webhook', line.middleware(config), (req, res) => {
    console.log(req.body.events);
    Promise
      .all(req.body.events.map(handleEvent))
      .then((result) => res.json(result));
});

const client = new line.Client(config);

function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  let mes = 'ちょっとまってね'; // 待ってねってメッセージだけ先に処理

  getQiitaTag(event.source.userId , event.message.text); // スクレイピング処理が終わったらプッシュメッセージ

  return client.replyMessage(event.replyToken, {
    type: 'text',
    text: mes
  });
}

const getQiitaTag = async (userId,tag) => {

    let mes = '';
    try {
        const res = await axios.get('http://shibe.online/api/shibes?count=1&urls=true&httpsUrls=true' );
        const item = res.data;
        mes = item[0];
    } catch (error) {
        // 該当しないものは404でエラーになる
        const {
            status,
            statusText
        } = error.response;
        console.log(`Error! HTTP Status: ${status} ${statusText}`);
        if( status == 404 ){
            mes = 'Qiitaのタグ「' + tag + '」の記事はありませんでした';
        } else {
            mes = `Error! HTTP Status: ${status} ${statusText}`;
        }
    }

    await client.pushMessage(userId, {
        type: 'text',
        text: mes,
    });
}

app.listen(PORT);
console.log(`Server running at ${PORT}`);
```
LINEで何かを入力したら柴犬画像を返すAPIを呼び出して、柴犬画像のURLがLINE上に表示されました。

![LINEトリミング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599091/be684070-02ab-b455-15ed-c13696c5c577.png)


流れ的には下記のようなイメージを持っていますが、
今の私のレベルではわからない領域が多くてなぜ上記コードが
上手く動いているかは理解できていません。

![LINE botの流れ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599091/9913d347-52e1-2d40-a483-2a2d9d36c9a0.png)

プロトアウトスタジオ第2回の宿題は、
「今日学んだこと（APIの仕組み）やLine Botを発展させる」です。
LINE Botは現状わからないことが多すぎて無理そうなので、まずは自分が理解できる領域で何かできないか考えてみました。

Progateを通じてHTMLとJavaScriptの基本中の基本はわかってきたことをふまえ、
下記のような形で、APIで取得した画像をHTML上に表示させる仕組みの実装にチャレンジしました。

![HTML案①.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599091/f6530539-637e-f676-d94e-18e7c55a3d30.png)

が、エラー！
理由は、「axiosはサーバ側で動かすものなのでフロント側で使うものではない」そうです。
ただ、HTML上のscriptタグで記載しておけば使えることは使えるそうで、下記のような形で再チャレンジしました。

![HTML案②.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599091/100d5f88-b240-c8da-545a-240c62f89114.png)


が、再度エラー。
理由としては、取得した画像データを直接フロント側で読み込むのは何とかオリジン（←名前忘れた、、、）の制約に引っかかるケースが多く難しいそうです。

最終的にはその制約に引っかからないAPIを講師の方に見繕っていただき、つなぐことができました！

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>犬の画像を呼び出す</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>      
    <button id="btn">ボタン</button>
    <img src="#" id="shiba">
    <script src="app.js"></script>
</body>
</html>
```

```js
let dogImage='';

document.querySelector('button').addEventListener('click',()=>{
        axios.get('https://dog.ceo/api/breeds/image/random')
       .then(function (response) {
         dogImage=response.data.message;
         document.getElementById('shiba').src= dogImage;
       })
       .catch(function (error) {
         // handle error
         console.log(error);
       });
    })
```

![感性物.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599091/402e0382-a33a-65bb-1e68-ef365f6e5843.png)

ということで、
ProgateのHTML/CSSとJavaScriptを2周やった程度でもAPIを呼んで取得した情報を表示させる、までは何とかたどり着けました。

これを作りながら、本当は下記のような形にできれば柴犬APIで取得した画像も表示できるのでは？と考えましたが、まだ時間が足りないのでこれから勉強します。
![今後できるようになりたいこと.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599091/d297a16e-aad1-7107-cf21-42bd3dab8e25.png)