«

»

Apr 02 2014

Using AppleScript to restore missing functionality from iChat to Messages in OS X 10.9.x Mavericks

Those of you who have run previous versions of OS X and are now running Mavericks may have noticed that the Messages client lacks quite a bit of the functionality of the iChat program that was included with earlier versions, and in particular the ability to take actions based on certain events.  However it is possible to restore some of that functionality using AppleScript.  Here’s a thumbnail overview of how to get started.

First, open the ~/Library/Application Scripts/com.apple.iChat/ directory and make a copy of the file Speak Events.applescript (you can temporarily copy it to another directory).  Rename the copy to something else (we used Custom Sounds.applescript for this demo) and move the copy back into the  ~/Library/Application Scripts/com.apple.iChat/ directory.

Open the Custom Sounds.applescript file in the AppleScript Editor (it’s in the Utilities folder inside your Applications folder) and make the changes shown below.  When you get through with your edits and you have compiled them you will see something like this:

Custom Sounds AppleScript

The easiest way to do this is to select all the existing AppleScript code, delete it, and replace it with the following:

using terms from application "Messages"
	on message received from theBuddy
		set qHandle to handle of theBuddy
		# do shell script "echo " & qHandle & " >> ~/Downloads/buddies.txt"
		if qHandle is equal to "someuser@somechatserver.com" then
			set playsound to POSIX path of ("/System/Library/Sounds/Pop.aiff")
		else if qHandle is equal to "someotheruser@somechatserver.com" then
			set playsound to POSIX path of ("/System/Library/Sounds/Frog.aiff")
		else
			set playsound to POSIX path of ("/System/Library/Sounds/Glass.aiff")
		end if
		do shell script ("afplay " & playsound & " > /dev/null 2>&1 &")
	end message received
	
	on active chat message received from theBuddy
		set qHandle to handle of theBuddy
		# do shell script "echo " & qHandle & " >> ~/Downloads/buddies.txt"
		if qHandle is equal to "someuser@somechatserver.com" then
			set playsound to POSIX path of ("/System/Library/Sounds/Pop.aiff")
		else if qHandle is equal to "someotheruser@somechatserver.com" then
			set playsound to POSIX path of ("/System/Library/Sounds/Frog.aiff")
		else
			set playsound to POSIX path of ("/System/Library/Sounds/Glass.aiff")
		end if
		do shell script ("afplay " & playsound & " > /dev/null 2>&1 &")
	end active chat message received
	
	# The following are unused but need to be defined to avoid an error
	
	on message sent theMessage with eventDescription
	end message sent
	
	on chat room message received with eventDescription
	end chat room message received
	
	on addressed message received theMessage from theBuddy for theChat with eventDescription
	end addressed message received
	
	on received text invitation with eventDescription
	end received text invitation
	
	on received audio invitation theText from theBuddy for theChat with eventDescription
	end received audio invitation
	
	on received video invitation theText from theBuddy for theChat with eventDescription
	end received video invitation
	
	on received local screen sharing invitation from theBuddy for theChat with eventDescription
	end received local screen sharing invitation
	
	on buddy authorization requested with eventDescription
	end buddy authorization requested
	
	on addressed chat room message received with eventDescription
	end addressed chat room message received
	
	on received remote screen sharing invitation with eventDescription
	end received remote screen sharing invitation
	
	on login finished with eventDescription
	end login finished
	
	on logout finished with eventDescription
	end logout finished
	
	on buddy became available with eventDescription
	end buddy became available
	
	on buddy became unavailable with eventDescription
	end buddy became unavailable
	
	on received file transfer invitation theFileTransfer with eventDescription
	end received file transfer invitation
	
	on av chat started with eventDescription
	end av chat started
	
	on av chat ended with eventDescription
	end av chat ended
	
	on completed file transfer with eventDescription
	end completed file transfer
	
end using terms from

