「全員ぼくにいいねしてよ！！！」を熱烈フォローするPower Automate フロー

# はじめに
動作イメージです。

https://twitter.com/ksgiksg/status/1682415339236388869?s=20

グループチャットのメンバーのうち、選択した投稿に対してリアクションしてくれていない人たちにメンション付きメッセージを投稿します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/f28a7574-a0ea-1d96-b7d5-5168cf6eec59.png)

同様にチャネルの投稿では、チームのメンバーを対象にフォロー投稿を行います。

# フローの解説
まずフローの全体像です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/92162679-09d0-8549-2963-fde326faf8e8.png)

大まかな構成としては、
 - 選択したメッセージをトリガーに
 - リアクションを集計
 - グループチャット or チームのメンバーを取得
 - リアクションしてくていれない人を抽出
 - メンションを取得してメッセージを作成
 - メッセージを投稿

といった順にフローが進みます。

## 選択したメッセージをトリガーに
フローを起動するトリガーです。
メッセージを選択したメニューから起動できるようにします。
選択したメッセージを対象にリアクションを集計することになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/efaca86f-7f99-0efe-a8b8-dbfa9a0a4122.png)

トリガーは`[選択したメッセージの場合]`です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/d420b14e-ece7-082f-6e96-3d2101a19f83.png)

アダプティブカードを編集して、フローの起動時に入力を追加することもできます。
今回は特に指定していませんが、**メンション付きで投稿するかどうかのチェックボックス**や、**フォローメッセージの文言を指定するテキスト入力欄**を作ると面白いかもしれません。

## リアクションを集計
`[メッセージ詳細を取得する]`で、メッセージにつけられたリアクションを取得します。
取得したリアクションから、リアクションしたユーザーのIDだけを取り出して、配列変数に格納します。(単純のため)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/d34fb749-cc0f-d270-3427-6267f0948588.png)

メッセージの種類は、グループチャットでもチャネルの投稿でもどちらの場合も`グループチャット`でＯＫです。
`会話ID`を指定すれば、チャネルの投稿でもちゃんと動きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/edc24193-c1a3-8de5-6b1a-8812d293a3a5.png)

取得したメッセージの詳細、リアクションからユーザーのIDのみを抽出します。
配列の加工には`選択`アクションをよく使います。

開始にはリアクションを指定したいのですが、動的なコンテンツから選択すると、何故か違ったプロパティが指定されてしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/141f5c19-6e65-7ffd-7de8-6c233d7a8811.png)

仕方がないので、関数の入力から以下の通り、直接指定してあげます。
```PowerFx:選択：開始
@{outputs('メッセージ詳細を取得する')?['body/reactions']}
```

マップにはユーザーのIDを指定します。
`キー値モードに切り替え`て、キーを持たない値のみの配列を作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/1b87759e-cf8e-e0f5-c84d-a82994a533d7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/4895a1de-6fa5-6c33-ef98-7089022ac0a5.png)
```PowerFx:選択：マップ
@{item()?['user/user/id']}
```


## グループチャット or チームのメンバーを取得
**グループチャット**か**チャネルのメッセージ**かで分岐を行います。
これはメンバー一覧を取得する方法がそれぞれ異なるためです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/d9f0f933-6498-332c-921d-98ec33fb9097.png)

条件分岐では、選択したメッセージから取得した情報に、**チャネルのID**が含まれるかどうかで判断します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/6c1ef992-2277-581b-6eb6-fae5c8834def.png)
```PowerFx:条件式の左辺
empty(triggerBody()?['teamsFlowRunContext']?['channelData']?['channel'])
```

### はい（グループチャット）の場合
チャネルIDの情報が空の場合はグループチャットと判断できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/aedffa0b-86c3-c3b1-ba69-4dfde665d348.png)

グループチャットの参加メンバーを取得するには`[List members]`を使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/69bb9009-2d0b-58a7-6d02-57c7829b4fbf.png)

取得したメンバー一覧から、また簡単のためにユーザーIDだけの配列を作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/2a245c12-3029-e8cf-c69c-f6541d116de9.png)

### いいえ（チャネルの投稿）の場合
チャネルIDの情報がある場合はチャネルの投稿です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/a6371dc8-d13c-011d-319e-10c9d8428f84.png)

チャネル投稿の場合はチームのメンバーを取得する必要がありますが、Teamsコネクタのアクションには該当するアクションが見つからないので、チームの裏にあるグループから取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/76f0609f-d477-e784-c1d3-e7f89c8eda4f.png)
```PowerFx:グループID
@{triggerBody()?['teamsFlowRunContext/ChannelData/Team/AadGroupId']}
```

:::note info
厳密には、プライベートチャネルの場合、チャネルのメンバーとチームのメンバーが一致しませんが、プライベートチャネルの投稿からはPower Automate のフローを起動できないので、今回は考慮していません。
:::

こちらの場合もユーザーIDだけの配列を作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/0976ff2c-00a4-1f3f-a7a8-d9b90aff4693.png)


## リアクションしてくていれない人を抽出
ここまでで取得したメンバー全員と、リアクションをした人の差分を取れば、リアクションしていない人が抽出できます。
また、自分にフォローしても仕方がないので、しれっとリアクションした人の中に自分も追加しておきます。(自分の投稿には自分でリアクションしていないことが多いと思うので…)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/6405870a-2be3-e87b-b7c2-4cccffc156e7.png)

`[マイプロフィールの取得]`から自分のIDを取得して、配列変数に追加しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/9d83d57b-5f9a-829a-94e5-506d37876b9b.png)

差分を取得するために`[アレイのフィルター処理]`を行います。
メンバー全員を対象に、条件はそれぞれの項目がリアクションした人の中に含まれるかどうかで判定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/aaa67e64-a089-8332-03c4-600770bf7ef4.png)
```PowerFx:条件
@not(contains(variables('reactionUsersID'), item()))
```

フィルタ結果の確認として、空に向かってメンションしてしまわないように、「全員がリアクションしていた場合＝リアクションしていない人がいなかった場合」に、フローを終了させます。
自分にだけ通知を送るようにしてもいいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/d111fa74-49ff-5ce5-0759-749fa40025e8.png)


## メンションを取得してメッセージを作成
抽出したリアクションしていないメンバーに対して、`[ユーザーの @mention トークンを取得する]`でメンションを付けます。
取得したメンションは文字列変数に順次追加し、ついでにメッセージも追加しておきます。(`<br>`は改行タグです)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/08b250ae-3da0-ca2b-2b7e-21d38dff62b4.png)



## メッセージを投稿
最後に、作成したメッセージを投稿します。
ここもまた、**グループチャット**か**チャネルのメッセージ**かで返信の投稿方法が異なるため、条件分岐を行います。(分岐条件は前と同じ)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/306852a7-df9c-9b01-a38c-14e392e6426e.png)

グループチャットの場合は`会話ID`を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/b18a6374-1b2b-6b6f-8ba3-735875620b60.png)

チャネル投稿の場合は、指定項目が多いですが、以下のように入力すればOKです。
特に`Message ID`に返信先のIDを指定しないといけないところが間違えやすいので注意してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/dde74a93-76b6-6f76-2978-f872cec5dbd8.png)


# おわりに
最近追加されたアクション、`[List members]`でグループチャットのメンバーが取れるようになったのが大きなポイントでした。
今回はメンションを付けてフォローをしましたが、CSVなどに吐き出して集計するようなフローも需要がありそうですね。


今回の解説は以上です。