Created
March 16, 2019 17:32
-
-
Save andermoran/7551e17bccd334b2f304848520b41aaf to your computer and use it in GitHub Desktop.
A small program that grabs the information of every contact on a user's mac
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import plistlib | |
import os | |
import sys | |
import getpass | |
# usage: python contact_reaper.py or python3 contact_reaper.py | |
# tested on macOS Mojave (10.14) | |
def get_main_dir_path(): | |
return "/Users/" + getpass.getuser() + "/Library/Application Support/AddressBook/Sources/" | |
def get_source_subdirs(): | |
main_dir_path = get_main_dir_path() | |
main_dir = os.fsencode(main_dir_path) | |
sub_dirs = [] | |
for file in os.listdir(main_dir): | |
filename = os.fsdecode(file) | |
if not filename.endswith(".DS_Store"): | |
sub_dirs.append(os.path.join(main_dir_path, filename)) | |
return sub_dirs | |
def get_contact_plist(path): | |
try: | |
contact_file = open(path, "rb") | |
pl = plistlib.load(contact_file) | |
return pl | |
except PermissionError: | |
print("[PermissionError] Unable to open file") | |
return None | |
except: | |
print("[Unknown Error] Unable to generate plist object") | |
return None | |
def get_contact_plist_for_name(name): | |
first_name = name.split(" ")[0] | |
last_name = name.split(" ")[1] | |
dirs = get_source_subdirs() | |
for dir in dirs: | |
dir_path = dir + "/Metadata/" | |
if os.path.isdir(dir_path): # because some folders may not contain the Metadata folder | |
directory = os.fsencode(dir_path) | |
print(dir_path, "is a dir") | |
for file in os.listdir(directory): | |
filename = os.fsdecode(file) | |
if filename.endswith(".abcdp"): | |
contact_filepath = os.path.join(dir_path, filename) | |
contact_pl = get_contact_plist(contact_filepath) | |
if contact_pl is None: | |
print("[Err] Unable to get contact plist for", name) | |
return None | |
try: | |
if contact_pl['First'] == first_name and contact_pl['Last'] == last_name: | |
return contact_pl | |
except: | |
"" | |
#print("[debug]No first or last name found for contact at path", contact_filepath) | |
return None | |
def get_number_for_name(name): | |
pl = get_contact_plist_for_name(name) | |
if pl is not None: | |
try: | |
return pl['Phone']['values'] | |
except: | |
print("[Oof] Contact does not contain phone number information") | |
else: | |
print("[Err] Unable to get phone number for", name) | |
return None | |
def get_address_for_name(name): | |
pl = get_contact_plist_for_name(name) | |
if pl is not None: | |
try: | |
return pl['Address']['values'][0]['Street'] | |
except: | |
print("[Oof] Contact does not contain address information") | |
else: | |
print("[Err] Unable to get address for", name) | |
return None | |
def get_all_contacts(): | |
dirs = get_source_subdirs() | |
contacts = [] | |
for dir in dirs: | |
dir += "/Metadata/" | |
if os.path.isdir(dir): # because some folders may not contain the Metadata folder | |
for file in os.listdir(dir): | |
filename = os.fsdecode(file) | |
if not filename.endswith(".DS_Store"): | |
contact = get_contact_plist(os.path.join(dir, filename)) | |
if contact is not None: | |
contacts.append(contact) | |
return contacts | |
contacts = get_all_contacts() | |
for contact in contacts: | |
try: | |
print("First name:", contact['First']) | |
except: | |
print("First name: (null)") | |
try: | |
print("Last name:", contact['Last']) | |
except: | |
print("Last name: (null)") | |
try: | |
number = ''.join(filter(lambda x: x.isdigit(), contact['Phone']['values'][0])) | |
print("Phone number:", number) | |
except: | |
print("Phone number: (null)") | |
try: | |
if len(contact['Email']['values']) > 0: | |
print("Email: ", end="") | |
for i in range(0, len(contact['Email']['values'])): | |
if i == 0 : | |
print(contact['Email']['values'][i], end="") | |
else: | |
print(",", contact['Email']['values'][i], end="") | |
print() | |
except: | |
print("Email: (null)") | |
try: | |
print("Street:", contact['Address']['values'][0]['Street']) | |
except: | |
"" | |
try: | |
print("State:", contact['Address']['values'][0]['State']) | |
except: | |
"" | |
try: | |
print("City:", contact['Address']['values'][0]['City']) | |
except: | |
"" | |
try: | |
print("Zip:", contact['Address']['values'][0]['Zip']) | |
except: | |
"" | |
print() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment