TinyURLService

Another simple service, this one converts URL or strings from the pasteboard to tinyurl.com equivalents.

Sources

TinyURLService.py

import traceback
import urllib
import urllib2

import Cocoa
import objc
from PyObjCTools import AppHelper


def serviceSelector(fn):
    # this is the signature of service selectors
    return objc.selector(fn, signature=b"v@:@@o^@")


def ERROR(s):
    # NSLog("ERROR: %s", s)
    return s


NAME = "TinyURLService-0.0"
TINYURL_API = "http://tinyurl.com/api-create.php"


def getTinyURL(url):
    data = urllib.urlencode({"url": url, "source": NAME})
    return urllib2.urlopen(TINYURL_API, data).read().decode("utf-8")


class TinyURLService(Cocoa.NSObject):
    @serviceSelector
    def doTinyURLService_userData_error_(self, pboard, data, error):
        # Mail.app in 10.4.1 doesn't do NSURLPboardType correctly!
        # Probably elsewhere too, so we just use strings.
        try:
            types = pboard.types()
            url = None

            if Cocoa.NSStringPboardType in types:
                urlString = pboard.stringForType_(Cocoa.NSStringPboardType)
                url = Cocoa.NSURL.URLWithString_(urlString.strip())
                if url is None:
                    return ERROR(
                        Cocoa.NSLocalizedString(
                            "Error: Given URL was not well-formed.",
                            "Given URL not well-formed.",
                        )
                    )

            if url is None:
                return ERROR(
                    Cocoa.NSLocalizedString(
                        "Error: Pasteboard doesn't contain a valid URL.",
                        "Pasteboard doesn't contain a valid URL.",
                    )
                )

            urlString = url.absoluteString()

            res = getTinyURL(urlString.UTF8String())

            resURL = Cocoa.NSURL.URLWithString_(res)
            if resURL is None:
                return ERROR(
                    Cocoa.NSLocalizedString(
                        "Error: Resultant URL was not well-formed.",
                        "Resultant URL not well-formed.",
                    )
                )
            pboard.declareTypes_owner_([Cocoa.NSStringPboardType], None)
            pboard.setString_forType_(resURL.absoluteString(), Cocoa.NSStringPboardType)
            return ERROR(None)
        except:  # noqa: E722, B001
            traceback.print_exc()
            return ERROR("Exception, see traceback")


def main():
    serviceProvider = TinyURLService.alloc().init()
    Cocoa.NSRegisterServicesProvider(serviceProvider, "TinyURLService")
    AppHelper.runConsoleEventLoop()


if __name__ == "__main__":
    main()

rebuild.py

#!/usr/bin/env python
"""
Quickie script to update the services
"""
import AppKit

AppKit.NSUpdateDynamicServices()

setup.py

"""
Script for building the example.

Usage:
    python3 setup.py py2app
"""
from setuptools import setup

plist = {
    "CFBundleIdentifier": "net.sf.pyobjc.TinyURLService",
    "LSBackgroundOnly": 1,
    "NSServices": [
        {
            "NSKeyEquivalent": {"default": "0"},
            "NSMenuItem": {"default": "Shorten URL"},
            "NSMessage": "doTinyURLService",
            "NSPortName": "TinyURLService",
            "NSReturnTypes": ["NSStringPboardType"],
            "NSSendTypes": ["NSStringPboardType"],
        }
    ],
}


setup(
    app=["TinyURLService.py"],
    options={"py2app": {"plist": plist}},
    setup_requires=["py2app", "pyobjc-framework-Cocoa"],
)