LoginSignup
1
0

More than 3 years have passed since last update.

micro.js(zeit)でAzure Bot serviceのチャットのリクエストを受け付ける

Posted at

Azure Bot Service + micro.jsでボットアプリ作成

Azure Bot Serviceを利用してbotアプリを作ってみました。
環境構築は慣れてなくても一瞬で完了します。
Azure Bot serviceをnode.jsで実装する際にサンプルがrestifyで実装されていましたが
micro.js(zeit)での実装に変更してみました。
環境は以下のようになります。

開発言語 :typescript v3.1.6
実行環境 :Node.js v8.9.4
アプリケーションフレームワーク :Asynchronous HTTP microservices zeit/micro
BOtフレームワーク :Azure Bot Framework | Microsoft Azure

環境構築(Azure側)

Azure bot frameworkで検索すると以下のサイトに行きつきこれを手掛かりに
Azure Bot serviceに足を踏み入れることにしました。

Art237.jpg

Azure Bot Framework | Microsoft Azure

まずは環境を整えるためFrameworkを入手するところから始めようと思いましたが
上記URLにモノを落とすようなURLがない。
他にこのページでやることがないようなので
MyBot → createでBot アプリケーションを作成してみる。

Art240.jpg

Azureにサインインします。
Art238.jpg

そして結局portalへ飛ばされます。
Art239.jpg

今回はfunctionsでなくweb appを選択。
Art241.jpg

app serviceが作成されます。
設定→メッセージングエンドポイントで受け付けるURLを設定
Art244.jpg

今回は
https://xxxxxxxxxxx.azurewebsites.net/api/messages
としました。

サンプルのソースコードを入手します。
Microsoft/BotBuilder-Samples

必要なモジュールのインストール

入手したpackage.jsonを以下のように編集しnpm installを実行

package.json

{
  "name": "natural-bot",
  "version": "1.0.0",
  "description": "",
  "main": "./dist/index.js",

  "dependencies": {
    "@types/micro": "^7.3.3",
    "botbuilder": "^4.2.0",
    "botframework-config": "^4.2.0",
    "config": "^1.31.0",
    "dotenv": "^6.1.0",
    "js-yaml": "^3.8.4",
    "micro": "^9.3.3",
    "micro-http-router": "^1.3.0"
  },
  "devDependencies": {
    "@types/dotenv": "6.1.0",
    "@types/micro": "7.3.3",
    "nodemon": "^1.18.6",
    "tslint": "^5.11.0",
    "typescript": "^3.1.6"
  }
}


ソースを編集してデプロイ

サンプルはrestifyで実装されているためmicroに入れ替えます。
tsconfig.json,echobot.botは変更点なしでそのまま流用します。
今回は取り合えず動けば良しとします(編集中)

index.ts

microを導入します。ルーティングはmicro-http-routerを利用して以下のRouter.tsにて実装しました。


const micro = require('micro')
const server = micro(async (req:any, res:any) => {
        // リクエスト受付(各ルーティング実行)
        let router:any
        let Router = require('./gateway/Router')
        router = await Router(req,res)
        return await router.handle(req, res);
})
server.listen(process.env.port || process.env.PORT || 3978, () => {
    console.log(`\n${server.name} listening to ${server.url}`);
    console.log(`\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator`);
    console.log(`\nTo talk to your bot, open echobot.bot file in the Emulator.`);
});


gateway/Router.ts


const Router = require('micro-http-router')
import { config } from 'dotenv';
import * as path from 'path';
import { BotConfiguration, IEndpointService } from 'botframework-config';
import { BotFrameworkAdapter } from 'botbuilder';
import { MyBot } from '../bot';

const ENV_FILE = path.join(__dirname, '../..', '.env');
config({ path: ENV_FILE });
const BOT_CONFIGURATION = (process.env.NODE_ENV || DEV_ENVIRONMENT);

module.exports = async (req:any, res:any) => {

    const router = new Router()
    // bot設定ファイルの読み込(サンプルではプロジェクトルートのechobot.botが読み込まれます。)
    // パスは上記.envファイル内で指定 
    const BOT_FILE = path.join(__dirname, '../..', (process.env.botFilePath || ''));
    let botConfig;
    try {
        botConfig = BotConfiguration.loadSync(BOT_FILE, process.env.botFileSecret);
        const endpointConfig = botConfig.findServiceByNameOrId(BOT_CONFIGURATION) as IEndpointService;
        const adapter = new BotFrameworkAdapter({
            appId: endpointConfig.appId || process.env.microsoftAppID,
            appPassword: endpointConfig.appPassword || process.env.microsoftAppPassword,
        });

        // on error
        adapter.onTurnError = async (context, error) => {
            console.error(`\n [onTurnError]: ${ error }`);
            await context.sendActivity(`Oops. Something went wrong!`);
        };

        // app service の『設定』で指定したエンドポイント
        router.post('/api/messages', (req:any, res:any) => {
            adapter.processActivity(req, res, async (context) => {
                // Route to main dialog.
                let myBot = new MyBot();
                await myBot.onTurn(context);
            });
        });
    } catch (err) {
        console.error(`\nError reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.`);
        console.error(`\n - The botFileSecret is available under appsettings for your Azure Bot Service bot.`);
        console.error(`\n - If you are running this bot locally, consider adding a .env file with botFilePath and botFileSecret.\n\n`);
        process.exit();
    }
    return router;
};

bot.ts

適当な返事をしてくれるメソッドを用意。util.jsは以下を使用。
eustia - A Tool for Generating JavaScript Utility Libraries:

turnContext.activity.textが受信されたテキストメッセージを保持、
turnContext.sendActivity()でテキストメッセージの送信が可能です。


import {
    ActivityTypes,
    TurnContext
} from 'botbuilder';
const natural = require('natural');
let util = require("./util/Util.js");

export class MyBot {
    /**
     * Use onTurn to handle an incoming activity
     *
     * @param {TurnContext} context on turn context object.
     */
    async onTurn(turnContext: TurnContext) {
        if (turnContext.activity.type === ActivityTypes.Message) {
            let message = turnContext.activity.text
            // 結果の返却
            await turnContext.sendActivity(`${  this.greet(message)}`);
        } else {
            Generic handler for all other activity types.
            await turnContext.sendActivity(`[${ turnContext.activity.type } event detected]`);
        }
    }

    greet(text:string):string{

        const goodMorning = "おはようございます、"
        const hello = "こんにちは、"
        const goodEveinning = "こんばんは、"

        if(util.isStr(text)){
            if(text.indexOf("おはよう") > -1){
                return goodMorning
            }else if(text.indexOf("こんにちは") > -1){
                return hello
            }else if(text.indexOf("こんちは") > -1){
                return hello
            }else if(text.indexOf("こんばんは") > -1){            
                return goodEveinning
            }
        }
        return ""
    }
}

あとはgit等でデプロイします。
デフォルトでsdk等が大量に用意されていて若干戸惑いますが、デプロイは通常のApp Serviceと同様になります。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0