You may wonder why we said to copy and open the copy of an existing file if we were just going to replace everything; it turns out that if you don’t do that the AppleScript editor seems to save the file in some format that Messages doesn’t recognize.

The edits you will need to change are these, in both the on message received… and on active chat message received… sections (make the same edits in both sections, otherwise it may not work as you expect):

		# do shell script "echo " & qHandle & " >> ~/Downloads/buddies.txt"

Uncomment these lines at first to discover the “handles” that are being sent when each buddy sends you an instant message – each one will produce a line in the file buddies.txt in your Downloads directory (you can use another directory and filename if you prefer). Normally they will be in a form like “username@server” which in some cases (particularly with Google users) might even be the same as their email address. Once a buddy has sent you a message, you can look in the file to see what their “handle” is. Then you can set up the conditions, like so:

		if qHandle is equal to "someuser@somechatserver.com" then
			set playsound to POSIX path of ("/System/Library/Sounds/Pop.aiff")
		else if qHandle is equal to "someotheruser@somechatserver.com" then
			set playsound to POSIX path of ("/System/Library/Sounds/Frog.aiff")
		else
			set playsound to POSIX path of ("/System/Library/Sounds/Glass.aiff")
		end if

Replace “someuser@somechatserver.com” and “someotheruser@somechatserver.com” with valid “handles”. The sounds can be whatever you want but they must be in .aiff file format – here we have used the standard sounds found in /System/Library/Sounds/ but there is no reason you can’t use other sounds or even custom .aiff files. The “else” condition specifies the default sound that will be played for incoming messages from buddies not specified in the other conditions. You can add as many “else if” conditions as you need, depending on whether you want to have distinctive sounds for additional buddies.

Don’t forget to comment the “do shell script …” lines back out once you have received all the “handles” that are important to you, otherwise that file will continue to grow with each received message, which is why we suggest putting it in your Downloads folder where you are more likely to notice it.

Finally to get Messages to use these sounds open its Preferences and select your new AppleScript file at the bottom of the panel:

Messages Preferences

Note that not only have we selected the Applescript, but we changed the default Message received sound to Tink, which is a very quiet sound – the reason is that while you can turn off all sounds in Messages, you can’t make the default Message received sound “nothing”. So when a message arrives, it will play both the “Tink” sound AND the sound you have selected in your AppleScript. We suppose you could use an audio editor (such as Audacity) to create an .aiff file with no sound in it, if even the Tink sound bothers you, or if that’s too much work you can download and unzip this one (place the resulting Silence.aiff file in the /System/Library/Sounds/ folder, and after doing that you’ll need to close and reopen the Messages application before you can select it as the Message received sound).

Obviously there are many other possibilities, both for adding custom sounds to other Message events and for taking additional or different actions. For example, if you looked at the Speak Events.applescript file that we had you copy at the start of this, you would see that it’s possible to have incoming messages be read aloud to you. Also, at least in theory it’s possible to select the buddy based on something other than the “handle” – if you go into the AppleScript Editor, File menu, and Open Dictionary, then scroll down to “Messages” and choose it, and then select “Messages Suite” and “buddy” you will see the screen shown here:

Messages Buddy options

You should be able to use the buddy “name” instead of the “handle”, but that would not work for us for some reason and generated an error popup. And note that to use some of these options you must have a “contacts card” (Address Book entry) for that buddy, with the selected field filled in.

By the way, rather that have two identical blocks of script under the on message received… and on active chat message received… sections, you could instead use a single subroutine, in this case named custom_notify, where the start of the script would be changed to look like this:

using terms from application "Messages"
	on message received from theBuddy
		custom_notify(theBuddy)
	end message received
	
	on active chat message received from theBuddy
		custom_notify(theBuddy)
	end active chat message received
	
	# The following are unused but need to be defined to avoid an error

(…the rest of the original script continues here…)

And then at the very end of the script (below the end using terms from line), you could define the custom_notify subroutine, which receives the single variable theBuddy:

