Connpass で自分が興味あるキーワードの勉強会が登録されたら、Microsoft Flow 経由で通知する

＊Microsoft Flow の勉強がてら、自分用のメモとして残しておきます。


IT系勉強会を探すときに、Connpass をよく使っています。

https://connpass.com/

Connpass では、所属するグループが新しい勉強会を登録すると、メールで通知を行ってくれます。

しかし、特定のキーワードや地域名での通知機能は存在しません。このため、自分が所属するグループ外で、面白うな勉強会が開かれていても、情報を見過ごすことが何度かありました。

そこで、Microsoft Flow と組み合わせて

* 自分が興味あるキーワード、地域の勉強会の登録情報を定期的に確認
* 新しい勉強会が登録されたら、[Microsoft Flow](https://japan.flow.microsoft.com/ja-jp/) を経由して、メールで通知する

ようにしてみました。

## Connpass のAPIについて

Connpass はREST APIを公開しています。
https://connpass.com/about/api/

パラメーターに所定の指定を行うことで、条件に一致した勉強会の情報をJSONで取得することができます。

例として、キーワードに

* Azure
* 東京都

を含む勉強会を検索する場合、以下のようなURIとなります。

https://connpass.com/api/v1/event/?keyword=azure&keyword=%E6%9D%B1%E4%BA%AC%E9%83%BD

ここから取得できるJSONには「results_available」という項目があり、検索条件に合致した件数が整数値として返ってきます。

## 大まかな仕様

APIの仕様を踏まえて、以下のように考えてみました。
(極めて単純な仕様です)

* Connpass のAPIを問い合わせるためのコードを作成
 * 今回は、「Azure」「東京都」をキーワードに含むものとする
* キーワードに合致した勉強会の合計数「results_availavble」の値を取得。「number.txt」に保存する。
* 24時間後に取得した「results_available」の値と、前日に保存した「number.txt」の値を比較
* 「results_available」の値が、「number.txt」の値よりも大きい場合、キーワードに合致した勉強会が新しく登録されたと判断し、Microsoft Flow にシグナルを送る。
* Microsoft Flow から gmailで通知メールを送る

## Microsoft Flow について

https://japan.flow.microsoft.com/ja-jp/

* MSさんが提供している、複数のウェブサービス連携システム
* [LogicApps 上に構築されたサービスである](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-compare-logic-apps-ms-flow-webjobs)
* 類似のサービスは「IFTTT」「Zapier」など
* AWSでいうと [「Flow Framework」](https://aws.amazon.com/jp/swf/details/flow/) (であっているのかな？)


## Microsoft Flow 側の設定

Microsoft Flow には、外部からのhttp通信を受け取ったら、次のアクションに移るトリガーが存在します。このトリガーを使って、最初の設定を行います。

![flow_1.png](https://qiita-image-store.s3.amazonaws.com/0/83767/9b2d8d77-e3a7-7890-1ff0-f8cc07ce636c.png)

ここでは、POSTメソッドで任意のJSONデータを受け取った場合、次のアクションを呼び出します。「HTTP POST のURL」に記述されたURLが、POST通信を行うためのエンドポイントとなります。

POSTによる通信を受けったら、次のトリガーに移動します。今回は、Microsoft Flow とGmail を連携し、Gmail から指定のメアドへ通知メールを送ることにします。

(Microsoft Flow と Gmail の連携については 
https://japan.flow.microsoft.com/ja-jp/connectors/shared_gmail/gmail/
を御覧ください)

![flow_2.png](https://qiita-image-store.s3.amazonaws.com/0/83767/af5f4895-a256-fb7c-a62f-2abdd7c2e873.png)

設定画面から「宛先」「件名」「本文」を入力します。

これで、Microsoft Flow 側の設定は終了です。

## Connpass 問い合わせ用のコード

次に、Connpass のAPIへ問い合わせを行うためのコードを準備します。


```php

<?php

// Connpass に問い合わせを行いたい APIのエンドポイントを記述

  $base_url = 'https://connpass.com/api/v1/event/?keyword=azure&keyword=%E6%9D%B1%E4%BA%AC%E9%83%BD';

// Connpass 検索用の関数「searchConnpass」にエンドポイントを引き渡し、返り値を取得

  $response = searchConnpass($base_url);
  $json = json_decode($response, true) ;

// 連想配列からイベントの合計値を取得

  $new_number = $json['results_available'];

// 前日に取得したイベントの合計値を取得

  $old_number = file_get_contents("number.txt");

// イベント数が増加していた場合、最新のイベント数を number.txt に書き込み
// Microsoft Flow へ通知を行う関数「postToFlow」を実行


  if ($old_number <  $new_number) {

    file_put_contents("number.txt" , $new_number);

    postToFlow();

  }

// Connpass 検索用の関数定義

  function searchConnpass($base_url) {

// UserAgent 情報をセットする

    $headers = array(
        "User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",    
    );

    $curl = curl_init();

    curl_setopt($curl, CURLOPT_URL, $base_url);
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

    $result = curl_exec($curl);
    curl_close($curl);

    return $result;

  }


// Microsoft Flow へ通知を行う関数「postToFlow」を定義


  function postToFlow() {

    $flow_url = 'Microsoft Flow で作成した HTTP POST 受信用のURLを記述';

// Microsoft Flow に渡すためのダミー用JSONを生成

    $data = array("name" => "new arrival");                                                                    
    $data_string = json_encode($data); 

// curlでPOST

    $curl = curl_init();

    curl_setopt($curl, CURLOPT_URL, $flow_url);
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($curl);

    curl_close($curl);

  }

?>


```


コードを記述したら、cronを設定して、日次で実行します。
前日の勉強会から数値が増えていたら、Flow 経由でメールが送信されます。

![mail_from_flow.png](https://qiita-image-store.s3.amazonaws.com/0/83767/d1310580-add3-6352-7091-c6cf89a3baa9.png)

## 新着・更新があった勉強会のURLをGmailの本文に挿入する

上述のコードを元に、アレンジを加えます。


* 過去24時間以内に新着・更新があった勉強会のJSONデータを取得
* 新着・更新があった勉強会のURLを変数に格納
* JSONに加工して、Microsoft Flow のエンドポイントへポスト
* Gmailから送信された本文内に、各勉強会のURLを改行付きで表示する

という仕様で開発してみます。


### Microsoft Flow 側の準備

Microsoft Flow のHTTPエンドポイントでJSONデータを取得するには、HTTPトリガーが受信するJSONの型を指定して、それに応じたJSONデータを送信する必要があります。

Microsoft Flow は Logic Apps 上に構築されているため、Logic Apps 向けのドキュメントが参考に設定を行いました。

https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-http-endpoint

上記を参考に、Flow 側の設定を以下のようにします。ここでは「data」という名前のJSONデータを受信するようになっています。



![flow_4.png](https://qiita-image-store.s3.amazonaws.com/0/83767/daeeb7b3-4a59-99b6-d2ae-40dc1f99fcc0.png)

このエンドポイントに

```json

{
  "data":"hogehoge"
}
```

というデータを送信すると、トリガーが発動します。

次にGmail側の設定を行います。HTTPトリガーが受信するペイロードの型に合わせて、Gmailの本文内にデータを挿入することができます。

Gmailでは&lt;br&gt;タグを解釈して文章を改行するので、見やすくするため&lt;br&gt;タグを挿入しています。

![flow_5.png](https://qiita-image-store.s3.amazonaws.com/0/83767/cabd26e0-94a7-e7df-c931-ec7ccafef7c8.png)


これでMicrosoft Flow 側の設定は終了です。


## コード

Microsoft Flow にJSONデータをpostするためのコードを記述して、24時間毎にcronで実行します。

```php

<?php

// Connpass に問い合わせを行いたい APIのエンドポイントを記述

  $base_url = 'https://connpass.com/api/v1/event/?keyword=azure&keyword=%E6%9D%B1%E4%BA%AC%E9%83%BD';

  // Connpass 検索用の関数「searchConnpass」にエンドポイントを引き渡し、返り値を取得

  $response = searchConnpass($base_url);

  // 返り値のJSON から、勉強会に関する情報が格納された「events」のデータを取得

  $data = json_decode($response, true);
  $events = $data["events"];

  // 新着勉強会の情報を格納するための変数「$list」を準備

  $list = "";

  // コードを実行した日時の24時間前の時間を「$yesterday」に格納
  // 連想配列 $events から、過去24時間内に登録・更新があった勉強会の情報を取得
  // 新着・更新勉強会のURL情報を改行タグ<br>を付加して変数$listに追記

  foreach ($events as $key => $value) {
  
      $update = strtotime($value["updated_at"]);
      $yesterday = strtotime("-1 day" , time());
  
      if ($update > $yesterday) {
  
          $list = $list . $value["event_url"] ."<br>" ;   
      }
  }

  // 変数$listを、Microsoft Flow にPOSTするための関数「postToFlow」に渡す

  postToFlow($list);
  

  // Connpass 検索用の関数定義

  function searchConnpass($base_url) {
    
    // UserAgent 情報をセットする
    
        $headers = array(
            "User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",    
        );
    
        $curl = curl_init();
    
        curl_setopt($curl, CURLOPT_URL, $base_url);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    
        $result = curl_exec($curl);
        curl_close($curl);
    
        return $result;
    
      }



      // Microsoft Flow へ通知を行う関数「postToFlow」を定義


  function postToFlow($list) {
    
        $flow_url = 'Microsoft Flow で設定したHTTPのエンドポイントを記述';
    
    // Microsoft Flow に渡すためのJSONを生成

        $data = array("data" => $list);                                                                    
        $data_string = json_encode($data); 

    // curlでPOST
 
    $headers = array(
        "Content-Type: application/json",    
    );

        $curl = curl_init();
    
        curl_setopt($curl, CURLOPT_URL, $flow_url);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    
        $response = curl_exec($curl);
    
        curl_close($curl);
    
      }
    
```


コードが実行されると、過去24時間以内に登録・更新があった勉強会の情報をGmail経由で送信してくれます。

![flow_6.png](https://qiita-image-store.s3.amazonaws.com/0/83767/216f9b8f-3079-ebc8-18ed-af6b2ab9a173.png)


## 積み残し

* Azure Functions や AWS Lambda などのサーバーレスサービスでコードを実行させたい

## 参考情報

http://blog.livedoor.jp/sce_info3-craft/archives/9706167.html