Call an Address Book contact with Skype

Over the last month I’ve been teaching myself applescript and I found this website very helpful so I wanted to give something back.

As you probably know, in the US we can make free phone calls over the internet with Skype. The latest version of Skype is scriptable, so I wrote this script to take advantage of that. Skype has its own address book where you put in the contact info of the people you want to call, but since we already have an Address Book with all of our contacts information, I wanted to dial from it instead of Skype… thus this script.

The script will first note if the Address Book application (AB) is running. This is used so we can quit the AB if this script launched it. The AB will provide a list of all your contacts. The subroutine Qsort() is used to alphabetically sort the list so when it is presented it will be easier to choose who you want to call. The list is presented, you select a name, and the script learns the first and last name of who you want to call. Based on the name selected, the AB is searched for the phone numbers of that person (i.e. home phone, work phone, mobile phone, pager etc.). The AB will then quit if this script launched it, otherwise it is left running. A list of the person’s phone numbers is presented and you choose which one you want to call. Miscellaneous characters are removed from the phone number, the country code is added to the front of the number, and Skype will launch and dial the number.


-- variables to change
set the countryCode to "+1" -- the country code needed to dial with Skype (for USA use +1)
set defaultContact to "" -- the default selected name to choose, formatted as "lastName<space>firstName" as listed in your address book

-- the script
global defaultContact
try
	-- note if Address Book is running so we can quit AB if this script launched AB
	my checkProcessAB()
	set theProcessCount to the result
	
	-- get a list of all the contacts in your Address Book
	my getContacts()
	set myContacts to the result
	
	-- present the list of contacts and so you can choose which person to call
	my presentContacts(myContacts)
	set theName to the result
	set FirstName to item 1 of theName as string
	set LastName to item 2 of theName as string
	
	-- get the person's phone numbers from your Address Book
	my get_phone_numbers(FirstName, LastName)
	set the_phone_numbers to the result
	
	-- quit Address Book if this script launched it, otherwise leave it running
	if theProcessCount is 0 then tell application "Address Book" to quit
	
	-- choose which phone number (i.e. home, work, mobile etc.) to dial
	my choosePhoneNumber(the_phone_numbers)
	set thePhoneNum to the result
	
	-- strip out just the phone number discarding miscellaneous characters
	my strip_phone_number(thePhoneNum)
	set integerPhoneNum to the result
	
	-- create the skype phone number by adding the country code
	set skypeNumber to countryCode & integerPhoneNum as string
	
	-- have skype call the phone number
	tell application "Skype"
		activate
		send command "CALL " & skypeNumber script name "Call By Skype"
	end tell
end try


----------------------------------- subroutines ------------------------------------
---------------------------------------------------------------------------------------
on checkProcessAB()
	-- this will check if the address book is running before the script runs
	-- it is used to know whether to quit AB or not
	set theApp to "Address Book"
	tell application "System Events"
		set theProcessCount to count (every process whose name is theApp)
	end tell
	return theProcessCount
end checkProcessAB

on getContacts()
	-- get the names of every person in your address book and sort them alphabetically
	tell application "Address Book"
		set myContacts to the name of every person
	end tell
	my Qsort(myContacts, 1, -1) -- alphabetically sort the contacts to present them in an orderly list
	return myContacts
end getContacts

on presentContacts(theContacts)
	-- presents the list of your contacts in the Finder, and returns the first and last name of the one you select
	tell application "Finder"
		activate
		choose from list theContacts with title "Calling With Skype" with prompt ¬
			"Who shall we call?" default items defaultContact as list ¬
			OK button name "Connect" cancel button name "Quit"
	end tell
	set theContact to the result as string
	set oldDelimiters to AppleScript's text item delimiters
	set AppleScript's text item delimiters to " "
	set nameList to every text item of theContact
	set AppleScript's text item delimiters to oldDelimiters
	set FirstName to item 2 of nameList
	set LastName to item 1 of nameList
	return {FirstName, LastName}
end presentContacts

