omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Distinguish contacts between two accounts

    Pythonista
    4
    11
    4223
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • tonytx05
      tonytx05 last edited by

      Is there a way to determine if a contact exists in a specific account? For example, my iPad syncs with both an Exchange server and iCloud, and I am trying to clean up some of the duplicates between both accounts. However, when I look at the contacts returned by Python, I can’t find a way to distinguish which account a specific contact came from. Is there a way to do this that I am missing?

      mikael cvp 2 Replies Last reply Reply Quote 0
      • mikael
        mikael @tonytx05 last edited by

        @tonytx05, for some reason (I am guessing historically poor API design that they are now a bit stuck with), Apple has made the link between contacts and accounts difficult to determine, even with the ObjectiveC API. See e.g. here.

        1 Reply Last reply Reply Quote 0
        • cvp
          cvp @tonytx05 last edited by cvp

          @tonytx05 could you test this little quick and dirty script, and give me some feedback.
          I can't really test because I only have iCloud contacts...

          from objc_util import *
          import contacts
          
          # ObjectiveC contacts
          objc_contacts = {}
          CNContactStore = ObjCClass('CNContactStore').alloc().init()
          CNContact = ObjCClass('CNContact')
          Containers = CNContactStore.containersMatchingPredicate_error_(None,None)
          for Container in Containers:
          	id = Container.identifier()
          	predicate = CNContact.predicateForContactsInContainerWithIdentifier_(id)
          	# keys not exactly like in Apple doc
          	# found a sample here https://github.com/tdamdouni/Pythonista/blob/master/contacts/Add%20Twitter%20Profile%20Picture%20to%20iOS%20Contacts.py
          	predicate_contacts = CNContactStore.unifiedContactsMatchingPredicate_keysToFetch_error_(predicate, ['familyName','givenName','middleName'], None)
          	for contact in predicate_contacts:
          		# crash if attribute not in fetched contacts
          		name = str(contact.givenName()) + '|' + str(contact.middleName()) + '|' + str(contact.familyName())
          		objc_contacts[name] = id
          
          # Pythonista contacts
          all_contacts = contacts.get_all_people()
          for person in all_contacts:
          	key = person.first_name + '|' + person.middle_name + '|' + person.last_name
          	id = '****'
          	if key in objc_contacts:
          		id = objc_contacts[key]
          	print(key, id)
          
          mikael 1 Reply Last reply Reply Quote 0
          • mikael
            mikael @cvp last edited by

            @cvp, works for me, thanks!

            I can get a semi-legible name for the container with:

            print(container.name(), '-', container.descriptionForContainerType_(container.type()))
            

            ... but from the contents I am still not sure which are from Gmail - ”Address Book - CardDav” or ”Personal Contacts - Exchange”...

            cvp 1 Reply Last reply Reply Quote 0
            • cvp
              cvp @mikael last edited by

              @mikael I can't help. Perhaps by putting one contact only in one account?

              1 Reply Last reply Reply Quote 0
              • mikael
                mikael last edited by

                Looks like Gmail is the ”Address Book”/”CardDAV” container. People being in more than one container was throwing me off.

                @cvp, I adjusted your code a little to show repeated entries for people in more than one container:

                from objc_util import *
                import contacts
                
                # ObjectiveC contacts
                objc_contacts = {}
                CNContactStore = ObjCClass('CNContactStore').alloc().init()
                CNContact = ObjCClass('CNContact')
                Containers = CNContactStore.containersMatchingPredicate_error_(None,None)
                containers = {}
                for Container in Containers:
                    id = Container.identifier()
                    containers[id] = Container
                    #print(dir(Container))
                    predicate = CNContact.predicateForContactsInContainerWithIdentifier_(id)
                    # keys not exactly like in Apple doc
                    # found a sample here https://github.com/tdamdouni/Pythonista/blob/master/contacts/Add%20Twitter%20Profile%20Picture%20to%20iOS%20Contacts.py
                    predicate_contacts = CNContactStore.unifiedContactsMatchingPredicate_keysToFetch_error_(predicate, ['familyName','givenName','middleName'], None)
                    for contact in predicate_contacts:
                        # crash if attribute not in fetched contacts
                        name = str(contact.givenName()) + '|' + str(contact.middleName()) + '|' + str(contact.familyName())
                        cont_per_name = objc_contacts.setdefault(name, [])
                        cont_per_name.append(id)
                
                # Pythonista contacts
                all_contacts = contacts.get_all_people()
                for person in all_contacts:
                    key = person.first_name + '|' + person.middle_name + '|' + person.last_name
                    id = '****'
                    if key in objc_contacts:
                        for id in objc_contacts[key]:
                          container = containers[id]
                          print(key, '-', container.name(), '-', container.descriptionForContainerType_(container.type()))
                
                cvp 2 Replies Last reply Reply Quote 0
                • cvp
                  cvp @mikael last edited by

                  @mikael 👍thanks

                  mikael 1 Reply Last reply Reply Quote 0
                  • cvp
                    cvp @mikael last edited by

                    @mikael Could you edit your post to replace "adjusted" by "improved" 😀

                    1 Reply Last reply Reply Quote 0
                    • mikael
                      mikael @cvp last edited by

                      @cvp, no, thank you - I would not have had the time for the ObjC gymnastics at this time.

                      cvp 1 Reply Last reply Reply Quote 0
                      • cvp
                        cvp @mikael last edited by

                        @mikael I agree that, with my very small knowledge about ObjC, I spend sometimes a lot of hours to finally write a so little script, but I have this time as retired 👴🏻

                        1 Reply Last reply Reply Quote 0
                        • osamu
                          osamu last edited by osamu

                          Matching by the name...
                          Is this the only way to correlate Pythonista contacts person.id and CNContact identifier()? 😟

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post
                          Powered by NodeBB Forums | Contributors