ささみ学習帳 - sasami's study book

ささみ学習帳

Microsoft365 や Power Platform について学んだこと・アイデアのメモ

Planner タスクのコメントを取得・投稿する PowerAutomate クラウドフロー

 

はじめに

2023年7月時点ではPlannerコネクタではタスクのコメントを取得・投稿するアクションは用意されていません。しかし、調べてみるとPower Automateで実現することができました。

コメントを取得するフローと、コメントを投稿するフローの2本立てです。

 

Planner タスクのコメントの仕組み

Planner タスクのコメントは、Planner プランが紐づいているMicrosoft365グループのグループメールボックスにメールとして保存されており、メールのスレッドがそのままコメントのスレッドとして活用されています。

タスクとコメントは、コメントメールスレッドのIDをタスク側で保持する事で連携されています。

「タスクの取得」アクションの出力に含まれている"conversationThreadId"でコメントメールスレッドのIdを確認できます。

ただし、コメントが1つも付いていないタスクの場合は"conversationThreadId"が存在しません。この値の有無でコメントの有無を判断することができます。

このような動作の為、コメント返信(コメントが1つ以上投稿済みのタスクにコメントする)の場合は既存スレッドに返信するだけでOKですが、新規コメントの場合は新たにメールスレッドを作成したうえでタスクの"conversationThreadId"にスレッドIdを設定して関連付けする作業が必要になります。

 

【補足】"新しいタスク「{タスク名}」が作成されました"というコメントはコメントではない

新しいタスクを作成すると"新しいタスク「{タスク名}」が作成されました"というコメントが表示されますが、これは内部的にはコメントとしては扱われておらずメールスレッド内に存在しません。コメントが1つも付いていない="新しいタスク「{タスク名}」が作成されました"のみの状態を指します。

 

 


 

【1】Plannerタスクのコメントを"取得する"フロー

フロー全体

フロー解説

トリガーでtaskIdを指定

今回は検証用フローの為、トリガーでPlannerタスクのIdを指定しています。

 

Plannerコネクタ-タスクを取得するアクション

タスクを取得し”conversationThreadId"の有無を確認し、"conversationThreadId"が無い場合はコメントは存在しないのでフローを終了します。

条件アクションでは下記の式で"conversationThreadId"の有無を判断しています。

empty(outputs('タスクを取得する')?['body/conversationThreadId'])

 

Office 365 Group Mail コネクタ - 会話スレッドの投稿を一覧表示する

コメントはプランが存在するMicrosoft365グループのメールボックスにメールスレッドとして保持されていますので、Office 365 Group Mail コネクタで取得する事ができます。

グループIDは、プランが存在するMicrosoft365グループを指定します。

スレッドIDには"conversationThreadId"を指定します。

outputs('タスクを取得する')?['body/conversationThreadId']

 

実行イメージ

このようなコメントがされているタスクでは...

次のようなjson形式でコメントが取得できます。

[
  {
    "@odata.etag": "W/\"CQAAABYAAADak64k/GnYTLbTI5g9FKdeAAAAAAVS\"",
    "id": "AAMkAGRmOTgxOGFlLTA4NjEtNDU5NS05ZDdkLWYwMDQ4MTFlY2ZlZgBGAAAAAABbX7qWdR05Q5m_YhPuq6kFBwDak64k-GnYTLbTI5g9FKdeAAAAAAEMAADak64k-GnYTLbTI5g9FKdeAAAAAAlVAAA=",
    "createdDateTime": "2023-07-05T22:57:40Z",
    "lastModifiedDateTime": "2023-07-05T22:57:40Z",
    "changeKey": "CQAAABYAAADak64k/GnYTLbTI5g9FKdeAAAAAAVS",
    "categories": [],
    "receivedDateTime": "2023-07-05T22:57:40Z",
    "hasAttachments": false,
    "body": {
      "contentType": "html",
      "content": "<html><body><div>\r\n<div>\r\n<div>\r\n<p>コメントですよよよ</p></div></div></div>\r\n</body></html>"
    },
    "from": {
      "emailAddress": {
        "name": "Sasami (ささみ)",
        "address": "sasami**********************.com"
      }
    },
    "sender": {
      "emailAddress": {
        "name": "Sasami (ささみ)",
        "address": "sasami**********************.com"
      }
    }
  },
  {
    "@odata.etag": "W/\"CQAAABYAAADak64k/GnYTLbTI5g9FKdeAAAAAAVY\"",
    "id": "AAMkAGRmOTgxOGFlLTA4NjEtNDU5NS05ZDdkLWYwMDQ4MTFlY2ZlZgBGAAAAAABbX7qWdR05Q5m_YhPuq6kFBwDak64k-GnYTLbTI5g9FKdeAAAAAAEMAADak64k-GnYTLbTI5g9FKdeAAAAAAlWAAA=",
    "createdDateTime": "2023-07-05T23:13:28Z",
    "lastModifiedDateTime": "2023-07-05T23:13:28Z",
    "changeKey": "CQAAABYAAADak64k/GnYTLbTI5g9FKdeAAAAAAVY",
    "categories": [],
    "receivedDateTime": "2023-07-05T23:13:28Z",
    "hasAttachments": false,
    "body": {
      "contentType": "html",
      "content": "<html><body><div>\r\n<div>\r\n<p>返信する</p></div></div>\r\n</body></html>"
    },
    "from": {
      "emailAddress": {
        "name": "Sasami (ささみ)",
        "address": "sasami**********************.com"
      }
    },
    "sender": {
      "emailAddress": {
        "name": "Sasami (ささみ)",
        "address": "sasami**********************.com"
      }
    }
  }
]

