この記事の内容
- LINEボットの完成形、常時稼働化のやり方
- そもそもモヤついていたところを自分なりにまとめてみた
完成品
(いじってたらなぜかアイコンが黒く怪しくなってしまった・・・どうやって戻すんだろう)
猿よりは賢いアプリを作った。(ただし、人間ほど完璧な回答はできない。)
- ?を付けて聞くと文章で返します
- ?がない時はwikipediaのリンクを返します
- お猿さんが知らない単語のときは、、無視します。。
QRコード(お友達になってあげてね!)
作っていて思ったこと・・・
そもそもexpress
,ngrok
,now
,heroku
ってそれぞれなんだろう。普通のサーバーと何が違うのだろう。
この辺りがモヤつくポイントだと思うので、自分なりの理解でまとめます。
さくらサーバー(phpを使う)
以前、レンタルサーバーにphpファイルを置いて、そこでwebhookを受けて処理をするように作り替えた。
常に動くLINEBOTにお引っ越し(レンタルサーバ+PHP編)
Express
Node.jsで利用できるwebアプリケーションフレームワーク。
const express = require('express');
const app = express();
requireでExpressを利用可能にし、expressのアプリケーションオブジェクトをappに格納する。
そうすることで、app.post()
postリクエスト時の処理や、app.listen()
サーバー起動などの処理が簡単に記述できる。
Expressでローカル環境にアプリケーションを構築することができるが、ローカル環境は基本的に外部に公開しないのでLINEbotからの外部とのやりとりができない。
ngrok
Expressを用いて作った手元のlocalhostにグローバルからアクセスできるようにするトンネリングツール。
設定等はこちらを参照。
ngrokのサブドメインを取得して、その/webhookに対してアクセスすることでngrokを通して、
app.post('/webhook', line.middleware(config), (req, res) => {....}
の処理を呼ぶことができる。
ただし、PCを閉じてしまうとこのngrokサーバも終了してしまい、常時動かすには不便。
now
とてもデプロイが簡単なPaas。
サーバにアクセスされるとnow.jsonの設定の通り処理が実行される。
設定等はこちらを参照。
Heroku
Paas。Gitを使ってデプロイする必要がある。
今回公開しているアプリはHerokuを使っています。なので手順を下記に記載する。
初期化
npm init -y
必要なライブラリインストール
npm i body-parser express
.gitignore
ファイルの作成
# Dependency directories
node_modules/
# Optional npm cache directory
.npm
1番上の階層にProcfile
の作成
web: node index.js
git
初期化
git init
herokuアプリを追加する。アプリケーションネームはお好きな名前を決める。
heroku create アプリケーションネーム
add -> commit -> pushをする
git add --a
git commit -m "commit"
git push heroku master
Nowで常時化
Nowを使って常時動くようにします。先述の通りNowはGitも不要で非常に簡単です。
準備
下記にあるようにngrokで動いていたモノが、nowでは正しい挙動をしない時があったので、前回記事から少し修正をした。
LINE BOTで天気を返すサンプルがngrokで動いてnowで動かない件
コード
'use strict';
const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;
// 追加
const axios = require('axios');
const config = {
channelSecret: 'XXXXXXXXXXX',
channelAccessToken: 'XXXXXXXXXXX'
};
const app = express();
app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない)
app.post('/webhook', line.middleware(config), (req, res) => {
// LINE上で入力された
console.log(req.body.events[0].message.text);
//ここのif文はdeveloper consoleの"接続確認"用なので後で削除して問題ないです。
if(req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff'){
res.send('Hello LINE BOT!(POST)');
console.log('疎通確認用');
return;
}
Promise
.all(req.body.events.map(handleEvent))
.then((result) => res.json(result));
});
const client = new line.Client(config);
async function handleEvent(event) {
if (event.type !== 'message' || event.message.type !== 'text') {
return Promise.resolve(null);
}
let mes = ''
// console.log(event.message.text);
if(event.message.text.indexOf('?') > -1){
// ?を含んでいる場合にはwikiで検索したものを出して、含んでない場合はurlを返す
var str = event.message.text;
var result = str.split( '?' ).join( '' ); //?を取り除く処理
mes = result + 'の説明:'; //wikiのbodyの前の一言
await client.replyMessage(event.replyToken, {
type: 'text',
// text: event.message.text //実際に返信の言葉を入れる箇所
text : mes
});
// このreturnはポイント
return getBody(event.source.userId,result,mes); //wiki APIで取得できたらプッシュメッセージ
}else{
var result = event.message.text;
mes = result + 'のURL:'; //wikiのurlの前の一言
await client.replyMessage(event.replyToken, {
type: 'text',
// text: event.message.text //実際に返信の言葉を入れる箇所
text : mes
});
// このreturnはポイント
return getUrl(event.source.userId,result); //wiki APIで取得できたらプッシュメッセージ
}
}
const getBody = async (userId,word,message) => {
const res = await axios.get('http://wikipedia.simpleapi.net/api?keyword='+ encodeURIComponent(word) + '&output=json');
const item = res.data;
console.log(item);
await client.pushMessage(userId, {
type: 'text',
text: item[0].body,
});
}
const getUrl = async (userId,word) => {
const res = await axios.get('http://wikipedia.simpleapi.net/api?keyword='+ encodeURIComponent(word) + '&output=json');
const item = res.data;
// console.log(item);
await client.pushMessage(userId, {
type: 'text',
text: item[0].url,
});
}
(process.env.NOW_REGION) ? module.exports = app : app.listen(PORT);
console.log(`Server running at ${PORT}`);
Herokuで常時化
Herokuとは
ソースコード
'use strict';
const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;
// 追加
const axios = require('axios');
const config = {
channelSecret: 'XXXXXXXX',
channelAccessToken: 'XXXXXXXX'
};
const app = express();
app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない)
app.post('/webhook', line.middleware(config), (req, res) => {
//ここのif文はdeveloper consoleの"接続確認"用なので後で削除して問題ないです。
if(req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff'){
res.send('Hello LINE BOT!(POST)');
console.log('疎通確認用');
return;
}
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 = ''
// console.log(event.message.text);
if(event.message.text.indexOf('?') > -1){
// ?を含んでいる場合にはwikiで検索したものを出して、含んでない場合はurlを返す
var str = event.message.text;
var result = str.split( '?' ).join( '' ); //?を取り除く処理
mes = result + 'の説明:'; //wikiのbodyの前の一言
getBody(event.source.userId,result); //wiki APIで取得できたらプッシュメッセージ
}else{
var result = event.message.text;
mes = result + 'のURL:'; //wikiのurlの前の一言
getUrl(event.source.userId,result); //wiki APIで取得できたらプッシュメッセージ
}
return client.replyMessage(event.replyToken, {
type: 'text',
text : mes
});
}
const getBody = async (userId,word) => {
const res = await axios.get('http://wikipedia.simpleapi.net/api?keyword='+ encodeURIComponent(word) + '&output=json');
const item = res.data;
// console.log(item);
await client.pushMessage(userId, {
type: 'text',
text: item[0].body,
});
}
const getUrl = async (userId,word) => {
const res = await axios.get('http://wikipedia.simpleapi.net/api?keyword='+ encodeURIComponent(word) + '&output=json');
const item = res.data;
// console.log(item);
await client.pushMessage(userId, {
type: 'text',
text: item[0].url,
});
}
app.listen(process.env.PORT || 8080);
// console.log(`Server running at ${PORT}`);
どんどん試そう
レンタルサーバを除いて、無料なのでお好きややり方でどんどん試していきましょう!