Created
December 3, 2013 16:40
-
-
Save deanishe/7772540 to your computer and use it in GitHub Desktop.
Search Mac Address Book with Python via the Scripting Bridge
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
#!/usr/bin/python | |
# -*- coding: utf-8 -*- | |
# vim: fileencoding=utf-8 | |
""" | |
Search Mac Address Book contacts via official API | |
""" | |
from __future__ import print_function, unicode_literals | |
import sys | |
from time import time | |
from collections import defaultdict | |
import AddressBook as ab | |
def _make_list(cdw): | |
"""Make a list from CoreDataWrapper""" | |
if not cdw: | |
return [] | |
values = [] | |
for i in range(cdw.count()): | |
values.append(unicode(cdw.valueAtIndex_(i))) | |
return values | |
# map dict keys to AB properties and conversion funcs | |
_text_property_map = { | |
# output key : (property, conversion func) | |
'first_name': (ab.kABFirstNameProperty, None), | |
'last_name': (ab.kABLastNameProperty, None), | |
'company': (ab.kABOrganizationProperty, None), | |
'emails': (ab.kABEmailProperty, _make_list), | |
} | |
def ab_person_to_dict(person): | |
"""Convert ABPerson to Python dict""" | |
d = {} | |
d['emails'] = [] | |
for key in _text_property_map: | |
prop, func = _text_property_map[key] | |
value = person.valueForProperty_(prop) | |
if func: | |
value = func(value) | |
if not value: | |
value = '' | |
d[key] = value | |
return d | |
def search(query): | |
"""Search Mac Address Book and return pythonified results""" | |
address_book = ab.ABAddressBook.sharedAddressBook() | |
# build search criteria | |
criteria = [] | |
for key in _text_property_map: | |
prop, func = _text_property_map[key] | |
criteria.append( | |
ab.ABPerson.searchElementForProperty_label_key_value_comparison_( | |
prop, | |
None, None, | |
query, | |
ab.kABContainsSubStringCaseInsensitive) | |
) | |
search = ab.ABSearchElement.searchElementForConjunction_children_( | |
ab.kABSearchOr, criteria) | |
# search Address Book | |
people = address_book.recordsMatchingSearchElement_(search) | |
results = defaultdict(set) | |
for person in [ab_person_to_dict(person) for person in people]: | |
key = '{} {}'.format(person.get('first_name', ''), | |
person.get('last_name', '')).strip() | |
for addr in person['emails']: | |
results[key].add(addr) | |
return results | |
def main(): | |
if len(sys.argv) < 2: | |
print('Usage : ABSearch.py <query> [<query> ...]') | |
return 1 | |
for query in sys.argv[1:]: | |
s = time() | |
people = search(query) | |
print("{} results for '{}' in {:.4f} seconds".format(len(people), | |
query, | |
time() - s)) | |
print('-' * 40) | |
for name, addrs in people.items(): | |
print('{} : {}'.format(name, list(addrs))) | |
print() | |
if __name__ == '__main__': | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment