Microsoft 365 メッセージ センターコネクタを試す - Part.2 連携

# はじめに
どんなものも注意深く観察していると一定の規則性を感じることができます。先日[Microsoft 365 メッセージ センターコネクタを試す - Part.1 設定](https://qiita.com/DEmodoriGatsuO/items/a4817a94ae94dc80e898)のブログにて、「メモ欄」に情報が集約されてしまい、解析する必要があると記載しましたが、私なりの対処法を検討しましたので、書いていこうと思います。

https://qiita.com/DEmodoriGatsuO/items/a4817a94ae94dc80e898

# 見出し: 文章で一定の構造化がされている
観察していくと
 - Message ID
 - Published date
 - Last updated date
 - Category
 - Tags
 - Relevance

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/20c4ba02-2b6e-6438-3100-965b4e016fae.png)

上記の例のように[見出し: 内容]と表現されます。
複数行テキストの情報は上記に該当しませんが少なくとも
 - Updated Month Day, Year
 - [When this will happen:]
 - [How this will affect your organization:]
 - [What you need to do to prepare:]

と情報が連なっています。

`Microsoft 365 管理センター`で見る
 - メッセージの件名
 - サービス
 - 最終更新
 - 対応期限
 - 関連性
 - 組織の状態
 - タグ

上記のような情報がパースして拾えそうな気配がします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/2cf91180-3dfc-e3d5-9899-0a16b902b3b4.png)

また複数例を見ていくと、「*Last updated date*」の見出しがある場合とない場合で分かれるなど、動的な項目の変動が見られます。
 - **一定の項目は固定的に抽出できる**
 - **動的な項目の変動に対処**

上記で情報をパースし、**アダプティブカード**で通知するシナリオを検討したいと思います。

## 文章の規則性
文章を観察すると、ほぼ「見出し: 内容」で構成されると同時に、今回抽出するテキストは、基本的に一行内に収まる情報です。

つまり改行するまでがパースの対象になります。
この点のものは「正規表現」を使いことが相場ですが、`データ操作`でトライしていきましょう。

### フローの流れ
1. 変数を初期化 - 配列（取得するキー項目の一覧）
1. 変数を初期化 - オブジェクト（値を取得するための箱）
1. [選択(Select)](https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-select-action) - キーバリューで値を抽出
1. [アレイのフィルター処理](https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-filter-array-action) - `null`を除外して項目の増減に対処
1. For each
    1. [作成](https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-compose-action) - オブジェクトを一時的に格納
    1. 変数を設定 - [addProperty 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#addproperty)でプロパティを追加

### 変数を初期化 - 配列（取得するキー項目の一覧）
呼び出したいキー項目を下記の通り列挙しておきましょう。
条件分岐で利用するためです。

```変数を初期化する - Array
[
  "Message ID",
  "Published date",
  "Last updated date",
  "Category",
  "Tags",
  "Relevance"
]
```

:::note info
ハードコーディングがナンセンス、という意見は一旦その通りです、と言っておきます
:::


### やはり便利な選択
[選択(Select)](https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-select-action)を用いて、改行コードごとに文章を分割[split 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#addproperty)、(1)で設定したキー項目を含む[contains 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#contains)要素のみ、キーバリューを明示的に収集します。

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#addproperty

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#contains

 - `From` - split(outputs('タスクの詳細を取得する')?['body/description'], decodeUriComponent('%0D%0A'))
- `Map`

```
{
  "key": @{if(contains(variables('Columns'),split(item(),': ')?[0]),split(item(),': ')?[0],null)},
  "value": @{if(contains(variables('Columns'),split(item(),': ')?[0]),split(item(),': ')?[1],null)}
}
```

:::note info
1. 改行コードで文字列を分割
    1. 改行コードは`decodeUriComponent('%0D%0A'))`が該当
1. オブジェクト型で`key`、`value`を拾いたい配列に含まれる場合のみ追加する方法
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/6e5c6201-d156-3065-9141-c7bdc4ac4336.png)


**やはり登場するのは選択です。**
**万能選手過ぎて驚きますね！**

https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-select-action

### [アレイのフィルター処理](https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-filter-array-action)で`null`を除外
[選択(Select)](https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-select-action)を用いた際に、(1)の配列に含まれないキーを全て`null`と設定しています。こちらによって配列から`null`を除外するフィルターを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/64facf2b-3d5a-5f5f-5e58-eb125e126649.png)

https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-filter-array-action

 - From - `body('選択')`
 - Filter Query - `@not(equals(item()?['value'],null))`


### あとは繰り返し処理
あとは繰り返しで[addProperty 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#addproperty)による属性の追加です。

`変数の設定`の中で対象の変数を呼び出すことはできないため、一度[作成](https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-compose-action)で格納してから[addProperty 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#addproperty)を適用しています。


```plaintext:Do until
addProperty(body('JSON_Array')?[variables('j')],'Index',iterationIndexes('Do_until'))
```

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#addproperty

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/2b4f66d6-798b-a6d6-12a9-6576a927fb4e.png)

## JSONになったらこっちのもの！
あとはお手の物です。
SharePoint Listsに格納するなり、Teamsでアダプティブカードに追加するなりできます。

文字列といえども目を凝らせば規則性があるもの。
観察👀大切ですね！

### アダプティブカード編

最終系はコチラ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/be95e111-7218-09bf-8e49-c7cc57dd8e44.png)

```json
{
    "$schema": "https://adaptivecards.io/schemas/adaptive-card.json",
    "type": "AdaptiveCard",
    "version": "1.4",
    "body": [
        {
            "type": "Container",
            "items": [
                {
                    "type": "FactSet",
                    "facts": @{body('FactSet')
                    }
                },
                {
                    "type": "TextBlock",
                    "text": "@{outputs('タスクの詳細を取得する')?['body/description']}",
                    "wrap": true
                }
            ]
        }
    ],
    "actions": @{body('actions')
    }
}
```

`FactSet`と`actions`は配列なので、`アレイのフィルター処理`から整形したほうが速いですね💦
並列分岐で追加しました。

■ `FactSet`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/7d2a30f5-875f-415e-3449-6da05ae6f52a.png)

 - `From` - `body('アレイのフィルター処理')`

 ```json:Map
 {
  "title": @{item()?['key']},
  "value": @{item()?['value']}
}
 ```

 ■ `actions`
参照リソースのURLです

  - `From` - `outputs('タスクの詳細を取得する')?['body/references']`

 ```json:Map
{
  "type": "Action.OpenUrl",
  "title": "Item", // title適当なので変えてください
  "url": @{item()?['resourceLink']}
}
 ```