Files
claudetools/temp/bardach_fix_blank_names.py

76 lines
2.8 KiB
Python

import urllib.request, urllib.parse, json, os
from collections import defaultdict
APP_ID = "fabb3421-8b34-484b-bc17-e46de9703418"
TENANT_ID = "dd4a82e8-85a3-44ac-8800-07945ab4d95f"
CLIENT_SECRET = os.environ["CLIENT_SECRET"]
USER_ID = "41d14430-feb4-4ae2-aed6-2bd4e6384ca7"
token_data = urllib.parse.urlencode({
'client_id': APP_ID, 'client_secret': CLIENT_SECRET,
'scope': 'https://graph.microsoft.com/.default', 'grant_type': 'client_credentials'
}).encode()
req = urllib.request.Request(f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token", data=token_data, method='POST')
with urllib.request.urlopen(req) as r:
token = json.loads(r.read())['access_token']
base = f'https://graph.microsoft.com/v1.0/users/{USER_ID}/contacts'
def patch_contact(cid, data):
body = json.dumps(data).encode()
req = urllib.request.Request(f'{base}/{cid}', data=body, method='PATCH',
headers={'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'})
with urllib.request.urlopen(req) as r:
return r.status
# Fetch all contacts with blank displayName
url = f'{base}?$select=id,displayName,givenName,surname,companyName,emailAddresses,businessPhones,mobilePhone&$top=999'
blanks = []
while url:
req = urllib.request.Request(url, headers={'Authorization': f'Bearer {token}'})
with urllib.request.urlopen(req) as r:
data = json.loads(r.read())
for c in data.get('value', []):
dn = (c.get('displayName') or '').strip()
if not dn:
blanks.append(c)
url = data.get('@odata.nextLink')
print(f'Found {len(blanks)} contacts with blank displayName\n')
fixed = 0
skipped = 0
for c in blanks:
given = (c.get('givenName') or '').strip()
surname = (c.get('surname') or '').strip()
company = (c.get('companyName') or '').strip()
emails = [e.get('address', '') for e in c.get('emailAddresses', []) if e.get('address', '').strip()]
phones = list(filter(None, (c.get('businessPhones') or []) + [c.get('mobilePhone')]))
# Build display name from best available info
if given and surname:
new_name = f'{given} {surname}'
elif given:
new_name = given
elif surname:
new_name = surname
elif company:
new_name = company
elif emails:
# Use email local part as name
new_name = emails[0].split('@')[0].replace('.', ' ').replace('_', ' ').title()
else:
# Nothing useful - skip
skipped += 1
continue
try:
status = patch_contact(c['id'], {'displayName': new_name})
src = 'name' if (given or surname) else ('company' if company else 'email')
print(f' [OK] "{new_name}" (from {src}, status {status})')
fixed += 1
except Exception as e:
print(f' [ERROR] {new_name}: {e}')
print(f'\n=== DONE: Fixed {fixed}, Skipped {skipped} (no usable data) ===')