…when a teacher would like to have a Team with their students and would like to have a channel for each of them however each of the channels should be locked such that the teacher and the respective student can access it. No student should view the channel of another student but the teacher should be able to view every student’s channel.
Synopsis
This script will loop through the Teams listed in Teams.csv
and for each of the members of the team, it will create private channels with the display name as the name of the member. Microsoft has some limitations put on the channel display names so if the member name contains any of the characters # % & * { } / \ : < > ? + | ‘
then the script removes those character(s). Also, if the member name is more than 50 characters, it will be trimmed to 50 characters. The channel will be private, accessible only to the member and the teacher specified in the $teacherEmail
variable.
Ensure that the team groupIds are correct on the CSV, if incorrect team names are given, there will be no error messages returned. It will be simply ignored.
Pre-requisites
- Add a column named
groupId
with the group ids of the teams toTeams.csv
saved in the same directory as the script. - Save the teacher email to the
$teacherEmail
variable. Ensure that they are a member/owner of the team already.
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<#
.SYNOPSIS
Create/Edit private channels within multiple Teams on Microsoft Teams.
.DESCRIPTION
This script will loop through the teams listed in $csvPath and for each of the 'members' of the teams, it will create private channels with the display name as the name of the respective member. If the customer chooses to edit the private channels within the Team(s) then it will loop through the existing private channels within the Team(s) and add the teacher emails in the $teacherEmails array.
Microsoft has setup limitations on the channel display names - if the member name contains any of the characters # % & * { } / \ : < > ? + | ' then the script will remove those character(s). Also, if the member name is more than 50 characters, it will be trimmed to 50 characters. The channel will be private, accessible only to the member and the teachers specified in the $teacherEmails array.
1. Ensure that the team groupIds are correct on the CSV, if incorrect groupIds are given, there will be no error messages returned. It will be simply ignored.
2. Before running the script as .\teamsChannels.ps1: Add a column named groupId with the group ids of the teams to the csv. Save the teacher emails to the $teacherEmail array.
3. Teacher emails in the $teacherEmail array must be 'owner's of the team(s) already - this is not handled by the script as of now as the requirement did not demand it. If they are not 'owner', there will be a channel created with the teacher name: which is not a desired output.
4. Sometimes there are exceptions returned and the script would fail to create channels but there is no issue with re-running the script in those cases.
5. You might want to try the extensive GraphAPI version here: https://code.nevinpjohn.in/teamsGraph
#>
using namespace System.Management.Automation.Host
$groups= @()
$teacherEmails = @('[email protected]', '[email protected]')
$csvPath = "Teams.csv" #path to the csv that have the groupId
function GetTeamGroupIds{
Import-Csv $csvPath | ForEach-Object{
Write-Host -ForegroundColor Yellow "Getting the team details of " $_."groupId"
try {
$groups += Get-Team -GroupId $_."groupId"
Write-Host -ForegroundColor Green $_."groupId" "fetched."
}
catch {
Write-Host -ForegroundColor Red
Write-Host -ForegroundColor Red $_
}
}
if ($groups.count -gt 0) {
$confirmation = Read-Host $groups.groupId.count"teams to process, Took note of exceptions, if any? (y/n)"
if ($confirmation -eq 'y') {
Clear-Host
Write-Host -ForegroundColor Green "Number of Teams to process : "$groups.groupId.count
Create-Choice
}
}else {
Write-Host $groups.count
Write-Host -ForegroundColor Yellow "--------------------------------"
Write-Host -ForegroundColor Red "No Teams found."
Write-Host -ForegroundColor Yellow "--------------------------------"
}
}
function CreatePrivateChannels{
Write-Host -ForegroundColor Yellow "--------------------------------"
Write-Host -ForegroundColor Blue "Trying to create Channels."
Write-Host -ForegroundColor Yellow "--------------------------------"
foreach ($group in $groups){
Write-Host -ForegroundColor Magenta "Creating Channels for the Team:-"$group.DisplayName
try {
($channelsList = Get-TeamChannel -GroupId $group.groupId -MembershipType Private) > $null
($teamMembersForThisGroup = Get-TeamUser -GroupId $group.groupId -Role member) > $null
foreach ($member in $teamMembersForThisGroup){
$channelExists = $false #assuming the channel does not exist, caution - this is not fool proof as it may result in creating duplicate channels IF the existing channel name for the member was formatted other than the method below. I can't think of a better method so that's that.
$channelName = $member.name -replace "[#%&*{}/\\:<>?+|']" #can't contain the characters # % & * { } / \ : < > ? + | ' as per MS guidelines.
$channelName = $channelName.subString(0, [System.Math]::Min(50, $channelName.Length)) #Names must be 50 characters or less as per the MS guidelines.
$channelName = $channelName.Trim() #Remove whitespaces from the beginning and end of the string
if ($channelsList.DisplayName.count -gt 0){
Foreach ($existingChannel in $channelsList) {
if ($existingChannel.DisplayName -eq $channelName) {
$channelExists = $True
break
}
}
}
if ($channelExists){
Write-Host -ForegroundColor Blue "The channel name" $channelName "exists in" $group.DisplayName
} else {
Write-Host -ForegroundColor Yellow "The channel name" $channelName "does not exist in" $group.DisplayName "hence creating..."
(New-TeamChannel -GroupId $group.groupId -DisplayName $channelName -MembershipType Private -Owner $member.User) > $null
Start-Sleep -Seconds 3
}
#As per MS docs: To turn an existing Member into an Owner, first Add-TeamChannelUser -User foo to add them to the members list, then Add-TeamChannelUser -User foo -Role Owner to add them to owner list hence the two commands.
foreach($teacherEmail in $teacherEmails){
try{
(Add-TeamChannelUser -GroupId $group.groupId -DisplayName $channelName -User $teacherEmail) > $null
Start-Sleep -Seconds 3
(Add-TeamChannelUser -GroupId $group.groupId -DisplayName $channelName -User $teacherEmail -Role Owner) > $null
Write-Host -ForegroundColor Green "Added" $teacherEmail "as owner of the Channel name : " $channelName
}
catch{
Write-Host -ForegroundColor Red $_
}
}
}
Write-Host -ForegroundColor Yellow "--------------------------------"
}
catch {
Write-Host -ForegroundColor Red "-----------------------------------"
Write-Host -ForegroundColor Yellow "Team name : " $group.DisplayName
Write-Host -ForegroundColor Yellow "Channel name : " $channelName
Write-Host -ForegroundColor Yellow "Member name : " $member.name
Write-Host -ForegroundColor Yellow "Member name : " $member.User
Write-Host -ForegroundColor Red $_
Write-Host -ForegroundColor Red "-----------------------------------"
}
}
$groups.clear()
Disconnect-MicrosoftTeams
Write-Host -ForegroundColor Green "Disconnected from Teams PS Session."
}
function EditPrivateChannels{
Write-Host -ForegroundColor Yellow "--------------------------------"
Write-Host -ForegroundColor Blue "Trying to Edit the Channels."
Write-Host -ForegroundColor Yellow "--------------------------------"
foreach ($group in $groups){
Write-Host -ForegroundColor Magenta "Editing Private Channels for the Team:-"$group.DisplayName
try {
($channelsList = Get-TeamChannel -GroupId $group.groupId -MembershipType Private) > $null
if ($channelsList.DisplayName.count -gt 0){
foreach ($channel in $channelsList){
foreach($teacherEmail in $teacherEmails){
(Add-TeamChannelUser -GroupId $group.groupId -DisplayName $channel.DisplayName -User $teacherEmail) > $null
Start-Sleep -Seconds 3
(Add-TeamChannelUser -GroupId $group.groupId -DisplayName $channel.DisplayName -User $teacherEmail -Role Owner) > $null
Write-Host -ForegroundColor Green "Added" $teacherEmail "as owner of the Channel name : " $channel.DisplayName
}
}
}else{
Write-Host -ForegroundColor Yellow "No private channels found in:-" $group.DisplayName
}
Write-Host -ForegroundColor Yellow "--------------------------------"
}
catch {
Write-Host -ForegroundColor Red "-----------------------------------"
Write-Host -ForegroundColor Yellow "Team name : " $group.DisplayName
Write-Host -ForegroundColor Yellow "Channel name : " $channe.DisplayName
Write-Host -ForegroundColor Red $_
Write-Host -ForegroundColor Red "-----------------------------------"
}
}
$groups.clear()
Disconnect-MicrosoftTeams
Write-Host -ForegroundColor Green "Disconnected from Teams PS Session."
}
function Create-Choice {
$EditPrivateChannels= [ChoiceDescription]::new('&EditPrivateChannels', 'EditPrivateChannels')
$CreatePrivateChannels = [ChoiceDescription]::new('&CreatePrivateChannels', 'CreatePrivateChannels')
$options = [ChoiceDescription[]]($EditPrivateChannels, $CreatePrivateChannels)
$custChoice = $host.ui.PromptForChoice('What do you want to do?', '', $options, 1)
switch ($custChoice) {
0 { EditPrivateChannels }
1 { CreatePrivateChannels }
}
}
try{
$auth = Connect-MicrosoftTeams
GetTeamGroupIds
}
catch {
Write-Host -ForegroundColor Red $_
}