TinyURLService

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

Sources

TinyURLService.py

import Cocoa
from PyObjCTools import AppHelper
import objc
import traceback
import urllib
import urllib2

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(dict(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:
            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 = dict(
    CFBundleIdentifier = "net.sf.pyobjc.TinyURLService",
    LSBackgroundOnly = 1,
    NSServices = [
        dict(
            NSKeyEquivalent=dict(
                default="0",
            ),
            NSMenuItem=dict(
                default="Shorten URL"
            ),
            NSMessage="doTinyURLService",
            NSPortName="TinyURLService",
            NSReturnTypes=[
                "NSStringPboardType",
            ],
            NSSendTypes=[
                "NSStringPboardType",
            ],
        ),
    ],
)


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

Resources