SlackのSlash Commandで既存システムから必要な情報を取得する

弊社の1システムとしてゴルフシステムがあります。当然ユーザー様は日本全国のゴルフ場なわけですが、ゴルフ場は基本郊外にありますのでネットワーク回線が不安定なことがあります。そのような理由からネットワークが不通となっても動作できるようオンプレで夜間バッチで連携を取る方式を現在は取っています。とはいえリアルタイムで特定の情報が知りたい事もあり、その場合はいちいちログインして確認することになるわけですが、それは面倒だ!加えてSlackは常に見てるので何でもSlackでやりたい。

で既存システムにslackのSlach Sommandsを組み合わせてみました。

システム構成

IIS 7.5
ASP.NET Web API
ASP.NET WCFサービスアプリケーション
.NET Framework 4.5.1

手順

  1. ゴルフ場サーバーから定周期でAWS上に作成したWCFをたたき、データ連携させる。

  2. Slash Commandsを作成。上記同様にAWS上に作成したWEB APIを叩くようにする。

これだけ。

f:id:ihisa:20160531151607p:plain

こんな感じになります。Slach Commandsを打つとPOSTする先となるWeb APIを新規に作成します。

Slach Commandsの仕様は以下の通りです。
Slash Commands | Slack

この仕様に則りWEB APIを作成します。記載の通りですが以下注意点です。

  1. 戻りは必ずHttpStatusを200にします。それ以外だと表示されないです。
  2. コマンドのパラメータはtextに入ってるので自由自在。
  3. 3秒以内に応答を返さないとSlackは応答がねぇよ!とあきらめます。
  4. 実行結果をコマンドを叩いたチャネルに通知する場合はresponse_typein_channelにする。デフォルトはephemeral(自身のみ)

詳しくはこちらを参照ください。
tech.sanwasystem.com

コード~結果

作ったWeb APIはこんな感じ。

using Newtonsoft.Json;
using System;
using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Web.Http;

namespace SlackAPI.Controllers.v1
{
    [RoutePrefix("v1/nt")]
    public class SlackController : ApiController
    {
        public SlackController()
        {
        }

        [HttpPost]
        [Route("information")]
        public HttpResponseMessage Information([FromBody]SlackRequestParameter parameter)
        {
            SlackResponseParameter response = new SlackResponseParameter();
            response.response_type = "ephemeral"; // slash command実行者のみ参照可能

            try
            {
                // token
                if (!parameter.token.Equals(ConfigurationManager.AppSettings["slacktoken"].ToString()))
                {
                    return Result(HttpStatusCode.OK, "認証がよろしくないです");
                }

                // optionに応じた処理
                if (parameter.text.ToLower().Equals("list"))
                {
                    response.text = "listオプションに応じた結果を返します";
                }
                else
                {
                    response.text = "そんなオプションは存在しません";
                }
                return Result(HttpStatusCode.OK, response);
            }
            catch (Exception)
            {
                response.text = "失敗しちゃった(´・ω・`)";
                return Result(HttpStatusCode.OK, response);
            }
        }

        private HttpResponseMessage Result<T>(HttpStatusCode status, T content)
        {
            HttpResponseMessage response = new HttpResponseMessage(status);
            if (content != null)
            {
                response.Content = new StringContent(JsonConvert.SerializeObject(content));
            }
            response.StatusCode = status;
            response.Content.Headers.ContentType.MediaType = "application/json";

            return response;
        }
    }

    [DataContract(Name = "SlackRequestParameter", Namespace = "http://hogehoge")]
    public class SlackRequestParameter
    {
        [DataMember]
        public string token { get; set; }
        [DataMember]
        public string team_id { get; set; }
        [DataMember]
        public string team_domain { get; set; }
        [DataMember]
        public string channel_id { get; set; }
        [DataMember]
        public string channel_name { get; set; }
        [DataMember]
        public string user_id { get; set; }
        [DataMember]
        public string user_name { get; set; }
        [DataMember]
        public string command { get; set; }
        [DataMember]
        public string text { get; set; }
        [DataMember]
        public string response_url { get; set; }
    }

    [DataContract(Name = "SlackResponseParameter", Namespace = "http://hogehoge")]
    public class SlackResponseParameter
    {
        [DataMember]
        public string response_type { get; set; }
        [DataMember]
        public string text { get; set; }
    }    
}

これをslash commandCommandで指定したコマンドをlistオプション付きで実行します。
f:id:ihisa:20160530155741p:plain

めでたく通知されました。
BYODが許可されている会社でしたらSlackを自身のスマホで利用されている方も多いでしょうから、Slackで自身が欲しい情報を取れるのは便利ですね!