PowerShellでTeamsのチャット履歴をcsvに出力する

## 概要

Microsoft Teamsのチャット履歴を手軽に出力する方法を模索し、Graph APIによる出力にたどり着きました。
今回は、PowerShellを用いてチャット履歴を出力し、エクセルで見られるようにcsv形式で保存するまでをご紹介します。

## 完成物のイメージ

自分(contoso)と相手(user1)が以下のようなやり取りをしたとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2745318/e361e8fe-ebc6-81b3-4a00-9c28f19a4d4d.png)

このとき、次のようなcsvファイルが出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2745318/6f00d224-719f-46f3-f3fc-97e7ab991df6.png)

以下がポイントです。
- リッチテキストで書かれた投稿内容を、可能な限りテキストに変換している
- 添付ファイルがある場合は、格納されている場所のURLを取得している
    - 複数の添付ファイルがある場合は、";"を区切り文字としてすべて記載している

## 事前準備
### Microsoft Graph PowerShell SDKのインストール

(参考: https://docs.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0)
PowerShell で以下のコマンドを実行します。

```PowerShell:PowerShell
Install-Module Microsoft.Graph
```

完了したら、以下のコマンドを実行してみます。

```PowerShell:PowerShell
Get-InstalledModule Microsoft.Graph*
```

ここで何も表示されなかったらインストールに失敗しているので、リトライしてみてください。

### チャットIDの取得

Web版のTeamsで、今回取得したいチャットを開きます。
すると、URLは以下のようになっているはずです。

```
https://teams.microsoft.com/_#/conversations/19:......@unq.gbl.spaces?ctx=chat
または
https://teams.microsoft.com/_#/conversations/19:......@thread.v2?ctx=chat
```

上記URLの中の `19:......@unq.gbl.spaces` や `19:......@thread.v2` の部分がチャットIDに該当します。

## 実行スクリプト

まずは完成したスクリプトをお見せした後に、解説を加えます。

### 完成品

以下が今回作成した `GetChats.ps1` です。

```PowerShell: GetChats.ps1
Import-Module Microsoft.Graph.Teams
$RequiredScopes = @("Chat.Read")
Connect-MgGraph -Scopes $RequiredScopes

$chatId = "<取得したチャットID>"
$chatMessages = Get-MgChatMessage -ChatId $chatId -All -PageSize 50

$csv = @()
foreach ($message in $chatMessages) {
    if ($message.body.contentType -eq "html") {
        $html = New-Object -ComObject "HTMLFile"
        $html.IHTMLDocument2_write($message.body.content)
        $message.body.content = $html.IHTMLDocument2_body.innerText
    }
    $data = New-Object PSObject | Select-Object DateTime, From, Content, Attachments
    $data.DateTime = $message.createdDateTime
    $data.From = $message.from.user.displayName
    $data.Content = $message.body.content
    $temp = $message.attachments | ForEach-Object { $_.ContentUrl}
    $data.Attachments = $temp -join "; "
    $csv += $data
}
$csv | Export-Csv -Path "chat.csv" -NoTypeInformation -Encoding UTF8

Disconnect-MgGraph
```

### 解説
#### Graph APIに接続する

```PowerShell: PowerShell
Import-Module Microsoft.Graph.Teams
$RequiredScopes = @("Chat.Read")
Connect-MgGraph -Scopes $RequiredScopes
```
まず、インストールしたSDKのうち、Teamsに関係する `Microsoft.Graph.Teams` をインポートします。
続いて、チャットのメッセージを取得するのに必要なアクセス許可は何かを調べたところ、`Chat.Read`であると書いてありました。
よって、このアクセスを許可するように指定しています。
(より大きな `Chat.ReadWrite` 権限でも可能ですが、今回は必要最低限のものを指定しています)
(参考: https://docs.microsoft.com/ja-jp/graph/api/chat-list-messages)

#### チャット履歴を取得する

```PowerShell: PowerShell
$chatId = "<取得したチャットID>"
$chatMessages = Get-MgChatMessage -ChatId $chatId -All -PageSize 50
```

チャットIDで指定したチャットの履歴を取得しています。
その他のパラメータは以下の情報をご覧ください。
https://docs.microsoft.com/en-us/powershell/module/microsoft.graph.teams/get-mgchatmessage

#### それぞれのメッセージの情報を加工する

以下のforeach文で、`$csv` オブジェクトに1つ1つ情報を加えています。

```PowerShell: GetChats.ps1
$csv = @()
foreach ($message in $chatMessages) {
    if ($message.body.contentType -eq "html") {
        $html = New-Object -ComObject "HTMLFile"
        $html.IHTMLDocument2_write($message.body.content)
        $message.body.content = $html.IHTMLDocument2_body.innerText
    }
    $data = New-Object PSObject | Select-Object DateTime, From, Content, Attachments
    $data.DateTime = $message.createdDateTime
    $data.From = $message.from.user.displayName
    $data.Content = $message.body.content
    $temp = $message.attachments | ForEach-Object { $_.ContentUrl}
    $data.Attachments = $temp -join "; "
    $csv += $data
}
```

foreach内の前半部分では、メッセージがHTML形式であったとき (リッチテキストだったとき)、その中のテキスト情報のみを抽出しています。
後半部分では、それぞれの列に情報を加えています。
ポイントとしていた、添付ファイルの扱いについては、以下の場所で行っています。

```PowerShell: GetChats.ps1
    $temp = $message.attachments | ForEach-Object { $_.ContentUrl}
    $data.Attachments = $temp -join "; "
```

取得した情報のうち、添付ファイルに関する情報(`$message.attachments`)には、ファイル名やファイルIDなど様々な情報が載っています。
ここでは、そのうちのURL部分のみを抽出しています。
さらに、添付ファイルが複数ある場合は `; ` でURLを区切っています。

#### csvに出力

```PowerShell: PowerShell
$csv | Export-Csv -Path "chat.csv" -NoTypeInformation -Encoding UTF8
```

`Export-Csv` コマンドを用いて、csvに出力します。
`-Encoding UTF8` を指定しないと、日本語が文字化けしてしまうので、必ずつけるようにしましょう。

#### 接続を閉じる

最後に、以下のコマンドで接続を閉じます。

```PowerShell: PowerShell
Disconnect-MgGraph
```

## 終わりに

今回は、Teamsのチャット履歴を簡単にcsvに出力する方法をご紹介しました。
`Get-MgChatMessage` コマンドのレスポンスには今回使っていない情報もあるので、適宜カスタマイズしてみてください。