MS Teams Channel Conversation "Backup"
Jan 1, 2020
msgraph
teams
We use Microsoft Teams, and probably as most, create a new team when it was first released, however have now decided to move to a new Team. This is all fine, but when we went looking for a “migration” pathway, there wasn't one. Instead we settled on making a backup/copy for historical purposes.
I went searching PowerShell for cmdlets to “backup” Teams and didn't find any. I then went searching the Microsoft Graph API and found the Teams API resources. One of the endpoints was called List Channel Messages (Link below), bingo!
https://docs.microsoft.com/en-us/graph/api/channel-list-messages
When you request the ms graph api, you need to provide a bearer token in the authorisation header. To get a token you need to setup an Azure AD Application, and go through one of the oauth flows.
With my app ready, I decided to use PowerShell to make the necessary authentication requests, get my access token, then makes requests to the Teams graph to list the channel messages.
Note that we have our access token we're ready to start poking the MS Graph API.
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
# This function takes 3 parameters, then pulls messages from the MS Graph API
function GetMessages {
param ([String]$team_id, [String]$channel_id, [String]$file_name)
# The initial MS Graph request to the MS Teams List Channel Messages endpoint
$uri = "https://graph.microsoft.com/beta/teams/$team_id/channels/$channel_id/messages"
do {
# Make your first request to the API
# Note: The $headers variable is a hash table with your Authorization header and Bearer token etc
$res = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get -SslProtocol:Tls12
# Get the next URL
$next = $res."@odata.nextLink"
# If there is a next URL, update $uri ready for the next iteration
if ($next) { $uri = $next }
# Loop through each message
$res.value | ForEach-Object {
# Assign the message content to $raw so that we can strip out the text
$raw = $_.body.content
# This regex will strip out all HTML tags, just leaving the text content
$msg = $raw -replace '<[^>]+>'
# Assign the message created datetime
$date = $_.createdDateTime
# Build up the HTML rows for each message, we will use this later. Note, you can use <table> or any other style you prefer
$body += '<hr><div><time datetime="' + $date + '">' + $date + '</time> | ' + $msg + '</div>'
}
# I put a sleep in because i kept hitting the rate limitations without it
Start-Sleep -Milliseconds 500
# Keep looping as long as there is a Next URL
} while ($null -ne $next)
# This is the HTML template. We will "insert" the rows ($body) we built above. Again, feel free to style this however you like
$template = @'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style>
body {font-size: small}
img {display: none}
hr {border-top: 0.3px solid lightgrey}
</style>
</head>
<body>
...body
</body>
</html>
'@
# Here we replace "...body" with our HTML body and save it to file
$template -replace '...body', $body | Out-File -Force "./$file_name.html"
$body = $null
} # This is the end of the funtion
# Here we setup some starting variables.
$team_id = 'nnn-nnn-nnn-nnn-nnn'
$channel_id = 'nnn@thread.skype'
$channel_displayName = 'nnn.html'
# Here we call the GetMessage function. Obviously you would put this into a foreach loop and loop through each channel in your Team
GetMessages -team_id $team_id -channel_id $channel_id -file_name $channel_displayName
~~~
</div>
|