Update Launch Center Pro's [list] with your most used Pinboard tags

One of the coolest tricks from Launch Center Pro 2 is the [list] parameter, which allows you to create a prompt of options to pick. It's great because services with a specific set of search queries doesn't rely on your memory to be called, like your Pinboard tags. However, once in a while you must review and manually update your LCP's lists and that's a bummer, so I built a Pythonista script to update your Pinboard tags for you.

#coding: utf-8

import console
import keychain
import pickle

login = keychain.get_password('pinboard.in','pythonista')
if login is not None:
    user, pw = pickle.loads(login)
else:
    user, pw = console.login_alert('Pinboard Login', '')
    login = pickle.dumps((user, pw))
    keychain.set_password('pinboard.in', 'pythonista', login)

import requests
import json
pinboard_url = 'https://api.pinboard.in/v1/tags/get?format=json'
r = requests.get(pinboard_url, auth=(user, pw))
data = json.loads(r.text)
tags = data.items()

# minTags is the minimum amount of times this tag must link to a bookmark to be part of our final list.
# Change the value to 1 to grab all tags, for example.
minTags = 10
# This will generate a list without tags with less than minTags bookmarks.
filteredTags = [(str(k).lower(),int(v)) for k,v in tags if int(v) >= minTags]
# Change to True to sort your tags by name, otherwise they'll be sorted by count
sortByName = False

from operator import itemgetter

if sortByName:
    filteredTags = sorted(filteredTags, key=itemgetter(0))
else:
    filteredTags = sorted(filteredTags, key=itemgetter(1), reverse=True)

# finalTags kicks the conversion to a Launch Center Pro [list] converting each tag so we can use them to call Pinswift later.
finalTags = '|'.join([k for k,v in filteredTags])

title = 'Pick a Tag!'
label = 'Pick a Tag!'
description = 'Outcome for our Pythonista script to create a list with our most used tags from Pinboard ready to trigger at Pinswift'

# Comment the next line if you're not using Pinswift
action = 'pinswift:///u:%s/t:[list:%s|%s]' % (user, label, finalTags)

# Uncomment the next line if you're using Pincase
#action = 'pincaseapp://x-callback-url/open?mode=personal_tag&tag=[list:%s|%s]' % (label, finalTags)

# Uncomment the next line if you're using Pushpin
#action = 'pushpin://feed?user=%s&tags=[list:%s|%s]' % (user, label, finalTags)

from urllib import quote
import webbrowser

import_lcp = 'launchpro://import?url=%s&title=%s&description=%s' % (quote(action), quote(title), quote(description))

webbrowser.open(import_lcp)

Get it on GitHub here.

Well, you ask, how does it work? First, this script is only possible because Pinboard has an API we can call to get our list of tags, therefore, I'm sorry to disappoint you, but you won't be able to update your list of Clear lists, for example. We use and store our Pinboard login using the keychain module and collect a list with all our tags and how many times they were used in our bookmarks. This is nothing special and you can find the workflow up to this point around the web.

There is a couple of customizable variables for your delight in this script, the first of them is minTags, which is the minimum bookmark count a tag must have to join our final list. The next variable is sortByName, which when set to True will sort our tags by name, otherwise they will be sorted by count.

You can tweak a few more things on the Launch Center Pro action such as the title, description and label of the prompt. You don't have to change that unless you want to. If you're fine with my variables and your Pinboard client of choice is Pinswift, just hit Run and Pythonista will bounce to LCP and you'll be asked if you want to install it. Pick a spot on the grid1 and you're done.

You know I'm a nice guy and if you use Pushpin or Pincase, the actions to trigger these apps instead of Pinswift are commented in the script. Just follow the instructions and you're ready.

And that's why web services and Launch Center Pro are so cool.


  1. I strongly suggest you to replace the previous action if you're running it the second time. Just a hint.