Seeking advice in taming contacts

Hi all,

I somehow managed to back my sorry self into a corner and have no idea how to get out of it.
I created a somewhat larger script than initially anticipated which deals with clients, opponents, courts, deadlines, appointments, invoices and so on (its for my wife since she is a lawyer).
Everything is working perfectly, until I discovered, far too late, that the id property of the Address Book Suite is not quite what it seems. It says there:

id (text, r/o) : unique and persistent identifier for this record.

Well, if somebody is looking into the documentation of the Contacts framework it says something similar, but somehow more precise:

identifier
A value that uniquely identifies a contact on the device.

Needless to say, the part ‘on the device’ is where I’m in deep trouble. I’ve chosen to save all the relevant data within Devonthink Pro (that is, just id’s of the contacts in plist files) which is synchronized to her Mac. Unfortunately, since every device creates it’s own id, all the records I prepare on my Mac are useless on hers. And vice versa.

Long story, sorry for that.
I noticed, however, that, upon exporting vcards from the contact, every contacts gets an UID which doesn’t change. Unfortunately, I can’t get it from Address Book Suite.

Now, should I rewrite to store just the names in the files, should I try to create my own vcard reading & writing mechanism (uh-uh), rewrite everything from scratch using Swift or whatever and just include scripts for storing in Devonthink and generating letters in Pages, or does anybody know how to get a contact’s UID?

Any help appreciated…

I’m not sure that I understand your problem.
Here are two bare scripts.

# Script 1

tell application "Contacts"
	activate
	try
		set groupCount to (count of groups)
		if groupCount = 0 then
			error number 1000
		else if groupCount = 1 then
			set recipientGroup to group 1
			set recipientGroupName to name of recipientGroup
		else
			set listOfGroups to name of every group
			set recipientGroupName to (choose from list listOfGroups with prompt "Choisissez un groupe de contacts…" default items (item 1 of listOfGroups))
			if recipientGroupName is false then error number -128
			
			set recipientGroupName to recipientGroupName's item 1
			set recipientGroup to group recipientGroupName
		end if
		
		set thePersons to every person of recipientGroup
		if (count thePersons) = 0 then error number 1001
		
		repeat with thePerson in thePersons
			set itsName to name of thePerson
			set uniqueID to id of thePerson
			(*
			set itsAddresses to address of thePerson
			if (count itsAddresses) > 0 then
				repeat with itsAddress in itsAddresses
					set textAddress to formatted address of itsAddress
				end repeat
			end if
			*)
		end repeat
		
		set the clipboard to uniqueID
	on error errText number errNum
		if errNum = -128 then
			display alert "Script interrompu par l'utilisateur."
		else if errNum = 1000 then
			display alert "Il n'y a aucun groupe dans le carnet d'adresses…"
		else if errNum = 1001 then
			display alert "Il n'y a aucun contact dans le groupe choisi…"
		else
			display alert "Erreur : " & errNum & return & errText
		end if
	end try
end tell

# Script 2

set uniqueId to the clipboard
tell application "Contacts"
	activate
	try
		set aPerson to person id uniqueId
		set itsName to name of aPerson
		set itsCard to vcard of aPerson
	end try
end tell

Run Script 1 will put an unique ID in the clipboard.
Run Script 2 will correctly extract infos from the person whose ID was in the clipboard.

Are you sure that it’s this kind of uniqueID that you are working with ?

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 18 mars 2019 17:13:06

Hi Yvan,

thanks for your answer and sorry for the misunderstanding, I got carried away there yesterday.

The id of a person is only unique for one device, that’s what I discovered yesterday to my utter dismay. What I want to have is the UID you get when you export a vcf file, since that one is indeed unique so I can use the script on different Macs and can retrieve correct contacts as well.

I think I do have a partial solution:

on getAllContacts(theNameOfTheGroup)
	set oldDelims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "\nUID:"
	tell application "Contacts"
		set kontaktGroup to first group whose name is theNameOfTheGroup
		set {theCompany, theID, theName, isACompany, firstName, lastName, theVcards} to {organization, id, name, company, first name, last name, vcard} of person of kontaktGroup
		repeat with i from 1 to (count of kontaktGroup)
			set theUUIDS to ""
			if (count of text items of (item i of theVcards)) = 2 then set theUUIDS to paragraph 1 of text item 2 of (item i of theVcards)
			set contactDataBase to contactDataBase & {{abID:(item i of theID), kontaktID:theUUIDS, theName:(item i of theName), isCompany:(item i of isACompany), firstName:(item i of firstName), lastName:(item i of lastName)}}
		end repeat
	end tell
	set AppleScript's text item delimiters to oldDelims
end getAllContacts

Performance is nothing to write home about, but for now it seems to work as expected - it’s just a quick hack and I omitted any error checking.

Still looking for a somewhat faster or better solution :expressionless:

I really don’t understand.To get it working I was forced to edit your script as :

property contactDataBase : {}

on getAllContacts(theNameOfTheGroup)
	
	set oldDelims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "UID:"
	tell application "Contacts"
		set kontaktGroup to first group whose name is theNameOfTheGroup
		set {theCompany, theID, theName, isACompany, firstName, lastName, theVcards} to {organization, id, name, company, first name, last name, vcard} of person of kontaktGroup
		
		repeat with i from 1 to (count of every person of kontaktGroup)
			set theUUIDS to ""
			if (count of text items of (item i of theVcards)) = 2 then set theUUIDS to paragraph 1 of text item 2 of (item i of theVcards)
			copy {{abID:(item i of theID), kontaktID:theUUIDS, theName:(item i of theName), isCompany:(item i of isACompany), firstName:(item i of firstName), lastName:(item i of lastName)}} to end of contactDataBase
		end repeat
		
	end tell
	set AppleScript's text item delimiters to oldDelims
	
end getAllContacts

my getAllContacts("Gerbino")
return contactDataBase

And, what a surprise, abID and kontaktID are identical.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 18 mars 2019 19:54:19

Uh, sorry, forgot the property declaration.
Seriously? OK, that’s funny and I fully understand why it seems crazy.

Why did you remove the \n? I think need this to differentiate between the UID and X-ABUID. The vcard’s I’m getting from Contacts look like this:

[format]BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.14.4//EN
N:OhneName;Ein Mandant;;;
FN:Ein Mandant OhneName
item1.EMAIL;type=INTERNET;type=pref:Email
item1.X-ABLabel:Privat
item2.TEL;type=pref:Mobil
item2.X-ABLabel:Mobil
item3.TEL:Telefon privat
item3.X-ABLabel:Privat
item4.ADR;type=pref:;;Anschrift;Stadt;;PLZ;
item4.X-ABLabel:Privat
CATEGORIES:Mandanten
UID:3d0af093-6f06-40fe-9afd-c5ea669d0680
X-ABUID:FF37231D-6ED5-461F-B688-BC32CC6AFB73:ABPerson
END:VCARD[/format]

Here I get two different id’s like
abID = FF37231D-6ED5-461F-B688-BC32CC6AFB73:ABPerson
whereas
kontaktID = 3d0af093-6f06-40fe-9afd-c5ea669d0680

Some local contacts only seem to have the X-ABUID in the vcard, which is identical to the person’s id property, at least here on my system. On another Mac the same contact has a different id but has the same UID.

On my Macs the the id property of person always ends with ABPerson so I’m completely lost here…

Now I’m completely confused :rolleyes:

I removed the return character because on my mac there is no paragraph resembling to your :
UID:3d0af093-6f06-40fe-9afd-c5ea669d0680 in the vCards

There is only the paragraphs resembling to :
X-ABUID:FF37231D-6ED5-461F-B688-BC32CC6AFB73:ABPerson

So I assumed that there was a typo.

To be complete, with a vCard like yours, the edited script would return
3d0af093-6f06-40fe-9afd-c5ea669d0680
which of course it can’t do with my vCards.

May this be due to a different version of the running operating system ?

In your script was the instruction :

repeat with i from 1 to (count of kontaktGroup)
which I had to edit as :
repeat with i from 1 to (count of every person of kontaktGroup)

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 18 mars 2019 21:06:43

Are your contacts locally stored or on a Server (iCloud, whatever)?

My local contacts don’t have an UID as well.

I never used a server.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 19 mars 2019 09:50:44