Office 365とかSaaSの自由帳

Office 365の話とかSaaSについてとかいろいろ書きたいと思います。なんだかんだ備忘録になると思います。

ノンコーディング!Exchange Onlineの予定の場所の近くの○○屋さんをTeamsに自動通知する

この記事はOffice 365のAdvent Calendar 2017に参加しております。
adventar.org


今回のAdvent Calendarは元々Teamsのチーム作成をSharePoint Onlineのワークフロー+Azure Automationで管理者の申請制にしてみよう!という記事を書こうと思ってたのですが、12/19担当の@matkjinさんが同様のアプローチをされていたので、こちらはまた次回ということで・・(記事のリンクはこちらです)

ということで、何書こうかなー?と考え、以前Office 365勉強会でお話させていただいた、打ち合わせ場所の近くの○○屋さんをTeamsに通知する方法をMicrosoft Flowを使った完全ノンコーディングバージョンでお届けしたいと思います。

以前はAzure Functionsを使ったアプローチだったのですが、今回は全てOffice 365の"利用者"でできるものしか使っておりません。(以前のアプローチはこちらのスライドを参照)
〇〇屋さんは皆さんのお好きなものを当てはめてください。(今回も例としてハンバーガー🍔)

それでは初めましょう。

必要なもの

なお、ぐるなびAPIを利用するためにはこちらからアカウントを発行してください。

今回のアプローチ

以下のような流れです。

  1. Exchange Onlineに予定を住所付きで登録 (例)社外打ち合わせ等
  2. 予定が始まる〇分前にFlowが動作する
  3. 住所をGeocodingのAPIに渡し、緯度と経度取得
  4. 緯度と経度をぐるなびAPIに渡し、近くの○○屋さんを取得
  5. 取得した情報をTeamsに通知する
  6. 美味しいお店に行けてハッピー

f:id:takeru55555:20171221190424p:plain

実装してみる

今回はすべてFlow側の実装となります。ちなみに処理をシンプルにするためにエラー処理や例外処理は記述しておりません。例えば住所が空欄の場合や会議室が入っている場合などは別途例外処理を記述する必要がありますのでご注意を。
それでは実装してみましょう。

  • トリガーとして、「予定しているイベントがすぐに開始されるとき」を選択し、以下のように設定。今回は予定の2時間前にFlowが動作するようにしました。

f:id:takeru55555:20171221192856p:plain

  • 次に「HTTP - HTTP」を選択します。Geocodingには以下のよにGETでAPIを叩きます。

http://www.geocoding.jp/api/?q=<住所をエンコードした値>

なお、日本語をエンコードするために、encodeUriComponent 式を利用します。
encodeUriComponent(triggerBody()?['Location']?['DisplayName'])

f:id:takeru55555:20171221193825p:plain

ちなみにこの結果はXMLで返ってきます。

  • 次も「HTTP - HTTP」を選択します。以下のようにGETでぐるなびAPIを叩きます。

http://api.gnavi.co.jp/RestSearchAPI/20150630/?keyid=<発行されたキー>&format=json&input_coordinates_mode=1&latitude=<緯度>&longitude=<経度>&range=3&freeword=<検索ワードをエンコードしたもの>
APIにはいろいろなパラメータが用意されているので仕様書を参考にしていただき色々組み替えてください

なお、緯度と経度はGeocodingの結果であるXMLから値を取り出すために、以下のようにFlowに装備されているxpath式を使います。
緯度
 xpath(xml(body('Http')),'string(/result/coordinate/lat)')
経度
 xpath(xml(body('Http')),'string(/result/coordinate/lng)')

f:id:takeru55555:20171221194955p:plain

こちらはJOSNで返ってきます。

  • 次に「JSONの解析」アクションを使います。実際の応答である「本文」からスキーマを生成することができますが、お店によってはnullのフィールドがあったりすると解析できずエラーとなる場合があります。そこで今回は全店舗で情報を持っているであろう店舗名、URL、住所のみを取るようにしました。

サンプルのスキーマは以下の通りです。

{
    "type": "object",
    "properties": {
        "@@attributes": {
            "type": "object",
            "properties": {
                "api_version": {
                    "type": "string"
                }
            }
        },
        "total_hit_count": {
            "type": "string"
        },
        "hit_per_page": {
            "type": "string"
        },
        "page_offset": {
            "type": "string"
        },
        "rest": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "@@attributes": {
                        "type": "object",
                        "properties": {
                            "order": {
                                "type": "string"
                            }
                        }
                    },
                    "name": {
                        "type": "string"
                    },
                    "url": {
                        "type": "string"
                    },
                    "address": {
                        "type": "string"
                    }
                },
                "required": [
                    "@@attributes",
                    "id",
                    "update_date",
                    "name",
                    "name_kana",
                    "latitude",
                    "longitude",
                    "category",
                    "url",
                    "url_mobile",
                    "coupon_url",
                    "image_url",
                    "address",
                    "tel",
                    "tel_sub",
                    "fax",
                    "opentime",
                    "holiday",
                    "access",
                    "parking_lots",
                    "pr",
                    "code",
                    "budget",
                    "party",
                    "lunch",
                    "credit_card",
                    "e_money",
                    "flags"
                ]
            }
        }
    }
}

f:id:takeru55555:20171221195524p:plain

  • 実際のデータが「rest」に格納されるので、後はループを回してTeamsに投稿していくだけです。ここでは「Apply to each」およびTeamsへの「Post message」にて投稿していきます。以下のような感じですね。

f:id:takeru55555:20171221195855p:plain

使ってみる

さて適当な予定を突っ込んで開始に時間前まで待ってみましょう。ちゃんと来ていますね。
f:id:takeru55555:20171221201816p:plain

今回はTeamsのPost messageアクションを使いましたが、少しシンプルすぎるので、もう少し見やすいようにするのであれば、TeamsのWebhookでメッセージを投稿した方が良いかもしれません。

まとめ

さて今回はハンバーガーという私の趣味一直線でしたが、例えばコーヒー屋さんでも良いでしょうし、色々応用が利きます。
Office 365の管理権限なんかも必要ないので、是非お試しください~~~

ではまた次回。