on get_phone_numbers(FirstName, LastName)
	-- gets the different phone numbers from the Address Book for the person with FirstName and LastName
	set the_delim to ":"
	tell application "Address Book"
		set phoneNumbers to {}
		set thePerson to (every person whose last name contains LastName and first name contains FirstName)
		set the_person to item 1 of thePerson
		repeat with i from 1 to the count of phone in the_person
			set thelabel to label of phone [i] of the_person as string
			set thePhone to value of phone [i] of the_person as string
			set phoneNumbers to phoneNumbers & thelabel & thePhone
		end repeat
	end tell
	return phoneNumbers
end get_phone_numbers

on choosePhoneNumber(thePhoneNums)
	-- presents the phone numbers in the Finder so you can choose which one you want
	set the_count to the count of thePhoneNums
	set phoneList to {}
	repeat with i from 1 to (the_count / 2)
		set y to ((i - 1) + i)
		set z to i * 2
		set phoneList to phoneList & {(item y of thePhoneNums) & ": " & (item z of thePhoneNums)}
	end repeat
	tell application "Finder"
		activate
		choose from list phoneList with title ¬
			"Calling With Skype" with prompt "Which phone number?"
		set thePhoneNum to the result as string
	end tell
	return thePhoneNum
end choosePhoneNumber

on strip_phone_number(thePhoneNumber)
	-- will remove miscellaneous characters from thePhoneNumber such as "(" and "-" and any other text values
	set phoneNumber to ""
	repeat with thenumber in thePhoneNumber
		try
			set aNumber to thenumber as integer
			set phoneNumber to phoneNumber & aNumber
		end try
	end repeat
	return phoneNumber
end strip_phone_number

on Qsort(theList, L, r)
	-- Qsort sorts a list alphabetically
	-- the authors of Qsort are Arthur Knapp and Nigel Garvey
	-- the script can be found in item 2 of http://bbs.applescript.net/viewtopic.php?id=17340
	script o
		property cutoff : 10
		property P : theList
		on qsrt(L, r)
			set i to L
			set j to r
			set v to my P's item ((L + r) div 2)
			repeat while (j > i)
				set u to my P's item i
				repeat while (u < v)
					set i to i + 1
					set u to my P's item i
				end repeat
				
				set w to my P's item j
				repeat while (w > v)
					set j to j - 1
					set w to my P's item j
				end repeat
				
				if (i > j) then
				else
					set my P's item i to w
					set my P's item j to u
					set i to i + 1
					set j to j - 1
				end if
			end repeat
			
			if (j - L < cutoff) then
			else
				qsrt(L, j)
			end if
			
			if (r - i < cutoff) then
			else
				qsrt(i, r)
			end if
		end qsrt
		on isrt(L, r)
			set x to L
			set z to L + cutoff - 1
			if (z > r) then set z to r
			
			set v to my P's item x
			repeat with y from (x + 1) to z
				if (my P's item y < v) then
					set x to y
					set v to my P's item y
				end if
			end repeat
			
			tell my P's item L
				set my P's item L to v
				set my P's item x to it
			end tell
			
			set u to my P's item (L + 1)
			repeat with i from (L + 2) to r
				set v to my P's item i
				if (v < u) then
					set my P's item i to u
					repeat with j from (i - 2) to L by -1
						if (v < my P's item j) then
							set my P's item (j + 1) to my P's item j
						else
							set my P's item (j + 1) to v
							exit repeat
						end if
					end repeat
				else
					set u to v
				end if
			end repeat
		end isrt
	end script
	set listLen to (count theList)
	if (listLen > 1) then -- otherwise the handler will error
		-- Translate negative indices
		if (L < 0) then set L to listLen + L + 1
		if (r < 0) then set r to listLen + r + 1
		
		if (r = L) then
			-- No point in sorting just one item
		else
			-- Transpose transposed indices
			if (L > r) then
				set temp to L
				set L to r
				set r to temp
			end if
			
			if (r - L < o's cutoff) then
				-- Skip the Quicksort if cutoff or less items
			else
				o's qsrt(L, r)
			end if
			o's isrt(L, r)
		end if
	end if
	return -- the original name of your list is the returned value
end Qsort

Model: PM dual 2.0 GHz G5
AppleScript: AppleScript 1.10.7
Browser: Safari 419.3
Operating System: Mac OS X (10.4)