Power Automate でプライベートチャネルを作成する

# はじめに
Teamsのコネクタに「Microsoft Graph HTTP 要求を送信する」が追加され、用意されていないアクションになくてもできることが増えました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/f0c94fcc-9018-cb24-6703-bac7a2d82cda.png)

> リアクションを追加することもできます
> [チャネルのすべての投稿にイイネするフロー
](https://qiita.com/ksgiksg/items/f9e1ce9f8df8403d607f)

この記事では、標準のアクションではできなかった、プライベートチャネルの作成に挑戦します。

:::note info
「チャンネルを作成します」アクションでは、チャネルの種類を指定することができず、標準チャネルのみが作成できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/efba1084-0a6b-2a11-6b02-02d3d06f0706.png)
:::

# Microsoft Graph APIを使用する
Microsoft Graph HTTP 要求を使用するために、まずはリファレンスページを確認しましょう。

https://learn.microsoft.com/ja-jp/graph/api/overview?view=graph-rest-1.0


このページの左側のナビゲーションを辿って、チャネルを作成する方法を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/36b9af07-e553-261a-02bc-95fa78ba429c.png)

https://learn.microsoft.com/ja-jp/graph/api/channel-post?view=graph-rest-1.0&tabs=http

実行例もちゃんと書いてくれているので、こちらの例を参考に進めていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/fe40b3c5-5cd4-7766-a70e-e22e56e811b0.png)



# 検証準備
動作検証用にチームを作成しました。
現在は、デフォルトで作成される標準チャネルのみの状態です。

自分以外に、チームの所有者である`Aさん`と、メンバーである`Bさん`を追加しています。
また、後ほどチームに参加していない`Cさん`にも出てきてもらう予定です。

![2024-04-06_19h52_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/809093ce-eaa1-7583-e70a-2bbccb18dc0a.png)

# 実行例
## 例1:自分が所有者となるプライベートチャネル
まずは、リファレンスページの例２の通りにやってみましょう。
`membershipType`を`private`にすることでプライベートチャネルが作成できるようです。

チャネル名（`displayName`）やチャネルの説明（`description`）の他に、チャネルを作成する親となるチームのIDや、チャネルの所有者として追加するユーザーのIDが必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/f3c02062-c24e-67e1-35f9-1c4450097da5.png)

チャネル名とチャネルの説明は変数として指定しておきます。
チームのIDとユーザーIDは、あらかじめ調べておいてもよいのですが、Power Automate のアクションを使って以下のように取得することが可能です。
![2024-04-06_19h53_38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/33510113-93c1-2d6c-e5ec-bbf57ff0d978.png)

変数としてあらかじめ設定した内容や、取得した情報を使って、リファレンスページの通りにアクションを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/a0b167c6-7fc4-453b-59dd-ab91e11f3efe.png)

```url:URL
https://graph.microsoft.com/v1.0/teams/@{outputs('チームの取得')?['body/id']}/channels
```

```json:本文
{
  "@odata.type": "#Microsoft.Graph.channel",
  "membershipType": "private",
  "displayName": "@{variables('チャネル名')}",
  "description": "@{variables('チャネルの説明')}",
  "members":
     [
        {
           "@odata.type":"#microsoft.graph.aadUserConversationMember",
           "user@odata.bind":"https://graph.microsoft.com/v1.0/users('@{outputs('マイ_プロフィールの取得_(V2)')?['body/id']}')",
           "roles":["owner"]
        }
     ]
}
```
```plaintext:コンテンツタイプ
application/json
```

結果は以下の通り、指定したチームに自分が所有者であるプライベートチャネルを作成することができました。
![2024-04-06_21h57_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/f44327e1-a657-de93-bbd0-652c82f18e11.png)

チャネルの説明も設定できていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/601a4342-bee3-6aa4-3ef3-606e3adb2f15.png)

## 例2:自分の他にもう1人所有者を追加する
所有者をもう1人設定してみます。
まずはIDの確認のため、「ユーザー プロフィールの取得 (V2)」アクションを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/d2e62260-c6d7-dd95-e125-8fe20723e2bf.png)

