Nest.jsでLineBotを作る
こんにちは、naoです。
最近業務でNest.jsを触る機会があったので、アウトプットがてら、Nest.jsでLineBotを作ろうと思います。
Node.jsで作る例は見たことありますが、Nest.jsはあまりないので参考になればと思います。
環境構築
nest/cliをインストールしていない方はグローバルにインストールしましょう。
npm i -g @nestjs/cli
nest new project-name
package managerを聞かれるので自分が使いやすいやつを選択しましょう。
以下のコマンドでサーバを立ち上げてlocalhost:3000でHello Worldが表示されればOKです。
npm run start:dev
Line設定
次にLineのコンソール上でプロダクトを作る必要があります。
まずはログインをしましょう。
次にプロバイダーを作成します。名前は好きなやつでOKです。
次に新しいチャンネルを作成します。タイプはMessaging APIを選択してください。
必要の情報等記入して作成しましょう。
作成できたら、「チャネル基本設定->チャネルシークレット」「Messaging API設定->チャネルアクセストークン」をルートディレクトリの.envに保存してください。
service module controller作成
ここからは実際にコードを書いていきましょう。
ターミナルを開いて以下のコマンドでservice module controlerを作成します。
おうむ返しBotを作っていきます。
nest g mo line
nest g co line
nest g s line
nest g mo line/config
次に今回必要なライブラリをインストールしていきます。
npm install @nestjs/config @line/bot-sdk
次にClientを作成します
import { messagingApi } from '@line/bot-sdk';
import { Injectable } from '@nestjs/common';
import type { ClientConfig } from '@line/bot-sdk';
@Injectable()
export class ConfigService {
createLinebotClient() {
const clientConfig: ClientConfig = {
channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
channelSecret: process.env.CHANNEL_SECRET,
};
return new messagingApi.MessagingApiClient(clientConfig);
}
}
@line/bot-sdk: これはLINE Messaging APIを利用するためのNode.jsのSDKです。このSDKを使用することで、LINEプラットフォーム上でメッセージを送受信したり、ユーザーと対話するための機能を組み込むことができます。
次はserviceの中身を記述します。
// LineService
import { Injectable } from '@nestjs/common';
import { WebhookEvent, WebhookRequestBody } from '@line/bot-sdk';
import { ConfigService as NestConfigService } from './config/config.service';
@Injectable()
export class LineService {
constructor(private configService: NestConfigService) {}
async handleWebhook(req: WebhookRequestBody): Promise<void> {
const client = this.configService.createLinebotClient();
const events: WebhookEvent[] = req.events;
events.forEach((event) => {
if (event.type === 'message') {
const returnMessage =
event.message.type === 'text'
? event.message.text
: 'No Text';
client.replyMessage({
replyToken: event.replyToken,
messages: [
{
type: 'text',
text: returnMessage,
},
],
});
}
});
}
}
@line/bot-sdkからWebhookEvent, WebhookRequestBodyをインポート: LINE Messaging APIのWebhookイベントの処理に必要な型定義を提供します。
このサービスは基本的に、LINEからのWebhookリクエストを受け取り、それがテキストメッセージであればその内容を返信し、そうでなければ特定の応答を返すという機能を持っています。これにより、ユーザーがLINEプラットフォーム上で送信したメッセージに対して自動的に応答することができます。
次にControllerからhandleWebhookを呼び出しましょう。
import { messagingApi } from '@line/bot-sdk';
import { Injectable } from '@nestjs/common';
import type { ClientConfig } from '@line/bot-sdk';
@Injectable()
export class ConfigService {
createLinebotClient() {
const clientConfig: ClientConfig = {
channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
channelSecret: process.env.CHANNEL_SECRET,
};
return new messagingApi.MessagingApiClient(clientConfig);
}
}
@line/bot-sdk: これはLINE Messaging APIを利用するためのNode.jsのSDKです。このSDKを使用することで、LINEプラットフォーム上でメッセージを送受信したり、ユーザーと対話するための機能を組み込むことができます。
次はserviceの中身を記述します。
import { WebhookRequestBody } from '@line/bot-sdk';
import { Body, Controller, Post } from '@nestjs/common';
import { LineService } from './line.service';
@Controller('line')
export class LineController {
constructor(private lineService: LineService) {}
@Post()
async handler(@Body() req: WebhookRequestBody) {
return this.lineService.handleWebhook(req);
}
}
最後にapp.module.tsを以下のようにして外部から呼び出せるようにします。
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LineModule } from './line/line.module';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
LineModule,
ConfigModule.forRoot({
envFilePath: ['.env'],
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
動作確認
ローカル環境では動作させることができないのでngrokを使用しました。
ngrok http 3000でローカル環境繋げましょう。発行されたURLをLINE Developersに登録します。
「Messaging API設定->Webhook URL->https://ngrokURL/line」
検証を押して「成功」と返ってくればOK。またLINE公式アカウント機能の応答メッセージを無効にしましょう。
スマホからQRコードを立ち上げておうむ返しができれば完了です!
まとめ
今回はNest.jsとLINE Messaging APIを連携させるところまで解説しました。
chatgptと連携させればもっと面白いのができると思うのでもう少し作り込んでみようと思います!
Discussion