ルドルフもわたるふもいろいろあってな

Microsoft 365、Power Platform、PowerShellについて調べたことや検証したことなどを投稿します。技術の話は面白い。

Microsoft Teamsで投稿に「いいね」をしていないひとに対してスケジュール実行でメンションする(解説編その2)

掲題のフローの解説編その2です。

フローはこちらからダウンロードできます。
github.com

これまでの解説の経緯

この投稿は、解説編その1からの続きです。

概要編はこちらです。

この回で解説する範囲

解説する範囲のフロー図


この範囲の目的

この範囲にあるのはひとつのスコープです。スコープの中には4つのアクションがあります。スコープにしている理由は、この4つのアクションはそれぞれが独立したものではなくこの4つでひとつの目的を達成しているためです。まとまったひとつの処理であることがこのフロー図を見て分かりやすいようにする意図があります。スコープが無くても処理内容は変わりません。

処理内容の解説を始める前にこの範囲の目的を解説します。

図で解説

この範囲の目的は下記の2つです。

  • 「① :Teamsの投稿から取得したリアクションの配列を作成」を行うこと
  • ①で作成した配列に「③ :①の配列から「リアクションした日時」を取得」を行うための仕込みを行うこと


入力データと出力データを解説

この範囲で行っているのはJSONの整形です。

解説編その1 の範囲で出力されたJSONが入力データです。それを今回の範囲で整形します。整形した結果出来上がった出力データのJSONを後続の処理に渡します。それが今回の範囲の目的です。

解説編その1で出力されたJSONとは、具体的には「メッセージ詳細を取得する」アクションにおけるbodyの値を指しています。

このJSONが以下の通りです。

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#chats('19%3A119718ede4b14fbf9e3e05aecb6011a8%40thread.tacv2')/messages/$entity",
  "id": "1635343695473",
  "replyToId": null,
  "etag": "1635343708503",
  "messageType": "message",
  "createdDateTime": "2021-10-27T14:08:15.473Z",
  "lastModifiedDateTime": "2021-10-27T14:08:28.503Z",
  "lastEditedDateTime": null,
  "deletedDateTime": null,
  "subject": "PNW Coffee kick-off",
  "summary": null,
  "chatId": "19:119718ede4b14fbf9e3e05aecb6011a8@thread.tacv2",
  "importance": "normal",
  "locale": "en-us",
  "webUrl": null,
  "channelIdentity": null,
  "policyViolation": null,
  "eventDetail": null,
  "from": {
    "application": null,
    "device": null,
    "user": {
      "id": "b47f27cf-ab22-4f31-a275-401256e5395e",
      "displayName": "Christie Cline",
      "userIdentityType": "aadUser"
    }
  },
  "body": {
    "contentType": "html",
    "content": "<div>Hi, \n<div style=\"display:inline\"><at id=\"0\">PNW Coffee Social Campaign</at></div> team, Awesome job all around getting things organized with our client this morning. I really love the participation, questions and collaboration coming from this group. The client expressed how excited they are to work with us. I created this channel to keep us on task. I've created folders for this channel so we can organize and collect assets here.</div>\n<div></div>",
    "plainTextContent": "Hi, \nPNW Coffee Social Campaign team, Awesome job all around getting things organized with our client this morning. I really love the participation, questions and collaboration coming from this group. The client expressed how excited they are to work with us. I created this channel to keep us on task. I've created folders for this channel so we can organize and collect assets here.\n"
  },
  "attachments": [],
  "mentions": [
    {
      "id": 0,
      "mentionText": "PNW Coffee Social Campaign",
      "mentioned": {
        "application": null,
        "device": null,
        "user": null,
        "tag": null,
        "conversation": {
          "id": "19:119718ede4b14fbf9e3e05aecb6011a8@thread.tacv2",
          "displayName": "PNW Coffee Social Campaign",
          "conversationIdentityType": "channel"
        }
      }
    }
  ],
  "reactions": [
    {
      "reactionType": "like",
      "createdDateTime": "2021-10-27T14:08:17.776Z",
      "user": {
        "application": null,
        "device": null,
        "user": {
          "id": "ac86a897-a97e-4bf7-9d68-6067105c9dea",
          "displayName": null,
          "userIdentityType": "aadUser"
        }
      }
    },
    {
      "reactionType": "like",
      "createdDateTime": "2021-10-27T14:08:26.263Z",
      "user": {
        "application": null,
        "device": null,
        "user": {
          "id": "238a4d61-50a3-40ee-b791-c5af3f30c324",
          "displayName": null,
          "userIdentityType": "aadUser"
        }
      }
    },
    {
      "reactionType": "like",
      "createdDateTime": "2021-10-27T14:08:28.528Z",
      "user": {
        "application": null,
        "device": null,
        "user": {
          "id": "a63d24d4-16e9-4299-a2d8-1c0a92c8d2bd",
          "displayName": null,
          "userIdentityType": "aadUser"
        }
      }
    }
  ],
  "messageLink": "https://teams.microsoft.com/l/message/19:119718ede4b14fbf9e3e05aecb6011a8@thread.tacv2/1635343695473?context=%7B%22contextType%22:%22chat%22%7D",
  "threadType": "chat",
  "conversationId": "19:119718ede4b14fbf9e3e05aecb6011a8@thread.tacv2"
}

