我水也

われみずなり

Azure Functionsでお手軽Slack Bot

このエントリは Microsoft Azure Advent Calendar 2017 - Qiita の17日目です。

登録した後に気付きましたが、2年連続17日目のエントリでした。

matcu.hatenablog.com

今回はタイトルの通りAzure Functionsを使って、Slack Botを作成してみたので、一通り作り方などを紹介したいと思います。

お手軽チャットボットはいかがですか?

Mac上でVSCodeを使って開発します。
VSCode便利になりましたねー

ちなみにVSCodeのAdvent Calendarはこちらです。

Azure関連だとMicrosoft Azure Tech Advent Calendar 2017もおすすめです。

今回の環境はこんな感じです。

  • Visual Studio Code (1.18.1)
  • (VSC拡張)Azure Account and Sign-In
  • (VSC拡張)Azure Functions for Visual Studio Code (Preview)
  • .NET Core 2.0(2.0.2)
  • Azure Core Function Tools 2.0(2.0.1-beta.21)
  • Node v8.5.0

Bot作成までの流れ

  • VSCodeでの作業
    • VSCodeにFunctionsを作成するアカウントでサインイン
    • Functions Appを作成
    • Functionを作成
    • デプロイ
  • Slackでの作業
    • 自分のアプリを作成&設定
    • 必要な情報を収集
  • VSCodeでの作業
    • Functionを修正
    • デプロイ

VSCodeにFunctionsを作成するアカウントでサインイン

諸々の環境を整備したVSCodeにAzureアカウントでサインインします。 コマンドパレットを開き(Shift + Command + P)「azure」と入力し、「Azure: Sign In」を選択します。

f:id:matcu:20171216125810p:plain

URLとcodeが表示されるので、「Copy & Open」を選択します。

f:id:matcu:20171216130855p:plain

ブラウザでcodeを入力し、アカウントを選択します。 成功するとVSCodeのステータスバーにアカウントが表示されます。

f:id:matcu:20171216130659p:plain

Functions Appを作成

コマンドパレットを開き「func」と入力し、「Azure Functions: Create New Project」を選択します。

f:id:matcu:20171216131600p:plain

プロジェクトディレクトリを選択すると、言語の選択になるので、「Javascript」を選択します。

f:id:matcu:20171216131651p:plain

Functionを作成

コマンドパレットを開き「func」と入力し、「Azure Functions: Create Function」を選択します。

f:id:matcu:20171216131704p:plain

プロジェクトのディレクトリを選択します。

f:id:matcu:20171216132008p:plain

言語選択ができますので、「Select Language」を選択し、今回は「Javascript」を選択します。

f:id:matcu:20171216132110p:plain

まだPreviewですが、増えましたねー

f:id:matcu:20171216132113p:plain

次にランタイムの選択で「Select Runtime」を選択し、今回は「~1」を選択します。
ランタイムについては、ここに説明があります。

f:id:matcu:20171216132122p:plain

f:id:matcu:20171216132128p:plain

続いて作成するFunctionのトリガーを選択します。
今回はSlackからのHTTPリクエストをトリガーとするので、「HTTP trigger」を選択します。

f:id:matcu:20171216132134p:plain

関数名は「SlackBot」と安易な名前にしておきます。

f:id:matcu:20171216132137p:plain

最後に認証レベルを「Function」に設定します。

f:id:matcu:20171216132147p:plain

これでFunctionができました。

デプロイ

ひとまずFunctionができたので、デプロイしてみましょう。

コマンドパレットを開き「func」と入力し、「Azure Functions: Deploy to Function App」を選択します。

f:id:matcu:20171216134143p:plain

デプロイする対象のディレクトリを選択します。

f:id:matcu:20171216134147p:plain

サブスクリプションを選択します。

f:id:matcu:20171216134151p:plain

まだAzure上にはFunctionAppがないので、新規で作成します。

f:id:matcu:20171216134156p:plain

適当に「advent2017-slackbot」という名前にします。
注意書きにあるようにこの名前がURLの一部となりますので、一意な名前にする必要があります。

f:id:matcu:20171216134203p:plain

リソースグループを選択します。なければここで作成します。

f:id:matcu:20171216134206p:plain

ストレージアカウントを選択します。
既存のものでもいいですし、新規作成でもOKです。ここでは新規作成します。

f:id:matcu:20171216134210p:plain

f:id:matcu:20171216134217p:plain

本当にデプロイしていいですか?「Yes」

f:id:matcu:20171216134220p:plain

↓↓VSCodeのOutputコンソールの表示↓↓

Using Subscription "Microsoft Azure (12345678-1234-1234-1234-123456789012)".
Using resource group "advent2017 (japaneast)".
Creating new storage account "advent2017slackbot (japaneast, Standard_LRS)"...
Created storage account "advent2017slackbot (japaneast, Standard_LRS)".
Creating new Function App "advent2017-slackbot"...
>>>>>> Created new Function App "advent2017-slackbot": https://advent2017-slackbot.azurewebsites.net <<<<<<

11:13:00 AM advent2017-slackbot: Creating zip package...
11:13:00 AM advent2017-slackbot: Starting deployment...
11:13:10 AM advent2017-slackbot: Generating deployment script.
11:13:17 AM advent2017-slackbot: Running post deployment command(s)...
>>>>>> Deployment to "advent2017-slackbot" completed. <<<<<<

ということで、デプロイ完了です!
ポータル上で動かしてみましょう。

デプロイされたFunctionを選択すると、右端に「Test」というタブがあるので、クリックします。

f:id:matcu:20171216135242p:plain

Functionへリクエスト出来ますので、「Request Body」に以下のJSONを入力し、「Run」をクリックします。

