Skip to content

Commit b5ba3d0

Browse files
Create TheoryCrafted_Sync_FuncNum_Improved.ps1
1 parent e94a454 commit b5ba3d0

1 file changed

Lines changed: 123 additions & 0 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# DISCLAIMER:
2+
# theoretically this new script and the implementations mentioedn in "Testmark.ps1" could improve the efficiency of the original script by around 5,5x
3+
# now includes better data structure usage, a better sorting algorithm (no longer an object sort but a unique key comparison aka binary), and process batching of API calls
4+
# theoretical API calls have been reduced down from 9.009.000 to 456.001
5+
# total runtime has theoreticall reduced from 39 hours on average to around 7 hours
6+
7+
8+
9+
10+
11+
# Parameters
12+
$batchSize = 20
13+
$folderName = "Func Numbers"
14+
$TestUserId = "<yourTestUserId>"
15+
$targetType = "User" # or "Group"
16+
$contactListSiteCollectionId = "<yourSiteCollectionId>"
17+
$contactListId = "<yourListId>"
18+
$e5GroupId = "<yourE5GroupId>"
19+
20+
# Logging Function (assumed implemented)
21+
function WriteLog { param($msg) ; Write-Output $msg }
22+
23+
# Fetch All Contacts Once
24+
[array]$data = Get-MgSiteListItem -SiteId $contactListSiteCollectionId -ListId $contactListId -ExpandProperty "Fields" -All
25+
26+
$contacts = [System.Collections.Generic.List[Object]]::new()
27+
foreach ($item in $data) {
28+
$fields = $item.Fields.AdditionalProperties
29+
$contact = [PSCustomObject]@{
30+
id = $item.Id
31+
givenName = $fields.field_4
32+
surname = $fields.field_3
33+
businessPhones = $fields.Title
34+
officeLocation = $fields.field_5
35+
status = if ($fields.Status -eq $null) { "" } else { $fields.Status }
36+
}
37+
$contacts.Add($contact)
38+
}
39+
WriteLog "[INFO] Loaded $($contacts.Count) contacts."
40+
41+
# Fetch All Users into Hash Table
42+
$userIdTable = @{}
43+
foreach ($member in $members) {
44+
try {
45+
$userId = if ($targetType -eq "User") { $TestUserId } else { $member.Id }
46+
$memberDets = Get-MgUser -UserId $userId
47+
$userIdTable[$member.Id] = $memberDets.UserPrincipalName
48+
} catch {
49+
WriteLog "[ERROR] Error retrieving member: $($_.Exception.Message)"
50+
}
51+
}
52+
WriteLog "[INFO] Prefetched $($userIdTable.Count) users."
53+
54+
# Fetch E5 Group Members Once
55+
$e5GroupMembers = Get-MgGroupMember -GroupId $e5GroupId -ConsistencyLevel eventual -All
56+
$e5MembersTable = @{}
57+
foreach ($member in $e5GroupMembers) {
58+
$e5MembersTable[$member.UserPrincipalName] = $true
59+
}
60+
WriteLog "[INFO] Loaded $($e5MembersTable.Count) E5 members."
61+
62+
# Function: Check if User is E5
63+
function IsE5Member {
64+
param($userPrincipalName)
65+
return $e5MembersTable.ContainsKey($userPrincipalName)
66+
}
67+
68+
# Main Processing Loop
69+
foreach ($member in $members) {
70+
$memberId = $userIdTable[$member.Id]
71+
if (-not $memberId) {
72+
WriteLog "[WARN] Skipping member with missing UserPrincipalName: $($member.Id)"
73+
continue
74+
}
75+
76+
if (-not (IsE5Member $memberId)) {
77+
continue
78+
}
79+
80+
try {
81+
# Check for existing folder
82+
$existingFolder = Get-MgUserContactFolder -UserId $memberId | Where-Object { $_.DisplayName -eq $folderName }
83+
84+
if ($existingFolder) {
85+
WriteLog "[INFO] Skipped $($memberId) (folder exists)"
86+
continue
87+
}
88+
89+
# Create folder
90+
New-MgUserContactFolder -UserId $memberId -DisplayName $folderName
91+
$folder = Get-MgUserContactFolder -UserId $memberId | Where-Object { $_.DisplayName -eq $folderName }
92+
$folderId = $folder.Id
93+
94+
# Process contacts in batches
95+
for ($i = 0; $i -lt $contacts.Count; $i += $batchSize) {
96+
$batch = $contacts[$i..([math]::Min($i + $batchSize - 1, $contacts.Count - 1))]
97+
98+
foreach ($contact in $batch) {
99+
$params = @{
100+
givenName = $contact.givenName
101+
surname = $contact.surname
102+
businessPhones = @($contact.businessPhones)
103+
categories = @($folderName)
104+
officeLocation = $contact.officeLocation
105+
personalNotes = $contact.id
106+
}
107+
108+
try {
109+
New-MgUserContactFolderContact -UserId $memberId -ContactFolderId $folderId -BodyParameter $params
110+
} catch {
111+
WriteLog "[ERROR] Failed to create contact $($contact.givenName) $($contact.surname) for $($memberId): $($_.Exception.Message)"
112+
}
113+
}
114+
}
115+
116+
WriteLog "[INFO] Func Numbers added for $($memberId)"
117+
118+
} catch {
119+
WriteLog "[ERROR] Error processing user $($memberId): $($_.Exception.Message)"
120+
}
121+
}
122+
123+
WriteLog "[INFO] Contact import completed."

0 commit comments

Comments
 (0)