##知らないことは恥ではない。知っているふりや「まあいいや」と知ろうとしないことが恥なのだ。(ホリエモン)
今の私に刺さる名言です。堀江さん良いこと言いますね。
落ち込んだとき、人生の迷ったとき、暇なとき、偉人たちの名言を調べたりしますよね。
というわけで、人生を導いてくれる名言BOTを作成しました。
##LINE Bot 実演
名言を含む言葉を投げかけることでランダムで名言を返してくれます。
収録数はおよそ3000!
名言だけでは何なので、偉人たちの画像とプロフィールもつけています。
この名言が生まれた時の歴史的な背景に思いを馳せてはいかがでしょうか。
・・・動画が暗い&地味すぎる。なぜ白黒写真の偉人を引いてしまうのか。
せっかくなのでお気に入りがみつかるまでリスエストし続けてみた結果、
イチロー(SSR)ゲット
レアリティは自分の心が決める。
##開発環境
Node v16.10.0
axios 0.22.0
ngrok 2.3.40
##使用したAPI(感謝!)
名言教えるよ!のサイト ・・・名言の収録数は3000超!楽しい
ウィキペディア ・・・言わずもがなのwikiです
##ソースコード
ソースコード全文(注・長い)
'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: 'xxxxxxxxxxxxxxxxxxxxxxxxx',
channelAccessToken: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
};
const sampleFunction = async (event) => {
const usertext = event.message.text;
let replyText = '';
// ユーザーメッセージに名言が含まれるか
if (usertext.indexOf('名言') > -1 ) {
// 「リプライ」を使って先に返事しておきます
await client.replyMessage(event.replyToken, {
type: 'text',
text: '調べています……'
});
let pushText = '';
let pushText2 = '';
let pushText3 = '';
try {
// axiosで名言apiを実行してランダムで1件取得
const res = await axios.get('https://meigen.doodlenote.net/api/json.php?c=1');
//返信用のテキストを作成して出力
//console.log(res.data);
const meigen = res.data[0].meigen;
const auther = res.data[0].auther;
pushText = `本日の名言:\n${meigen}\n${auther}`;
//名言の著者でwikiから情報を取得
const res2 = await axios.get('https://ja.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro&explaintext&redirects=1&titles='+ encodeURIComponent(auther));
if(res2.data.query.pages === -1){
pushText2 = `著者:見つかりませんでした`;
}else{
for (let id in res2.data.query.pages){
const wiki = res2.data.query.pages[id].extract;
pushText2 = `著者:\n${wiki}`;
}}
//さらに画像も取得してくる
const res3 = await axios.get('https://ja.wikipedia.org/api/rest_v1/page/summary/'+ encodeURIComponent(auther));
if(res3.status === '404'){
pushText3 = 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Beethoven.jpg/266px-Beethoven.jpg';
}else{
const wiki_img = res3.data.thumbnail.source;
pushText3 = wiki_img;
}
} catch (error) {
pushText = '検索中にエラーが発生しました。ごめんね。';
// APIからエラーが返ってきたらターミナルに表示する
console.error(error);
}
// 「プッシュ」で後からユーザーに通知します
await client.pushMessage(event.source.userId, {
type: 'text',
text: pushText
});
await client.pushMessage(event.source.userId, {
type: 'image',
originalContentUrl: pushText3,
previewImageUrl: pushText3
});
return client.pushMessage(event.source.userId, {
type: 'text',
text: pushText2
});
} else {
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サーバーを実行中です…`);
##ソース解説
名言教えるよ!のサイトのAPI箇所
JSONとXMLで情報取得ができます。今回はJSONで取得。名言と著書を取得してます。
const res = await axios.get('https://meigen.doodlenote.net/api/json.php?c=1');
const meigen = res.data[0].meigen;
const auther = res.data[0].auther;
pushText = `本日の名言:\n${meigen}\n${auther}`;
wikiから著者のプロフィールと画像を取得してます。
データの構造がややこしくてデータとるときに苦労したところ
const res2 = await axios.get('https://ja.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro&explaintext&redirects=1&titles='+ encodeURIComponent(auther));
if(res2.data.query.pages === -1){
pushText2 = `著者:見つかりませんでした`;
}else{
for (let id in res2.data.query.pages){
const wiki = res2.data.query.pages[id].extract;
pushText2 = `著者:\n${wiki}`;
}}
const res3 = await axios.get('https://ja.wikipedia.org/api/rest_v1/page/summary/'+ encodeURIComponent(auther));
if(res3.status === '404'){
pushText3 = '';
}else{
const wiki_img = res3.data.thumbnail.source;
pushText3 = wiki_img;
}
##感想
初めてのLINEBot、実際に動かして試せるのは新鮮で楽しかったです。
開発していてつくづく感じるのは先人の皆さんの知恵とマメさですね。困ったら検索すれば大体出てくる、やろうとしていることがそのまま出てくる。というのは素人でも気楽には入れてすばらしいです。
それだけに技術力よりはアイデアや発信力が重視されているということなんだと実感しました。
映えもちゃんと意識しないとだめですね、今回の投稿は動画が地味すぎる&暗すぎました。最大の反省点と言わざるを得ない。