{
    "name":"Microsoft Azure Advent Calendar 2017"
}

f:id:matcu:20171216135348p:plain

Outputに「Hello Microsoft Azure Advent Calendar 2017」が表示されればデプロイOKです!

Slackと連携出来るようにする

Slackへ投稿するためにHTTPリクエストをするので、npmでsuperagentをいれます。
npm initを実行したら、npmでsuperagentをいれます。

$ npm init
$ npm install superagent --save
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN slackbot@1.0.0 No description
npm WARN slackbot@1.0.0 No repository field.

+ superagent@3.8.2
added 24 packages in 3.486s

Slackからの認証要求に答えれるように、index.jsを以下のようにします。
ちゃんとしたレスポンスが出来ればOKですので、ここでは私の手抜き例です。

var request = require('superagent');

module.exports = function (context, req) {
    var body_type = req.body.type;
    if(body_type == 'url_verification'){
        var body_challenge = req.body.challenge;
        context.res = {
            body: body_challenge
        };
    } else if(body_type == 'event_callback'){
        // あとで実装
    } else {
        context.res = {
            status: 400,
            body: "Bad Request. Please check your request parameters."
        };
    }
    context.done();
};

ここまでできたら、再度Azure上へデプロイしておきます。
さて、もう少しです。ここからはSlack側の設定をします。

自分のアプリを作成&設定

Slack API: Applications | Slack へ接続します。

「Create New App」を選択します。

f:id:matcu:20171216140425p:plain

任意の名前を入力し、Botを入れるSlackのワークスペースを選択します。

f:id:matcu:20171216140437p:plain

「Basic Information」が表示されますので、「Bots」を選択します。

f:id:matcu:20171216140611p:plain

画面が切り替わりますので「Add a Bot User」を選択し、Botユーザーを作成します。

f:id:matcu:20171216140848p:plain

「Basic Information」の「Install your app to your workspace」を展開し、「Install App to Workspace」をクリックします。

f:id:matcu:20171216144724p:plain

自分のワークスペースBotを追加しても良いか聞かれますので、Authorizeします。

f:id:matcu:20171216144917p:plain

作成できたらメニューの「Event Subscriptions」を選択します。

f:id:matcu:20171216140957p:plain

「Request URL」に先程作成したFunctionのURLを入力します。
FunctionのURLがわからない場合は、VSCodeからも確認できます。
VSCode左側エクスプローラーの「AZURE FUNCTIONS」から作成したFunctionを右クリックし、「Copy Function Url」でコピーできます。

f:id:matcu:20171216141204p:plain

Request URLがVerifiedになればOKです。

f:id:matcu:20171216141617p:plain

続いて、画面下の「Subscribe to Bot Events」で「message.channels」を選択します。

f:id:matcu:20171216141824p:plain

続いてメニューから「OAuth & Permissions」を選択し、「Bot User OAuth Access Token」の値をメモっておきます。

f:id:matcu:20171216144329p:plain

ここまででSlack側の設定は完了です!

あとは好きなチャンネルにBotを追加して、Functionの中身を更新すればチャットボットの完成です。

今回は単にオウム返しをするBotを作ってみます。

Functionを修正

先程デプロイしたindex.jsの「// あとで実装」とコメントアウトしていた部分を以下に書き換えます。
BOTユーザ名>2箇所、<Bot User OAuth Access Token>1箇所は自分の環境に合わせます。

    } else if(body_type == 'event_callback'){
// ここから
        var event = req.body.event;
        
        // Bot以外の発言を対象にしないと、無限ループに陥る
        if(event.type == 'message' && event.username != '<BOTユーザ名>'){
            var own = req.body.authed_users[0]; // BotのユーザーID

            // メンション部分を抜いたメッセージ
            var original_text = event.text.replace('<@' + own + '> ', '');
            
            // Bot宛のメンションの場合のみ反応
            if(event.text.indexOf('<@' + own + '>') != -1){
                request
                .post("https://slack.com/api/chat.postMessage")
                .field('token', "<Bot User OAuth Access Token>")
                .field('channel', event.channel)
                .field('text', original_text)
                .field('Username', '<BOTユーザ名>')
                .end(function(res){
                    context.done();
                });            
            }
        }
// ここまで
    } else {

修正したら、再度Azure上へデプロイします。

SlackでBotに話しかけてみる

Botを追加したチャンネルで話かけてみると・・・

f:id:matcu:20171216145808p:plain

ちゃんとオウム返ししてくれました!

あとは好きなようにFunctionを触れば、面白いボットも作れますね!

まとめ

  • 手順は多そうに見えるが、お手軽にボットが実装できます。

  • VSCode拡張機能は便利。

  • (重要!)実際はコード中に設定情報等を入れない。

    • 今回は簡単な説明のため省きましたが、Bot User OAuth Access Tokenなどは基本的にコード中には書かず、Application Settingsへ設定情報として外出しします。f:id:matcu:20171216150309p:plain
    • Application Settingsへ登録した情報は process.env.SlackPostToken といった感じでコード中から利用できますので。ぜひ、こちらを利用してください。
  • あとは実装次第。

    • StorageやCosmosDBなど他のAzureサービスとの連携が簡単なので、ぜひ使ってみてほしい。

他のサービスと組み合わせてみる

人工知能チャットボット (chatbot) - ユーザーローカルのチャットボット (chatbot) 開発サービス

こういったサービスを組み込むと会話っぽくできます。

f:id:matcu:20171216151240p:plain

QnA Maker API | Microsoft AzureCognitive Services | Microsoft Azureを自分なりに使ってみるのもおもしろいと思います。

Azure Functionsで素敵なチャットボットライフを。

Appendix