on custom_notify(theBuddy)
	set qHandle to handle of theBuddy
	# do shell script "echo " & qHandle & " >> ~/Downloads/buddies.txt"
	if qHandle is equal to "someuser@somechatserver.com" then
		set playsound to POSIX path of ("/System/Library/Sounds/Pop.aiff")
	else if qHandle is equal to "someotheruser@somechatserver.com" then
		set playsound to POSIX path of ("/System/Library/Sounds/Frog.aiff")
	else
		set playsound to POSIX path of ("/System/Library/Sounds/Glass.aiff")
	end if
	do shell script ("afplay " & playsound & " > /dev/null 2>&1 &")
end custom_notify

This is just a quick overview to get you started but the idea is that by using AppleScript you should be able to restore the functionality of any “missing” iChat triggers that are important to you, and maybe even do a few things that iChat wouldn’t. If you come up with any useful AppleScript snippets or “recipes”, please feel free to post them in the comments section, so that others might benefit from your cleverness.

Related:
Buddy online notification in Messages (OS X Mavericks) (Too busy to…)
Send SMS to Messages and run commands with AppleScript Apps (Macworld)

3 comments

  1. DJR12

    Thanks so much for the thorough rundown. I’m not a developer but I dabble in AppleScript when it can help achieve what I need. Sadly, it looks from the beta of Yosemite that Apple has removed even *more* customizability from Messages. I guess it’s understandable that they want it to more closely resemble the iOS version, but I’m still going to miss the ability to customize colors and everything.

    I’m curious if you have any tips on this: I used to have a really simple script, pre-Mavericks Messages, that would automatically log me back in whenever one of my accounts logged out. It was easy to use because back then you could call a script when a specific event occurred. So, for the event of logging out, I had the script:

    tell application “System Events”
    if (processes whose name is “Messages”) exists then
    tell application “Messages” to log in
    end if
    end tell

    And that pretty much covered it. Any idea what the equivalent would be in Mavericks?

    1. Admin

      DJR12, we haven’t attempted anything like that but note the last screenshot in the article and accompanying text – in the middle column of the AppleScript Editor Dictionary, if instead of selecting “buddy” you select “service”, then in the right hand column select “connection status”, you will see that “disconnecting” and “disconnected” are among the states that can be tested. Or if you select “status” in the right hand column, you can test for the “offline” state. Unfortunately we don’t know the correct syntax offhand – we only have passing familiarity with AppleScript – but it seems like if you can figure it out, you may then be able to use “log in” (select that in the center column of the AppleScript Editor Dictionary to see details) to get back online. If you figure it out, please reply with a note on how you did it, because that would probably be something a lot of Messages users would like to be able to do.

      By the way, sorry to hear that they are making Messages even less customizable. If Apple keeps this up they are going to cede the (non-Windows) desktop to Linux. We suspect that the only reason some people stick with OS X now is that there is a lot of software that runs under OS X but doesn’t (yet) come in a Linux version, but if Apple’s actions drive enough desktop users to Linux, software developers could start thinking that it’s more advantageous to develop Linux versions of their software than OS X versions. May not happen for a few more years, but it seems like although Linux has its issues, on the whole it just gets more capable and user-friendly, whereas Apple just seems intent on taking functionality away in some of their core software, or breaking things that shouldn’t be broken (like SAMBA).

  2. Alex

    I have a particularly specific question/request for a Messages AppleScript. We use Jabber at work (I also have my personal Gmail chat set up) and we utilize both chatroom messages and of course private messages. Prior to Mavericks, it was so simple to leave PM alert sounds enabled while disabling chat room alert sounds. I tried tinkering with the AppleScript at the beginning of this post but didn’t have much luck in changing its behavior from how it’s already set up. Is there a way to do something like this, and if so, any idea how? All I really want is the chat room alert sound to be non-existant, while still seeing a visual alert. The rest can stay as it is. Thanks in advance!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current ye@r *

%d bloggers like this: