Azure Functions + Node.js + Flow で、Connpass のイベント情報を定期的に取得する

 Azure Functions と Node.js の勉強がてら、作ってみました。[前記事の続き](https://qiita.com/TakeshiNickOsanai/items/bf4f17c7f3d58960da12)  となります。

# やること

Connpass で、自分が興味あるキーワードの勉強会が新規登録・更新されたら、メールで通知する。

# 仕様

* Azure Functions で、一日一回「Azure」「東京都」に関する勉強会の更新・登録情報を検索する。
* 新着情報があったら、その勉強会のURLを Microsoft Flow に送信する。
* Microsoft Flow で受け取った勉強会情報を、Gmail で送信する。

以下、

* Microsoft Flow の設定
* Azure Functions の設定
    * 初期設定
    * npmによるパッケージのインストール
    * Azure Functions の Node.js バージョン
* Node.jsのコード作成
    * 設定とテスト
* 実際の挙動

の順番で記述します。


# Microsoft Flow の設定

Microsoft Flow の設定は前回の記事と同じ手順となります。

* [Microsoft Flow 側の設定](https://qiita.com/TakeshiNickOsanai/items/bf4f17c7f3d58960da12#microsoft-flow-%E5%81%B4%E3%81%AE%E8%A8%AD%E5%AE%9A)
* [新着・更新があった勉強会のURLをGmailの本文に挿入する](https://qiita.com/TakeshiNickOsanai/items/bf4f17c7f3d58960da12#%E6%96%B0%E7%9D%80%E6%9B%B4%E6%96%B0%E3%81%8C%E3%81%82%E3%81%A3%E3%81%9F%E5%8B%89%E5%BC%B7%E4%BC%9A%E3%81%AEurl%E3%82%92gmail%E3%81%AE%E6%9C%AC%E6%96%87%E3%81%AB%E6%8C%BF%E5%85%A5%E3%81%99%E3%82%8B)


# Azure Functions の設定

Microsoft Flow 側の設定が終了したら、Azure Functions の設定を行います。

Azure のポータル画面から、[新規]を選び、「functions」で検索=>[Functions App]を選択=>[作成]を行う

![functions_1.png](https://qiita-image-store.s3.amazonaws.com/0/83767/8cde59a7-bfab-77da-4523-f5daa493a870.png)

アプリ名、リソースグループなどを設定してサービスを立ち上げる

![functions_2.png](https://qiita-image-store.s3.amazonaws.com/0/83767/77ccf6ca-a859-5d26-f0ce-127000f81e25.png)


セットアップが終わったら、Functions のカスタム関数から新規関数を登録する。ここでは「タイマー」「JavaScript(=Node.js)」を選択する。

![functions_4.png](https://qiita-image-store.s3.amazonaws.com/0/83767/c623adef-7570-5f34-ee1d-78ab0d884938.png)


もしくは、クイックスタートを使用しても良い。

カスタム関数の名前を設定。ここでは「ConnpassSearch」とした。下部はタイマーのスケジュール設定(cron方式)。Cronの書式で記述すると、そのルールに従って関数を実行する。
タイマーのスケジュールは後で変更できるので、とりあえずこのまま作成する。

![functions_5.png](https://qiita-image-store.s3.amazonaws.com/0/83767/f335f030-03ce-c728-942b-d77b68c4b355.png)




関数が登録され、初期のダミー関数とエディタが表示される。このエディタ内に、実行したい関数を登録していく。

![functions_6.png](https://qiita-image-store.s3.amazonaws.com/0/83767/1cfb5f3a-b307-edd4-cffb-7a4691436080.png)

## npmによるパッケージのインストール

次に、npmで必要なパッケージをインストールする。npmの操作方法は [Azure のドキュメント](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-reference-node#node-version-and-package-management) に従って操作する。

https://&lt;function_app_name&gt;.scm.azurewebsites.net へアクセス。今回の例では、Functions App の名称を「connpasstest」としたため

https://connpasstest.scm.azurewebsites.net

となる。

[Debug Console]=>[CMD]へ移動して、コマンドプロンプトを表示する。

次に、npmをインストールしたい関数のディレクトリへ移動。
今回の例では「ConnpassSearch」という関数名にしたため、

```
D:\home\site\wwwroot\ConnpassSearch
```

へ移動する。

![functions_7.png](https://qiita-image-store.s3.amazonaws.com/0/83767/b5bd7053-5262-a58b-c355-32c78edc03de.png)


コマンドプロンプトで

```
npm init
npm install --save request
```

と打ち込み、requestパッケージをインストールする。


## Azure Functions の Node.js バージョン

[ドキュメント](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-reference-node#node-version-and-package-management)によると、2018年2月時点では「6.5.1」で固定されているとのこと。

# Node.js のコード作成

Azure Functions で実行する Node.js のコードを記述。

* Connpass のAPIから、検索キーワードに合致した勉強会のデータを取得
* コード実行時から24時間以内に登録・更新があった勉強会のデータを取得
* 勉強会のURL情報を Microsoft Flow にpostする

というロジックで書いてみました。
([前回書いたphpのコード](https://qiita.com/TakeshiNickOsanai/items/bf4f17c7f3d58960da12#%E3%82%B3%E3%83%BC%E3%83%89)を JavaScript で書き直しました)

```javascript
  'use strict';

  // モジュールと通信のためのエンドポイントを変数に定義

  const request = require('request');
  const URL = 'https://connpass.com/api/v1/event/?keyword=azure&keyword=%E6%9D%B1%E4%BA%AC%E9%83%BD';
  const FlowURL = 'Flowで設定したエンドポイント';


  // 関数[connpassSearch]で、勉強会の情報を取得

  connpassSearch(URL).then(function(response) {

  // APIからの返り値 response から連想配列 events を切り出す  

    const events = response.events;

    // events内の勉強会の更新日・登録日をUNIX TIME のミリ秒で取得
    // 過去24時間内に更新・登録された勉強会があったら、そのイベントURLを変数listに追記

    const dt = new Date();
    const yesterday = dt - 86400000;
    let list = '';

    for (let i in events) {
      let updated_at = new Date(events[i].updated_at);
      if (updated_at > yesterday) {
        list += events[i].event_url + "<br>";
      }
    }

    // 変数listをJSON型の変数[data]に加工する

    const hash = {
      data: list
    };

    const data = JSON.stringify(hash);

    // 更新・新着勉強会があったら ＝ 変数 dataが空でなければ
    // Microsoft Flow へ更新・新着勉強会のURLを渡す
    
    if (data !== null) {
      postData(data);
    }
  });

  // Connpass のREST APIを叩くための関数「connpassSearch」を定義
  // Connpass のAPIから取得したデータを Promise で返す

  function connpassSearch(URL) {
    return new Promise((resolve, reject) => {
      request.get({
        uri: URL,
        headers: {
          'Content-type': 'application/json',
          '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',
        },
        json: true
      }, function(err, req, data) {
        resolve(data);
      });
    });
  }

  // Microsoft Flow へ JSONデータをポストするための関数 [postData]を定義

  function postData(data) {
    request.post({
      uri: FlowURL,
      headers: {
        'Content-type': 'application/json',
      },
      body: data,
    }).on('error', function(err) {
      console.log(err)
    });
  }

```

## 設定とテスト

先ほど作成した、Functions のエディタ画面から、Node.jsのコードを貼り付ける。
初期状態の関数には

```javascript
module.exports = function (context, myTimer) {}
```
と記述されている。この「context」オブジェクトは、[Functions の実行のために必要な記述](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-reference-node#context-object)とのことなので、そのまま残し、ダミーコードの部分を今回記述したコードに入れ替える。

```javascript
module.exports = function (context, myTimer) {

// 作成したコードを貼り付ける

}
```

![functions_8.png](https://qiita-image-store.s3.amazonaws.com/0/83767/19ab9328-9cab-26e6-5b56-a023be963b87.png)


コードを保存したら、実行テストを行って挙動を確認する。また、メニューの[統合]から、実行間隔を設定する。

Azure Functions では、協定世界時(UTC)が基準となる。Functionsサービスをどのリージョンに設定しても変わらない。東日本のリージョンに設定してもUTCとなる。

例として、毎日AM8時にコードを実行したい場合、設定は

```
0 0 23 * * *
```

となる。

![functions_9.png](https://qiita-image-store.s3.amazonaws.com/0/83767/3483079b-b3ce-6faa-b549-89fc2d6decb5.png)


タイマーの設定が終わったら、保存をして終了。

# 実際の挙動

「Azure」「東京都」に関連する新着情報が、毎日定時にメールで届きます。

![functions_10.png](https://qiita-image-store.s3.amazonaws.com/0/83767/973725b4-110c-4820-4766-1314aae8557c.png)




#ちなみに

[Movable Type](https://www.sixapart.jp/movabletype/)  に関する Connpass のエンドポイントは

```
https://connpass.com/api/v1/event/?keyword=Movable%20Type
```

となります。(ダイマ)