🙄
LINEのイベントを複数のwebhookでリッスンしてみた
はじめに
自動返信機能付きのchatbotをチャネルトークなどのadminツールで管理したい!
LINE側ではwebhookを1つしか指定できないという都合上、直接複数のwebhookでLINEのイベントを受け取るのは不可能です。
しかし、LINEで指定したwebhookで受け取った情報をそのまま別のwebhookへと横流しするという方法を取ることで、擬似的に複数のwebhookでリッスンすることが可能になります。
データの流れは以下のとおりです
(ユーザーからのメッセージ)
↓
LINEサーバー
↓
webhook1(自動返信)
↓
webhook2(admin)
具体的な実装
まずはwebhook1で受け取った情報をwebhook2へ横流しするだけのコードを書いてみましょう。
Part1
import express from 'express';
import axios from 'axios';
import bodyParser from 'body-parser';
const app = express();
app.use(bodyParser.json());
app.post('/webhook', async (req, res) => {
const { method, url, headers, body } = req;
console.log({ method, url, headers, body });
try {
const { 'host': _, ...filteredHeaders } = headers
const axiosHeaders = {
...filteredHeaders,
'content-type': 'application/json charset=utf-8'
}
const response = await axios({
method: method,
url: 'https://example.com/webhook',
headers: axiosHeaders,
data: body,
});
console.log('Forwarded Data:', response.data);
console.log('HTTP Status Code:', response.status);
res.status(200).send('Data forwarded successfully');
}
catch (error) {
console.error('Error:', error);
res.status(500).send('Failed to forward data');
}
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
要するに、webhookで受け取ったリクエストを再現し、https://example.com/webhook に送っています。
node index.js
ngrok http 3000
で(ngrokのurl)/webhookをLINE側に指定してあげましょう。
これで、https://example.com/webhook にLINEからのイベントが送られるはずです。
Part2
自動返信などの機能を実装したい場合は以下のようにします。
...
async function handleEvent(event) {
// 自動返信などの処理
...
}
const app = express();
app.use(bodyParser.json());
app.post('/webhook', async (req, res) => {
const { method, url, headers, body } = req;
console.log({ method, url, headers, body });
try {
const { 'host': _, 'content-length': __, 'transfer-encoding': ___, ...filteredHeaders } = headers;
const axiosHeaders = { ...filteredHeaders, };
const response = await axios({
method: method,
url: 'https://example.com/webhook',
headers: axiosHeaders,
data: body,
});
console.log('Forwarded Data:', response.data);
console.log('HTTP Status Code:', response.status);
const result = await Promise.all(req.body.events.map(handleEvent));
res.json(result);
}
catch (error) {
console.error('Error:', error);
res.status(500).send('Failed to forward data');
}
});
handleEventの処理を追加しただけですね。
あとがき
実質的にLINE側で1つのwebhookしか指定できない問題は解決できました。
注意点として、今回の方法ではwebhookを介したものしか扱えないため、例えばbotからの自動返信の内容などはadminに表示されません。
Discussion