HTTP要求本文の`members`にも同じ形式でもう1人分の情報を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/4bd46289-ff16-637c-a679-640ff5232b7f.png)
```json:本文
{
  "@odata.type": "#Microsoft.Graph.channel",
  "membershipType": "private",
  "displayName": "@{variables('チャネル名')}",
  "description": "@{variables('チャネルの説明')}",
  "members":
     [
        {
           "@odata.type":"#microsoft.graph.aadUserConversationMember",
           "user@odata.bind":"https://graph.microsoft.com/v1.0/users('@{outputs('マイ_プロフィールの取得_(V2)')?['body/id']}')",
           "roles":["owner"]
        },
        {
           "@odata.type":"#microsoft.graph.aadUserConversationMember",
           "user@odata.bind":"https://graph.microsoft.com/v1.0/users('@{outputs('ユーザー_プロフィールの取得_(V2)')?['body/id']}')",
           "roles":["owner"]
        }
     ]
}
```
実行すると、所有者が2人のプライベートチャネルが作成できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/714f2f0f-de1e-6a11-9637-6144bfe9f433.png)



## 例3:自分以外にメンバーを追加する
次は、所有者ではなく、メンバーとしてもう1人追加します。
例2のフローからメンバーにしたいユーザーの`roles`を空にすればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/1ec535d9-9b11-d57a-2335-6fbf2cefd235.png)
```json:本文
{
  "@odata.type": "#Microsoft.Graph.channel",
  "membershipType": "private",
  "displayName": "@{variables('チャネル名')}",
  "description": "@{variables('チャネルの説明')}",
  "members":
     [
        {
           "@odata.type":"#microsoft.graph.aadUserConversationMember",
           "user@odata.bind":"https://graph.microsoft.com/v1.0/users('@{outputs('マイ_プロフィールの取得_(V2)')?['body/id']}')",
           "roles":["owner"]
        },
        {
           "@odata.type":"#microsoft.graph.aadUserConversationMember",
           "user@odata.bind":"https://graph.microsoft.com/v1.0/users('@{outputs('ユーザー_プロフィールの取得_(V2)')?['body/id']}')",
           "roles":[]
        }
     ]
}
```
実行すると、メンバーが追加されたプライベートチャネルが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/107ab64a-b477-9fa0-80d4-3ea0f4a79ef1.png)


## 例4:自分の代わりの所有者を設定する
今度は自分が参加しない状態でも作成できるのかを確認してみます。
Aさんのみを所有者として設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/9646667e-387e-b744-b34b-ca396ccdf4ce.png)
```json:本文
{
  "@odata.type": "#Microsoft.Graph.channel",
  "membershipType": "private",
  "displayName": "@{variables('チャネル名')}",
  "description": "@{variables('チャネルの説明')}",
  "members":
     [
        {
           "@odata.type":"#microsoft.graph.aadUserConversationMember",
           "user@odata.bind":"https://graph.microsoft.com/v1.0/users('@{outputs('ユーザー_プロフィールの取得_(V2)')?['body/id']}')",
           "roles":["owner"]
        }
     ]
}
```
実行してみると、フローが成功しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/7c3dd3de-0b7e-d917-ca1c-dea6e91d1543.png)

自分の画面からはチャネルの存在が確認できませんが・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/d503f538-be3c-a4a6-d44c-f4c23a752dff.png)

Aさんのアカウントで確認すると、確かに作成できています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/a570b969-fb26-23a8-6bcb-4a1efb676b10.png)

自分が参加していなくても、ユーザーの代わりにプライベートチャネルを作成できることがわかりました。

## 例5:メンバー0人で作成(エラー)
所有者の指定が少しややこしかったので、試しに所有者なしで登録できるか確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/a2fe93ce-a1ba-8bc8-bebb-c46fffb22cb6.png)
`members`を空の配列にしてメンバー無しで設定してみます。
```json:本文
{
  "@odata.type": "#Microsoft.Graph.channel",
  "membershipType": "private",
  "displayName": "@{variables('チャネル名')}",
  "description": "@{variables('チャネルの説明')}",
  "members":[]
}
```

結果は以下のようにエラーになってしまいました。
プライベートチャネルには少なくとも1人の参加者が必要なようです。

:::note alert
**エラーの詳細**
> conversationMembers cannot be empty.
> (conversationMembersを空にすることはできません。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/ef57a7bf-032e-0da5-fdcf-db9136e7ed5a.png)
:::

## 例6:所有者無しでメンバーのみ(エラー)
今度は1人のメンバーを追加しますが、所有者権限なしで追加できるかを確認してみます。
`roles`を空の配列にすることで、特権なしのメンバーとして追加してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/897c910e-41c8-7093-f463-6fa8835681b3.png)

