this is probably a simple question but I am a bit confused as I haven't found many examples online.
I've been able to send messages through Messages in Mac OS using Javascript (Using this tutorial) but I can't figure out how to do it using Python and PyObjC.
Using Javascript I'd do something like this:
var messages = Application('Messages');
var buddy = messages.services["E:%REPLACE_WITH_YOUR_IMESSAGE_EMAIL%"].buddies["%REPLACE_WITH_BUDDYS_EMAIL%"];
messages.send("JavaScript sent this message!", {to: buddy});
I can't figure out how to set the buddy
variable to the relevant object with Python. The following works fine to access Messages
from Foundation import *
from ScriptingBridge import *
Messages = SBApplication.applicationWithBundleIdentifier_("com.apple.iChat")
Then in Python I'm able do something like this.
In [182]: s = Messages.services()
In [183]: [x.name() for x in s]
Out[183]: ['E:foo@icloud.com', 'Bonjour', 'SMS']
But I'm not sure how to make the leap from this to actually getting it to send a message using Messages.send_to_
after I create the Messages object.
Your help would be greatly appreciated, thank you very much!
You can do it like this:
from ScriptingBridge import SBApplication
Messages = SBApplication.applicationWithBundleIdentifier_("com.apple.iChat")
# get the first budddy who's name is Chris Cummings
buddy_to_message = [b for b in Messages.buddies() if b.fullName() == "Chris Cummings"][0]
# send text to buddy
Messages.send_to_("sending this from python test", buddy_to_message)
Something I've found really useful when trying to use the largely undocumented ScriptingBridge module from pyobjc is to search for methods that are available on the class that I'm trying to get access to in the repl
>>>[method for method in dir(Messages) if "bud" in method.lower()]
["buddies", "buddies"] # found the buddies method
>>>[method for method in dir(Meessages.buddies()[0]) if "name" in method.lower()]
[ ... 'accessibilityParameterizedAttributeNames', 'className',
'elementWithCode_named_', 'entityName', 'firstName', 'fullName',
'fullName', 'lastName', 'name', 'name', 'scriptAccountLegacyName',
'valueWithName_inPropertyWithKey_']
# ... this one had a bunch of other junk but hopefully this illustrates the idea
An additional note on dir:
Of course dir()
can take arguments as well and you can get a list of methods that are defined on the object that match a string with dir('name')
but the ObjectiveC classnames are almost never capitalized as I'd expect, so I think it's useful to search for them all lowercase.