先週公開した記事(Leaflet.js で空間フィルタリングをやってみる - Esri Leaflet Tips )で紹介した空間フィルタリングのサンプル アプリは、住所や地名を入力して周辺の施設を検索するという機能でしたが、これを Slack などのチャット上で実行できたら便利かしら?と思い立ち BOT を作ってみました。
「BOT(ボット)」とはロボットの略称で、最近では Twiter や LINE、Slack などのタイムライン上で会話ができるプログラムやアカウントのことを指す場合が多いですね。
このような BOT 向けの API やツールが公開されているため、BOT を作ってみたという開発者の記事をよく見かけるようになりました。
今回、BOT 作成にはオープンソースのチャット ロボットである Hubot という GitHub が作成した BOT プログラムを使いました。
また、最近エンジニアの間では一般的なチャットツールとなっている Slack 向けの BOT として作ってみました。
まずは BOT を使って結果を得るまでのフローを整理します。
この中で Hubot として実装したのは 1 ~ 3 です。
インストールから Slack への Hubot の設定等については、いろいろ詳しい記事があるので、そちらを参照するとよいと思います。
今回は主に Slack への BOT 設定をして、Hubot を Heroku にデプロイした後の話をします。
主に Hubot のスクリプトについてです。
4, 5 は Esri Leaflet Tips にて紹介した空間フィルタリングのサンプルをベースに、バッファーの中心座標が URL パラメーターの緯度経度取得をトリガーとするように作り直しました。
サンプルを Gist に置きましたのでご覧ください。
なお、無料 wifi スポットのデータは、オープンデータとして国土交通省が公開している歩行者移動支援サービスに関するデータサイトにある「無料公衆無線LANスポット」(国土交通省観光庁) を ESRIジャパン株式会社が加工したものを使っています。
URL パラメーターへの緯度経度埋め込みを試してみたい方はこちらにアクセスしてみてください。
デフォルトは札幌駅の緯度経度です。
Hubot では BOT の基本フローである「特定のメッセージを受け取ったら、対応するメッセージを返信する」というプログラムを CoffeeScript で記述します。
今回の実装はメッセージを受け取った後に緯度経度を取得するための処理を加えています。
Esri の住所検索サービス(World Geocoding Service)※1 へ住所・地名を送信して、取得した緯度経度を加えたアプリ URL を返信するという流れになります。
REST API の仕様は以下に詳しいです。
ここでも簡単に説明しますが、ArcGIS の住所検索サービスには 4 つのオペレーションが存在します。
REST の URL は以下のように作ります。
http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/[オペレーション名]?[パラメーター]
各オペレーションに対応したパラメーターは仕様を確認してください。
今回は Slack 上で入力された住所・地名を使って緯度経度を取得できればよいので、findAddressCandidates を使います。
findAddressCandidates でよく使うパラメーターは以下の通り。
パラメーター | 内容 |
---|---|
f | レスポンスのフォーマットを指定 (json | pjson) |
singleLine | 緯度経度を取得する住所・地名を指定 |
searchExtent | 検索範囲を指定 |
location | 基点となる位置を指定、distance で指定した値の半径円内に含まれる結果を優先します |
distance | location で指定した位置からの距離を指定 (デフォルトでは 50,000 メートル) |
maxLocations | 取得する結果 (候補) の数を指定 |
forStorage | 永続的に保存※2 を行うかどうかを指定 |
たとえば、永田町駅の緯度経度を取得する URL はこのようになります。
Hubot のスクリプトとして記述する内容を整理します。
上記フローの 1 ~ 3 のスクリプトです。
Hubot のスクリプトには msg.http を使ったリクエスト URL の生成・送信が可能なので、これを利用しています。
msg.match[1] に「探して」の後に記述されたキーワードが含まれているので、それをリクエスト URL の singleLine パラメーターに指定しています。
robot.respond /探して (.*)/i, (msg) -> keyword = msg.match[1] msg.send keyword + '周辺の無料 wifi スポットだよ!' request = msg.http('http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates') .query({ f: 'json', singleLine: keyword, outSr: 4326, forStorage: false, outFields: '*', maxLocations: 1 }) .get()
残りのフロー 4 ~ 5 のスクリプトです。
コールバックにエラー処理と取得した結果は JSON.parse でパースした json を参照します。
緯度経度は json.candidates[].location に x と y パラメーターとして与えられているので、これをもとに地図 URL を作ります。
最後に msg.send で地図 URL を送信して、終わり。
request (err, res, body) -> if err msg.send 'みつからないよ〜' robot.emit 'error', err, res return json = JSON.parse body appUrl = 'https://bl.ocks.org/ynunokawa/raw/8ec5c70d089a55bcabf7e3fd5dce9e39/?lat=' + json.candidates[0].location.y + '&lng=' + json.candidates[0].location.x msg.send appUrl if json.candidates.length > 0
今回作った Hubot はサンプルとして GitHub に公開しているので、よければお試しください。
なお、社内やチーム内で実運用する場合は、ArcGIS for Developers の有償プランにグレードを上げる必要があるのでご注意を。
※1 住所検索サービスは100万リクエスト/月の上限内であれば使い放題です
※2 findAddressCandidates で取得した結果の永続的な保存にはクレジットが必要です
関連リンク