Contextual menu to dial by name

This is the third and last in my series of phone-dialing posts. The first two are here and here. Today, I’ll be showing how I combined AppleScript and On My Command to create a contextual menu item that takes a name you’ve selected in any application, looks it up in the Address Book, and dials its phone number through the modem. As with the last two posts, today’s script requires the excellent dialModemOSAX scripting addition from Javier Díaz Reinoso.

Here is the AppleScript. I call it abphones.scpt and keep it in my ~/bin folder.

property areaCode : "630"
property longDistance : "1"
property myModem : "/dev/cu.usbmodem"

-- change all letters to digits, strip punctuation,
-- and standardize pauses to ~
on translateNumber(num)
  set pipeline to "echo " & quoted form of num & ¬
    " | tr 'a-z' 'A-Z'" & ¬
    " | tr 'A-Z' '22233344455566677778889999'" & ¬
    " | tr ',' '~'" & ¬
    " | sed 's/[^0-9~]//g'"
  return do shell script pipeline
end translateNumber

-- return the numbers you actually dial
on makeDialable(num)
  set tnum to translateNumber(num)
  -- strip prefix and area code from local numbers
  if length of tnum is 11 ¬
    and characters 1 thru 4 of tnum as string ¬
    is (longDistance & areaCode) then
    set tnum to characters 5 thru 11 of tnum as string
  end if
  -- handle all 10-digit numbers
  if length of tnum is 10 then
    -- strip area code from local numbers
    if characters 1 thru 3 of tnum as string is "630" then
      set tnum to characters 4 thru 10 of tnum as string
    else -- add prefix to long distance numbers
      set tnum to longDistance & tnum
    end if
  end if
  return tnum
end makeDialable

on searchName(theName)
  tell application "Address Book"
    set nameWords to every word in theName
    set personList to every person whose name ¬
      contains the first item of nameWords
    repeat
      if the length of nameWords = 1 then
        exit repeat
      else
        set newPersonList to {}
        set nameWords to rest of nameWords
        repeat with p in personList
          if name of p contains first item of nameWords then
            set end of newPersonList to p
          end if
        end repeat
        set personList to newPersonList
      end if
    end repeat
    return personList
  end tell
end searchName

on run argv
  -- initialize the data
  set contacts to searchName(item 1 of argv)
  set workPhone to ""
  set homePhone to ""
  set cellPhone to ""
  set phList to {}

  -- handle the case of multiple hits
  if length of contacts > 1 then
    tell application "Address Book"
      set nList to {}
      set i to 1
      repeat with c in contacts
        set end of nList to (i as string) & ": " & name of c
        set i to i + 1
      end repeat
    end tell
    tell application "System Events"
      activate
      set whichPerson to choose from list nList with prompt ¬
        "Which \"" & (item 1 of argv) & "\" are you looking for?"
    end tell
    if whichPerson is false then
      return
    end if
    set whichPerson to first item of whichPerson
    set astid to AppleScript's text item delimiters
    set AppleScript's text item delimiters to ": "
    set cIndex to (first item of text items of whichPerson as string)
    set AppleScript's text item delimiters to astid
    set contact to item cIndex of contacts
  else
    set contact to item 1 of contacts
  end if

  -- get the canonical name and the phone numbers
  tell application "Address Book"
    set fullName to name of contact
    set dScript to "display dialog \"Dial which number for " & ¬
      fullName & "?\" buttons ["
    set allPhones to every phone of contact
    repeat with ph in allPhones
      set end of phList to (label of ph) & ": " & (value of ph)
    end repeat
  end tell

  -- ask the user which number to call
  tell application "System Events"
    activate
    set whichNum to false
    set whichNum to choose from list phList with prompt ¬
      "Dial which number for
" & fullName & "?"
  end tell
  if whichNum is false then
    return
  end if
  set whichNum to first item of whichNum
  set astid to AppleScript's text item delimiters
  set AppleScript's text item delimiters to ": "
  set phoneNumber to second item of text items of whichNum as string
  set AppleScript's text item delimiters to astid

  -- prepare the number for dialing
  set phoneNumber to makeDialable(phoneNumber)

  -- pause iTunes if it's running
  try
    do shell script "ps acx | grep 'iTunes$'"
    tell application "iTunes" to pause
  end try

  -- dial it
  initModem myModem with "^MAT&F1E0S7=45S0=0L2^M"
  --was "~^M~AT&F1E0S7=45S0=0L2^M"
  dial modem "ATDT" & phoneNumber
  delay 3
  hang up

end run

It uses the translateNumber and makeDialable functions described here and a slight modification to the searchName function described here. What is does is:

To turn this into a contextual menu item, I use On My Command and the OMCEdit application that comes with it. The command is created this way (you can click on the image to see it full-sized).

Once this is saved a “Look up and Dial” item shows up in the contextual menu whenever some text is selected. I use it mostly to call people mentioned in emails and in my text-file-based notes. Beats the hell out of doing it by hand.

Tags: