Slack hosting rental server

レンタルサーバーを使って自動応答するSlack bot(Slack app)を作ってみた

Slack hosting rental server

はじめまして、そうせいじと申します。普段は内部監査室のセキュリティ監査チームに所属しており、コードを書く最前線は15年前に引退してるの身ですが、2019年度も9月に実施されたお産合宿に参加してちょっとだけコードを書いてきました。

その際にSlackアプリを作ってみて、レンタルサーバーでも結構簡単にできてしまったのですが、レンタルサーバーでもこんな感じにやったら自動応答型のSlackのbotを作れるよーという情報がネット上に少なかったので、まとめて書いてみることにしました。

なぜレンタルサーバーか

ペパボは、ロリポップヘテムルというレンタルサーバーのサービスを提供している事業者だからです。皆、これ読んだらSlackbot作りたくなって借りてくれると良いなと思ってます!!!

事前準備

  • Slackでアプリを作成するワークスペースに参加します
  • ロリポップヘテムルなどに申し込んでプログラムを設置できるようにします。今回、プログラムはPHPで記載したものをサンプルで記載していきますが、言語はレンタルサーバー上で動く言語であれば何でも問題ありません。

SlackでAppを作成する

まずは、何はともあれSlack上でアプリを作成しましょう。作成手順は以下のとおりです。

  1. Slack apiのappsページにアクセスし「Create New App」ボタンを押す
    Crete New Appボタンを押す
  2. 「App Name」を入力し、作成するワークスペースを選択し「Create App」ボタンを押します。なお、App Nameは後から変更可能なので、仮の名前で先に進めても問題ありません。
    App NameとWorkspaceを設定する

イベントを受信するbotを作成する

先にアプリがイベントを受信するbotを作成してしまいます。

  1. 「Bots」をクリックしてOffからOnに変更する。
    Botsの設定
  2. botの名前とディスプレイ名はアプリと同じ名前にして問題ありません。また、一番下の「Always Show My Bot as Online」をOnにします。(※これをOnにしておかないと、RTMを利用しないので作ったbotはずっとオフラインのままになります)
    Botsの作成

イベントを受信するURLを設定する

  1. 右メニューから「Event Subscriptions」をクリックしてOffをOnに変更する。
    Event Subscriptionsの設定
  2. Slackからの通信を受け取るURLを「Request URL」の欄に入力して設定します。入力するURLは、レンタルサーバー上でPOSTを受け取るプログラムが動くURLを入力します。
    Request URLの設定
    入力すると、すぐにSlack側からPOSTされてきますが一旦はエラーになります。次の手順で、レンタルサーバー側にプログラムファイルを設置します。
  3. 今回の手順において、プログラム言語はPHPを使います。以下のようなプログラムを書いて上記の手順で入力したURLの場所に設置します。

     <?php
        
     $data = json_decode(file_get_contents("php://input"),true);
        
     if($data["type"] == "url_verification"){
       header('Content-Type: text/plain');
       echo $data["challenge"];
       exit;
     }
        
    
  4. Slack appの設定画面に戻り「Retry」ボタンを押してください。すると下記のようにチェックが通過するようになったと思います。
    Request URLのRetry
  5. そのままbotが受け取るイベントの設定をします。そのまま画面の下にある「Add Bot User Event」の下にある入力欄で「app_mention」と「message.im」を追加します
    Request URLのRetry
  6. 最後に右下にある「Save Changes」を押すと、SlackからのPOSTをプログラムで受け取れるようになりました。

作ったアプリをワークスペースにインストールする

POSTを受け取るには、Slack側でもう一つ手続きが必要です。

  1. 右サイドメニューから「Basic Information」を選択し、「Install your app to your workspace」の中にある「Install App to Workspace」のボタンを押す
    Request URLのRetry
  2. 手順に従って許可をしてください。特別なことは特に必要ありません。

自動応答部分のプログラムを書く

  1. まずは、slackからのPOSTであることを確認するコードを追加します。その際にSecret情報が必要ですので「Basic Information」を開いて「App Credentials」の中にある「Signing Secret」をコピーします。
    Request URLのRetry
  2. 続いてBot Userのtokenが必要ですので、「OAuth & Permissions」を開き、その中の「Bot User OAuth Access Token」の値をコピーします
    Request URLのRetry
  3. 上の方の手順で作成したプログラムに、slackからのPOSTであることを確認するコードと受信した後にオウム返しするコードを付け足します
     <?php
        
     //秘密情報の定義
     define("SLACK_SIGNING_SECRET"  ,"[上の手順でコピーした「Signing Secret」を貼り付ける]");
     define("SLACK_BOT_ACCESS_TOKEN","[上の手順でコピーした「Bot User OAuth Access Token」を貼り付ける]");
        
     $base_input = file_get_contents("php://input");
        
     //SlackからのRequestだけ受け付ける
     if(!verify_slack_request($base_input)){
       exit;
     }
        
     $data = json_decode($base_input,true);
        
     if($data["type"] == "url_verification"){
       header('Content-Type: text/plain');
       echo $data["challenge"];
       exit;
     }
        
     //event_callbackの場合に自動応答する
     if($data["type"] == "event_callback"){
       if(isset($data["event"]["subtype"]) && $data["event"]["subtype"] == "bot_message"){
         exit; // 自分自身(bot)のメッセージは処理しない
       }
        
       // 自動応答メッセージの送信
       $message=$data["event"]["text"];
       send_slack_message($message,$data["event"]["channel"]);
     }
        
        
     // slackからの通信であることを確認するコード
     // 参照 https://api.slack.com/docs/verifying-requests-from-slack
     function verify_slack_request($base_input)
     {
       //必要なヘッダーがない場合はfalse
       if(!isset($_SERVER["HTTP_X_SLACK_REQUEST_TIMESTAMP"]) || !isset($_SERVER["HTTP_X_SLACK_SIGNATURE"])){
         return false;
       }
        
       //5分以上はfalse
       $request_timestamp = $_SERVER['HTTP_X_SLACK_REQUEST_TIMESTAMP'];
       if(abs(time() - $request_timestamp) > 60 * 5){
         return false;
       }
        
       $sig_basestring = "v0:" . $request_timestamp . ":" . $base_input;
       $my_signature = "v0=" . hash_hmac( "sha256", $sig_basestring, SLACK_SIGNING_SECRET);
       $slack_signature = $_SERVER["HTTP_X_SLACK_SIGNATURE"];
        
       // (PHP 5 >= 5.6.0, PHP 7) であればこっちを利用
       //return hash_equals($my_signature,$slack_signature);
       return ($my_signature === $slack_signature);
     }
        
        
     // 送信部分はfunctionにしてると便利
     function send_slack_message($message,$channel)
     {
         $ch = curl_init("https://slack.com/api/chat.postMessage"); 
         $data = http_build_query([
             "token" =>  SLACK_BOT_ACCESS_TOKEN,
             "channel" => $channel, 
             "text" => $message, 
             "username" => "bot",
         ]);
         curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
         curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
         $result = curl_exec($ch);
         curl_close($ch);
         return $result;
     }
        
    
  4. 作ったbotにSlack上からメッセージを送ると、オウム返しで返答がきました
    Request URLのRetry

以上で、レンタルサーバー上に自動応答するbotプログラムを設置することができました。思ってたより簡単だなと感じてもらえたら幸いです!