```json:本文
{
  "@odata.type": "#Microsoft.Graph.channel",
  "membershipType": "private",
  "displayName": "@{variables('チャネル名')}",
  "description": "@{variables('チャネルの説明')}",
  "members":
     [
        {
           "@odata.type":"#microsoft.graph.aadUserConversationMember",
           "user@odata.bind":"https://graph.microsoft.com/v1.0/users('@{outputs('マイ_プロフィールの取得_(V2)')?['body/id']}')",
           "roles":[]
        }
     ]
}
```

結果は以下のようにエラーになってしまいました。
プライベートチャネルには少なくとも1人の参加者が必要なだけでなく、所有者が必要なようです。

:::note alert
**エラーの詳細**
> CreateChannel_Private: Cannot create private channel, at least one member should be an owner.
> (少なくとも一人のメンバが所有者でなければなりません。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/06b4ccf2-f047-cad5-8057-3815a7ba0ee1.png)
:::

## 例7:チームに参加していないユーザーを追加(エラー)
次に、チームに参加していないCさんを追加してみます。
例3のフローから、追加するメンバーをCさんに変更するだけですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/20f89514-5860-c53e-12a3-28a19497dddf.png)

結果は以下のようにエラーになってしまいました。
当たり前ですが、チームに参加していないユーザーをプライベートチャネルに追加することはできないようです。

:::note alert
**エラーの詳細**
> CreateChannel_Private: Cannot create private channel, user 8:orgid:{CさんのID} is not part of team {チームID}. (Note : If the team is created in migration mode then finalize the team and add this user to the team before creating private channel)
> (プライベートチャネルを作成できません。ユーザー{CさんのID}はチーム{チームID}のメンバーではありません。(注意 : チームがマイグレーションモードで作成された場合、プライベートチャネルを作成する前にチームを確定し、このユーザをチームに追加してください))

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/17820b0e-ad1b-eed3-7ab9-2f3b76801371.png)
:::

## 例8:プライベートチャネルを作り続ける
最後にプライベートチャネルの作成上限を超えるまで、プライベートチャネルを作成し続けてみます。
プライベートチャネルは30までしか作成できないので、途中でエラーになる見込みです。

新たに、一般チャネル以外に存在しない、まっさらなチームを作成しておきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/8f5bd010-0aa6-f3c9-2b7c-3d453afd3227.png)

フローではループを使って、いつまでもプライベートチャネルを作成するように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/56101668-8645-2453-0b9b-6e7bc9976ec5.png)

:::note info
正確には、デフォルトの制限回数の60回まで実行するようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/a64ee3cb-1184-4055-8af4-ce2657359f01.png)
:::

フローを実行すると、次々にプライベートチャネルが作成されていき・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/2254f4b4-e3ec-0b97-3bc0-91c8af93129b.png)

？？？？？？？？？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/16309398-603b-bcbc-0523-63f3d6d146b9.png)

一瞬、30を超えても実行され続けたように見えましたが、作成されたチャネルにアクセスしようとすると、削除されているようでした。（そもそも削除されていない？）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/3eecb8d1-c658-4c9c-29bb-59e5f6c13fa3.png)

フローの方でも、予想通り30回を超えたところでエラーになっています。

:::note alert
**エラーの詳細**
> An unexpected error(Type = MaxPrivateChannelLimitExceeded) occurred. Please try again.
> (予期しないエラー(Type = MaxPrivateChannelLimitExceeded)が発生しました。再試行してください。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/a8543a59-bf0e-9049-df18-9010a67a90b6.png)

:::

# おわりに
Teamsのコネクタに「Microsoft Graph HTTP 要求を送信する」が追加されたことを記念して、今までできなかったプライベートチャネルの作成ができるようになりました。
ただし、プライベートチャネルの乱立は避けた方がよいとされていますので、使用する場面は考えた方がいいでしょう。

https://blog.trainocate.co.jp/blog/teams01_020

https://dekiru.net/article/23452/

今回はゲストユーザーの追加や共有チャネルの作成については触れられませんでしたが、同じようにMicrosoft Graph リファレンスページを確認して真似すればPower Automate でも実行できます。

標準アクションでできないことがあれば、一度APIを確認してみるのもよいのではないでしょうか？(実運用として導入するかはともかく😇)