あとはjsonを解析してコメントを取り出すだけです。

 


 

【2】Plannerタスクにコメントを"投稿する"フロー

フロー全体

フロー解説

トリガーでtaskIdを指定

今回は検証用フローの為、トリガーでPlannerタスクのIdと投稿するコメントを指定しています。

 

Plannerコネクタ-タスクを取得するアクション

タスクを取得し"conversationThreadId"の有無を確認しています。

条件アクションは下記の式で"conversationThreadId"の有無を判断して処理を分岐しています。

empty(outputs('タスクを取得する')?['body/conversationThreadId'])
  • "conversationThreadId"が無い(=コメントは存在しない)
    • 新規スレッドを作成しコメントを投稿
  • "conversationThreadId"がある(=コメントが存在する)
    • 既存スレッドに返信コメントを投稿

 

[はい]Office 365 Group Mail コネクタ-「スレッドを作成して新しいグループ会話を開始する」アクション

"conversationThreadId"が無い(既存のコメントがない)場合は、メールスレッドを作成します。

グループIDは、プランが存在するMicrosoft365グループを指定します。

新しいトピックは、Plannerでコメントを投稿した際と同じルールで設定しています。

タスク "@{outputs('タスクを取得する')?['body/title']}" のコメント

本文コンテンツは、コメントに設定するテキストを指定します。

 

[はい]Office 365 Groupコネクタ-HTTP要求を送信しますアクション

作成したメールスレッドのIdをPlannerタスクに設定してタスクとコメントを関連付けます。この処理はGraph APIで行っています。今回のUpdate plannerTaskはOffice 365 Groupコネクタの"HTTP要求を送信します"アクションで実行可能でしたのでプレミアムコネクタは不要です。

 

パラメーター
URI https://graph.microsoft.com/v1.0/planner/tasks/@{triggerBody()['text']}
メソッド PATCH
本文

{

"conversationThreadId":"@{outputs('スレッドを作成して新しいグループ会話を開始する')?['body/id']}"

}

コンテンツタイプ application/json
CustomHeader1 Prefer: return=representation
CustomHeader2 If-Match: @{trim(outputs('タスクを取得する')?['body/@odata.etag'])}

 

リクエストヘッダーの If-Match で更新するタスクを指定します。ここには、「タスクを取得するアクション」の"@odata.etag"を指定します。

ただ、値を直接指定してしまうとフロー上で値の参照が崩れてしまうため、この値には何も影響しないtrim関数で処理した結果を設定しています。 

 @{trim(outputs('タスクを取得する')?['body/@odata.etag'])}

 

update plannerTaskについてはこちらのページを参考にしました。

learn.microsoft.com

 

※[検証メモ]今回使用したGraphAPIのUpdate plannerTask およびget planner Taskは、HTTP with Azure ADコネクタ - HTTP要求を呼び出しますアクションでも実行可能な事を検証時に確認できました。

 

[いいえ] Office 365 Group Mailコネクタ - 会話スレッドに返信するアクション

"conversationThreadId"が存在する(コメントが投稿済み)場合は、メールスレッドが存在していますのでそのスレッドに対して返信を行います。

グループIDは、プランが存在するMicrosoft365グループを指定します。

スレッドIDには"conversationThreadId"を指定します。

outputs('タスクを取得する')?['body/conversationThreadId']

本文コンテンツは、コメントに設定するテキストを指定します。

 

 

さいごに

Plannerのコメント操作は調べても実現できず一旦断念していたのですが、Twitterでのおいしみさんと七草あんこさんのアドバイスがきっかけで実現することができました。お二人に最大限の感謝を✨✨✨