この入力データを整形することで、出力データとして得られるのが以下のJSONです。このJSONを作るのが今回の範囲の目的です。

[
  "\"id_ac86a897-a97e-4bf7-9d68-6067105c9dea\":{\"reactionType\":\"like\",\"id\":\"ac86a897-a97e-4bf7-9d68-6067105c9dea\",\"createdDateTime\":\"2021-10-27T14:08:17.776Z\"}",
  "\"id_238a4d61-50a3-40ee-b791-c5af3f30c324\":{\"reactionType\":\"like\",\"id\":\"238a4d61-50a3-40ee-b791-c5af3f30c324\",\"createdDateTime\":\"2021-10-27T14:08:26.263Z\"}",
  "\"id_a63d24d4-16e9-4299-a2d8-1c0a92c8d2bd\":{\"reactionType\":\"like\",\"id\":\"a63d24d4-16e9-4299-a2d8-1c0a92c8d2bd\",\"createdDateTime\":\"2021-10-27T14:08:28.528Z\"}"
]

どんな手法を使っているの? → 「JSON Dictionary」です。

この出力データのJSONは「JSON Dictionary」です。

Dictionaryとは、キー(Key)と値(Value)の組み合わせを持つデータの集合です。JSON形式のデータでDictionaryを実現したものが「JSON Dictionary」です。

データの集合をキー(Key)と値(Value)の組み合わせにすることによって先ほどの図の「③ :①の配列から「リアクションした日時」を取得」が行えるようになります。Excel関数のLookUp と同じだと捉えてください。

JSON Dictionary」については Hiroさんのブログ記事で詳しく解説されているのでこちらを参照してください。私が今回の範囲で使用している4つのアクションの使い方は正直に言いますとHiroさんのこのブログ記事の真似です。なので元ネタであると認識しつつ下記記事を読んでから今回の解説を読むと理解がしやすいと思います。
mofumofupower.hatenablog.com

出力データの配列は具体的にどんなデータを表しているの?

出力データを表にすると以下の通りになります。左の列がキー(Key)です。右の列が値(Value)です。Valueの中に配列が入れ子になっています。

* 追記4/17 21:22:表の構造が誤っていたので修正しました。

それぞれの列の解説です。

  • キー(key)はユーザーIDです。keyとして使うことが分かりやすいように頭に「id_」という文字列をつけています。
  • 「reactionType」列の値はTeamsの投稿に行ったリアクションの種類を表します。「like」が"いいね" を表しています。
  • 「id」列の値はキー(key)と同じです。こちらは頭に「id_」をつけていないです。
  • 「createdDateTime」列の値はリアクションを行った日時です。

※ 「id」列はフローを作成した当時、念のためいれたものですが実際にはフローの処理で使っていないです。

各アクションの解説

1.「リアクション部分抽出」アクション

これは「データ操作」>「選択」アクションです。解説編その1の出力データのうち、フローで必要な列だけを抽出しています。

入力

"from": "@body('メッセージ詳細を取得する')?['reactions']",
"select": {
 "reactionType": "@item()?['reactionType']",
 "id": "@item()?['user']?['user']?['id']",
 "createdDateTime": "@item()?['createdDateTime']"
 }

出力

