以前、Clouflare wokersにhonoでLINE Botを作成する記事を作成しました
その末尾にあとはよしなになんかと繋げて使ってください!というメッセージを残したのですが、流石に投げっぱなしは忍びないと思いまして、
- ノーコードツール、makeでwebhookを作る
- cloudflare workersからそのwebhookにリクエストを送る
- 結果をBotのメッセージとして返す
というところを実際に実装してみたいと思います。
0. 準備
0.1. makeのアカウント登録
そもそもmakeとは、ノーコードでアプリケーションを繋ぎ合わせることができるサービスです。
いわゆるiPaaS(integration Platform as a Service) に該当し、さまざまなサービスやアプリケーションを繋ぎ合わせることで、独自のアプリケーションを構築することができます。
こちらからGoogleなどのソーシャルログインで問題ありませんので登録しておいてください。
0.2. makeでGPTと会話できるLINE Botの作成
少々古いですが、こちらの3-3までを実施いただけると、本記事の意味合いがわかりやすいかと思います
0.3. Cloudflare workers上で動作するecho botの作成
この記事の続きですので、おうむ返しBotができているものとします。
1. ハンズオン
1.0. 全体を通して作るもの
今回はCloudflare
からmake
にリクエストを送り、makeの中で具体的なロジックを実行(サンプル例はGPTのAPIです)。再度Cloudflareに返して、結果を返答するLINE Botを作成します。
そのために、make側の準備を整えたのち
、Cloudflare側のコードを書き換え
、つなぎこむ
、という手順で進めます
1.1. makeのLINE Botをwebhook経由のAPIに切り替える
まずは0.2
で作成したLINE Botについて、これをAPIに切り替えることでCloudflareと繋げる準備をします。
1.1.1. 両端のLINE モジュールを削除して、webhook モジュールに切り替える
- 今、こんな感じだと思いますので、両側のLINEモジュールを削除します
- 削除したら、Webhooksのモジュールを選んでください
- 選ぶのはCustom webhookです
-
Create a webhook
のボタンを押します
- わかりやすい名前をつけて、
save
ボタンを押してください
- こんな感じの待機画面になったらひとまずOKです
- 一旦
stop
を押して止めてください
- 末尾に同様のwebhooksモジュール(webhook response)を作ったら完成です
1.1.2. 補足|さっきの待機画面が気になる方向け
詳細は折りたたみで表示、読み飛ばして問題ないです
先ほどは、webからのリクエストを待機していました。
表示されていたwebhook URLに対して、実際のリクエストを送ることで、データ構造を定義して、makeの中で使えるようにしてくれます。
なので、このあとcloudflare側の準備を整えて、繋ぎ込んでいきます。
1.2. Cloudflareとmakeと繋ぐ
それでは、makeとCloudflareを繋いでいきます。まずは、Cloudflare側で作成したLINE Botを触っていきます。」
1.2.1. Cloudflareのコードを書き換える
次のコードをindex.ts
の中に貼り付けます(前回記事の通り実施している前提です)。
import {
messagingApi,
webhook,
} from '@line/bot-sdk'
import { ExecutionContext, Hono } from 'hono'
import HmacSHA256 from "crypto-js/hmac-sha256";
import Base64 from "crypto-js/enc-base64";
type Bindings = {
CHANNEL_ACCESS_TOKEN: string,
CHANNEL_SECRET: string,
WEBHOOK_URL: string,
}
const app = new Hono<{ Bindings: Bindings }>()
app.get('/', (c) => {
return c.text('Hello hono & line!')
})
app.post('/webhook', async (c) => {
const body = await c.req.text() // JSONではなくテキストで取得
const channelAccessToken = c.env.CHANNEL_ACCESS_TOKEN || ''
const channelSecret = c.env.CHANNEL_SECRET || ''
const webhookURL = c.env.WEBHOOK_URL || ''
// シグネチャの取得
const signature = c.req.header('x-line-signature')
if (!signature) {
return c.text('Missing signature', 400)
}
// HMACを使ってシグネチャを生成
const hash = await generateHmac(channelSecret, body);
// シグネチャの検証
if (signature !== hash) {
return c.text('Invalid signature', 403)
}
const events = JSON.parse(body).events
const promises = events.map((event: webhook.Event) => handleEvent(event, channelAccessToken, webhookURL, c.executionCtx))
await Promise.all(promises)
return c.text('OK')
})
const handleEvent = async (
event: webhook.Event,
accessToken: string,
webhookURL: string,
ctx: ExecutionContext
) => {
if (event.type !== 'message' || event.message.type !== 'text') return;
try {
fetch('https://api.line.me/v2/bot/chat/loading/start', {
method: 'POST',
headers: {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json"
},
body: JSON.stringify({"chatId": event.source?.userId})
})
ctx.waitUntil(
(async () => {
const res = await fetch(webhookURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(event)
})
const text = await res.text();
if(!event.replyToken) return
const responseBody: messagingApi.ReplyMessageRequest = {
replyToken: event.replyToken,
messages: [
{'type': 'text', 'text': text}
]
}
return fetch('https://api.line.me/v2/bot/message/reply', {
method: 'POST',
headers: {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json"
},
body: JSON.stringify(responseBody)
})
})()
)
} catch (error) {
console.error(error);
}
}
export default app
const generateHmac = async (secret: string, message: string) => {
const hmac = HmacSHA256(message, secret);
return Base64.stringify(hmac);
}
1.2.2. 環境変数の設定
環境変数として、makeのwebhook URLを設定し、Cloudflare側からリクエストを送れるようにします。
- 次のコマンドをターミナルに入力してください
bunx wrangler secret put WEBHOOK_URL
- 次のようにコピペしてくれと言われます
- make側に戻り、
Redetermine data structure
ボタンを押します
-
Copy address to clipboard
ボタンを押して、URLをコピーします
- コピーしたコードをコピペしてenter
- 成功したら、画面のようになります
- 次のコマンドを入力してデプロイ
bun run deploy
1.2.3. webhookにリクエストを送る
- なんでも良いので、LINEからメッセージを送ってみます
- うまくいくと、LINEに
Accepted
と表示されます
- またモジュール側にも
Successfuly determined
と表示されます
1.2.4. OpenAIのモジュールにwebhookの値を入れる
- 先ほどの手順で、OpenAIのモジュールにデータ構造が定義されています
- text contentにwebhooks経由できた値を入れます
- webhooksのBodyにOpenAIから返ってきた値を入れます
1.2.5. 補足|コードの変更点
詳細は折りたたみで表示、読み飛ばして問題ないです
先ほどは、webからのリクエストを待機していました。
表示されていたwebhook URLに対して、実際のリクエストを送ることで、データ構造を定義して、makeの中で使えるようにしてくれます。
なので、このあとcloudflare側の準備を整えて、繋ぎ込んでいきます。
1.3. 実行してみる
- Run onceを押してみます
- LINE からメッセージを送ってみましょう
まあはやいかな
2. 動作しているところ
動作の肝はこれですね
honoのExecutionContextにあるwaitUntilがポイントです