21
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

タイトルを呟いたらポスターとあらすじを答える映画どろbotを作ってみた

Posted at

『世界侵略: ロサンゼルス決戦』と『スカイライン -征服-』ってどっちがどっちでしたっけ?

ラストに主人公が〇〇になって「うぉぉぉ!」とテンション上がったほうを見返したいんですけど、どっちでしたっけ? という時にあらすじとポスターを調べてくれるLINE botを作りました。
0509-skyline.jpg

実際に動いているところの動画

手軽にネタバレなしのあらすじを知りたいときに

タイトルをGoogleやWikipediaで調べてしまうと記事タイトルでネタバレを見てしまうリスクがあります。TMDb(The Movie Database)から取得するので公式のあらすじとポスターだけを知ることができます。

こんな時に使えます。

  • 映画をおすすめされた時にあらすじとポスターを知りたい
  • 自分が長期シリーズの何作目まで観たのか思い出したい

環境

Node.js 15.12.0
npm 7.6.3
axios 0.21.1
LINE bot
TMDb API

コード

app01.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: '【LINEのAPIキーを入力】',
    channelAccessToken: '【LINEのアクセストークンを入力】'
  };
  
// ########## ▼▼▼ メイン関数 ▼▼▼ ##########
const sampleFunction = async (event) => {   
        let pushTitle = '';
        let pushOriginalTitle = '';
        let pushOverview = '';
        let pushPosterUrl =  '';
        let pushBackdropUrl =  '';

        try {

            //APIの説明ページは https://developers.themoviedb.org/3/search/search-movies です。
            let response = await axios.get(
                'https://api.themoviedb.org/3/search/movie?api_key=【TMDbのAPIキーを入力】&language=ja&query='+ encodeURIComponent(event.message.text)+'&page=1&include_adult=false'
              );
            
            //検索結果が複数の場合に備えてループする
              for (let i = 0; i < response.data.total_results; i++) {
                pushTitle = response.data.results[i].title;
                pushOriginalTitle = response.data.results[i].original_title;
                pushOverview = response.data.results[i].overview;
                pushPosterUrl = 'https://image.tmdb.org/t/p/original' + response.data.results[i].poster_path;
                pushBackdropUrl = 'https://image.tmdb.org/t/p/original' + response.data.results[i].backdrop_path;

                await client.pushMessage(event.source.userId, {
                  type: 'text',
                  text: pushTitle,
              });
                await client.pushMessage(event.source.userId, {
                  type: 'text',
                  text: pushOriginalTitle,
              });

              await client.pushMessage(event.source.userId, {
                type: 'text',
                text: pushOverview,
              });

              await client.pushMessage(event.source.userId, {
                type: 'image',
                originalContentUrl: pushPosterUrl,
                previewImageUrl:pushPosterUrl
              });

              await client.pushMessage(event.source.userId, {
              type: 'image',
              originalContentUrl: pushBackdropUrl,
              previewImageUrl:pushBackdropUrl
              });

            }

        } catch (error) {
            // APIからエラーが返ってきたらメッセージに表示する
            await client.pushMessage(event.source.userId, {
              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サーバーを実行中です…`);

詰まったところをシェアします

  1. 前回QiitaAPIを使って記事の作成日を取得したときにはdataが配列でしたが、TMDb APIはdataより1段下のresultsが配列でした。TMDb APIの仕様書をちゃんと読みましょう。
    QiitaAPI: response.data[i].created_at
    TMDb API: response.data.results[i].original_title

  2. LINE botで画像として送るにはhttpではダメで、httpsにする必要がありました。LINE botの仕様書をちゃんと読みましょう。

おわりに

Googleでタイトルを検索すれば同じことはできるのですがLINE botに呟くほうが圧倒的に簡単で余計な情報を目にする必要もなく、ポスターの画質も良くて満足です。今回はngrokで仮で動かしましたが自分用に常時起動しておいてもいいと思ってしまうほどでした。

TMDbのサイトをブラウザで見ると劇中画像が複数枚あったり、各国のポスターも閲覧できるので、これもAPIで取れないか今後やってみたいです。

━-━-━-━-━-━-━-━-━-━-━-━-━━-━-━-━-━-━-━-━-━
2021年4月からプロトアウト(プロトタイプ+アウトプット)スタジオに参加して、技術を学んだり自身を深掘りして卒業制作=クラウドファンディングのテーマを決めたりしています。

金融系SEという安定稼働を最優先にガチガチに設計書を作ってバグは許さぬ、という世界で十数年やってきました。自分の性格としても独創的なアイディア出しは苦手で、決まったことを正確に効率的にこなすことが得意です。

そんな私が無事クラウドファンディングに辿り着いて成功できるのか、見守っていただけましたら幸いです。

〇情報発信
・自身とテーマ深掘り的な記事 → note
・開発中のつぶやき → Twitter

参考URL

TMDbのAPIの映画情報をPythonで取得してみた
Web APIを利用して映画のポスターやあらすじを自分のサイトに表示する
ジェイソン・ステイサムで妄想するのが日課になっていたので、いっそBOTにしてみた。
LINE Messaging API でできることまとめ【送信編】

21
21
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
21
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?