[
  {
    "reactionType": "like",
    "id": "ac86a897-a97e-4bf7-9d68-6067105c9dea",
    "createdDateTime": "2021-10-27T14:08:17.776Z"
  },
  {
    "reactionType": "like",
    "id": "238a4d61-50a3-40ee-b791-c5af3f30c324",
    "createdDateTime": "2021-10-27T14:08:26.263Z"
  },
  {
    "reactionType": "like",
    "id": "a63d24d4-16e9-4299-a2d8-1c0a92c8d2bd",
    "createdDateTime": "2021-10-27T14:08:28.528Z"
  }
]

2.「選択 - リアクションを辞書(Key-Value)形式に変換」アクション

これも「データ操作」>「選択」アクションです。「リアクション部分抽出」アクションの出力結果の1件ずつに対して、「id_(ユーザーID)」の文字をくっつけています。

入力

"from": "@body('リアクション部分抽出')",
        "select": "@concat('\"id_', item()?['id'], '\":', string(item()))"

出力

[
  "\"id_ac86a897-a97e-4bf7-9d68-6067105c9dea\":{\"reactionType\":\"like\",\"id\":\"ac86a897-a97e-4bf7-9d68-6067105c9dea\",\"createdDateTime\":\"2021-10-27T14:08:17.776Z\"}",
  "\"id_238a4d61-50a3-40ee-b791-c5af3f30c324\":{\"reactionType\":\"like\",\"id\":\"238a4d61-50a3-40ee-b791-c5af3f30c324\",\"createdDateTime\":\"2021-10-27T14:08:26.263Z\"}",
  "\"id_a63d24d4-16e9-4299-a2d8-1c0a92c8d2bd\":{\"reactionType\":\"like\",\"id\":\"a63d24d4-16e9-4299-a2d8-1c0a92c8d2bd\",\"createdDateTime\":\"2021-10-27T14:08:28.528Z\"}"
]

3.「結合」アクション

これは名前の通り、「データ操作」>「結合」アクションです。「選択 - リアクションを辞書(Key-Value)形式に変換」アクションの出力を "," を区切り文字として入れてひとつの文字列にしています。このアクションの目的は、次のアクションでこの文字列をJSON形式に変換するための前準備です。

入力

 "from": "@body('選択_-_リアクションを辞書(Key-Value)形式に変換')",
 "joinWith": ","

出力

"id_ac86a897-a97e-4bf7-9d68-6067105c9dea":{"reactionType":"like","id":"ac86a897-a97e-4bf7-9d68-6067105c9dea","createdDateTime":"2021-10-27T14:08:17.776Z"},"id_238a4d61-50a3-40ee-b791-c5af3f30c324":{"reactionType":"like","id":"238a4d61-50a3-40ee-b791-c5af3f30c324","createdDateTime":"2021-10-27T14:08:26.263Z"},"id_a63d24d4-16e9-4299-a2d8-1c0a92c8d2bd":{"reactionType":"like","id":"a63d24d4-16e9-4299-a2d8-1c0a92c8d2bd","createdDateTime":"2021-10-27T14:08:28.528Z"}

4.「作成 - JSON Dictionary」アクション

これは「データ操作」>「作成」アクションです。「結合」アクションの出力で得られた文字列を括弧({})で囲んだうえで、json関数で変換を実行しています。

入力

 "inputs": "@json(concat('{', body('結合'), '}'))",

出力

{
  "id_ac86a897-a97e-4bf7-9d68-6067105c9dea": {
    "reactionType": "like",
    "id": "ac86a897-a97e-4bf7-9d68-6067105c9dea",
    "createdDateTime": "2021-10-27T14:08:17.776Z"
  },
  "id_238a4d61-50a3-40ee-b791-c5af3f30c324": {
    "reactionType": "like",
    "id": "238a4d61-50a3-40ee-b791-c5af3f30c324",
    "createdDateTime": "2021-10-27T14:08:26.263Z"
  },
  "id_a63d24d4-16e9-4299-a2d8-1c0a92c8d2bd": {
    "reactionType": "like",
    "id": "a63d24d4-16e9-4299-a2d8-1c0a92c8d2bd",
    "createdDateTime": "2021-10-27T14:08:28.528Z"
  }
}

これで目的のJSONが得られました。

解説編その2は以上です。

追記:解説編その3を投稿しました。

投稿しました。
wataruf.hatenablog.com