Get Buddy Info
==============

* :download:`Download example <PyObjCExample-Get Buddy Info.zip>`

An automator action that returns the current status for an iChat buddy.


.. rst-class:: tabber

Sources
-------

.. rst-class:: tabbertab

GetBuddyInfo.py
...............

.. sourcecode:: python

    import struct
    from AddressBook import ABAddressBook, ABPerson
    from Automator import AMBundleAction
    from Cocoa import NSAppleEventDescriptor
    from InstantMessage import (
        IMPersonFirstNameKey,
        IMPersonLastNameKey,
        IMPersonScreenNameKey,
        IMPersonServiceNameKey,
        IMPersonStatusAvailable,
        IMPersonStatusAway,
        IMPersonStatusIdle,
        IMPersonStatusKey,
        IMPersonStatusMessageKey,
        IMPersonStatusOffline,
        IMPersonStatusUnknown,
        IMService,
    )
    
    typeObjectSpecifier = struct.unpack(">i", b"obj ")[0]
    keyAEContainer = struct.unpack(">i", b"from")[0]
    keyAEKeyData = struct.unpack(">i", b"seld")[0]
    
    
    class GetBuddyInfo(AMBundleAction):
        def runWithInput_fromAction_error_(self, value, anAction, errorInfo):
            people = []
    
            # convert the input to a list of ABPerson objects
            if isinstance(value, NSAppleEventDescriptor):
                count = value.numberOfItems()
    
                for i in range(1, count + 1):
                    personDescriptor = value.descriptorAtIndex_(i)
                    if personDescriptor is not None:
                        # get the uid of the person from this descriptor
                        if personDescriptor.descriptorType() == typeObjectSpecifier:
                            container = personDescriptor.descriptorForKeyword_(
                                keyAEContainer
                            )
                            if container is not None:
                                uidDescriptor = container.descriptorAtIndex_(
                                    i
                                ).descriptorForKeyword_(keyAEKeyData)
                                if uidDescriptor is not None:
                                    uid = uidDescriptor.stringValue()
                                    if uid is not None:
                                        # get the person object from the uid
                                        person = ABAddressBook.sharedAddressBook().recordForUniqueId_(  # noqa: B950
                                            uid
                                        )
                                        if person is not None:
                                            people.append(person)
    
            info = []
            for person in people:
                for service in IMService.allServices():
                    if isinstance(person, ABPerson):
                        screenNames = service.screenNamesForPerson_(person)
                        if screenNames is not None:
                            for screenName in screenNames:
                                info_dict = service.infoForScreenName_(screenName)
                                if info_dict is not None:
                                    # build the description
                                    description = "\rName: "
    
                                    firstName = info_dict[IMPersonFirstNameKey]
                                    if firstName is not None:
                                        description += firstName
                                        description += " "
    
                                    lastName = info_dict[IMPersonLastNameKey]
                                    if lastName is not None:
                                        description += lastName
    
                                    description += "\r"
    
                                    serviceName = info_dict[IMPersonServiceNameKey]
                                    if serviceName is not None:
                                        description += "Service: "
                                        description += serviceName
                                        description += "\r"
    
                                    screenName = info_dict[IMPersonScreenNameKey]
                                    if screenName is not None:
                                        description += "Screen Name: "
                                        description += screenName
                                        description += "\r"
    
                                    status = info_dict[IMPersonStatusKey]
                                    if status is not None:
                                        description += "Status: "
    
                                        if status == IMPersonStatusUnknown:
                                            description += "Unknown"
                                        elif status == IMPersonStatusOffline:
                                            description += "Offline"
                                        elif status == IMPersonStatusIdle:
                                            description += "Idle"
                                        elif status == IMPersonStatusAway:
                                            description += "Away"
                                        elif status == IMPersonStatusAvailable:
                                            description += "Available"
    
                                        description += "\r"
    
                                    message = info_dict[IMPersonStatusMessageKey]
                                    if message is not None:
                                        description += "Message: "
                                        description += message
                                        description += "\r"
    
                                    info.append(description)
            return str(info)

.. rst-class:: tabbertab

setup.py
........

.. sourcecode:: python

    """
    Script for building the example.
    
    Usage:
        python3 setup.py py2app
    
    Then install the bundle in dist into ~/Library/Automator.
    """
    from setuptools import setup
    
    infoPlist = {
        "AMAccepts": {
            "Container": "List",
            "Optional": False,
            "Types": ["com.apple.addressbook.person-object"],
        },
        "AMApplication": ["Address Book", "iChat"],
        "AMCanShowWhenRun": True,
        "AMCategory": "iChat",
        "AMDefaultParameters": {},
        "AMDescription": {
            "AMDAlert": "iChat must be running for this action to work properly.",
            "AMDNote": "Information will not be returned for the current user.",
            "AMDSummary": "This action returns the Instant Message information "
            "of the people passed from the previous action.",
        },
        "AMIconName": "iChat",
        "AMKeywords": ("Instant", "Message", "IM"),
        "AMName": "Get Buddy Info",
        "AMProvides": {"Container": "List", "Types": ["com.apple.cocoa.string"]},
    }
    
    setup(
        name="Get Buddy Info",
        plugin=["GetBuddyInfo.py"],
        data_files=[],
        options={"py2app": {"extension": ".action", "plist": infoPlist}},
        setup_requires=[
            "py2app",
            "pyobjc-framework-Automator",
            "pyobjc-framework-AddressBook",
            "pyobjc-framework-InstantMessage",
            "pyobjc-framework-Cocoa",
        ],
    )

