Skip to content

Instantly share code, notes, and snippets.

@valpackett
Last active September 7, 2023 21:01
Show Gist options
  • Save valpackett/5189568 to your computer and use it in GitHub Desktop.
Save valpackett/5189568 to your computer and use it in GitHub Desktop.
INSTANT Pinboard search from Alfred 2

INSTANT Pinboard search from Alfred 2

I've had a Python script that makes an HTML Bookmarks file for LaunchBar.
Now that I use Alfred 2, I modified it to make XML for Alfred.
This allows me to search my bookmarks with GREP SPEED!

Installation

First, add your token (from pinboard.in/settings/password) to ~/.netrc

machine pinboard.in
  password username:T0K3N11111111111

Then:

  1. Get pinboard-xml (I've also attached it to the gist in case I change something in my dotfiles repo)
  2. Put in the folder where you keep your scripts (eg. ~/bin)
  3. chmod +x it
  4. Add to crontab (eg. */30 * * * * ~/bin/pinboard-xml)
  5. Make a workflow in Alfred 2 with the following Script Filter (using /bin/bash) to Open URL:
echo "<?xml version=\"1.0\"?>"
echo "<items>"
cat $HOME/.bookmarks.xml | grep "{query}"
echo "</items>"

Enjoy!

#!/usr/bin/env python
# Made by Val Packett, ages ago in a past life
# https://gist.github.com/valpackett/5189568 <- also on gist
# Feel free to steal it, but attribution is nice
import os
import sys
import json
import netrc
import errno
import urllib2
def die(msg, err):
sys.stderr.write(msg)
sys.exit(err)
login = netrc.netrc().authenticators('pinboard.in')
if not login:
die('pinboard.in not found in netrc; add token as password', errno.ENODATA)
try:
getreq = urllib2.urlopen('https://api.pinboard.in/v1/posts/all?format=json&auth_token='+login[2])
if getreq.code == 429:
die('too often', errno.EPERM)
if getreq.code != 200:
die('http error %s on getting, maybe wrong password?' %
getreq.code, errno.EACCES)
items = json.loads(getreq.read())
res = '''<?xml version="1.0"?>
<items>'''
for item in items:
href = item['href'].encode('utf-8').replace('\n', '').replace('&', '&amp;')
desc = item['description'].encode('utf-8').replace('\n', '').replace('&', '&amp;')
res += '<item uid="%s" arg="%s"><title>%s</title><subtitle>%s</subtitle></item>\n' % \
(href, href, desc, href)
res += '</items>'
open(os.environ['HOME']+'/.bookmarks.xml', 'w').write(res)
except urllib2.HTTPError:
die('connection error', errno.ECONNREFUSED)
@cjs226
Copy link

cjs226 commented May 24, 2013

Thanks for this!

@wxn0000
Copy link

wxn0000 commented Feb 6, 2014

Thank you so much for this little tool! I really like it!

However, whenever there is a & (ampersand) in the URL or the description, the grep command return couldn't be correctly parsed by Alfred, therefore this particular item won't show up in the search result.

Also, it was working fine until today. When I run

/opt/local/bin/python2.7 /Users/xiaoning/Scripts/pinboard_xml.py

these are the error messages:

Traceback (most recent call last):
  File "/Users/xiaoning/Scripts/pinboard_xml.py", line 16, in <module>
    login = netrc.netrc().authenticators('pinboard.in')
  File "/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/netrc.py", line 35, in __init__
    self._parse(file, fp, default_netrc)
  File "/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/netrc.py", line 113, in _parse
    " the owner", file, lexer.lineno)
netrc.NetrcParseError: ~/.netrc access too permissive: access permissions must restrict access to only the owner (/Users/xiaoning/.netrc, line 3)

I may have updated some python packages today. Did that somehow broke the script? I'd greatly appreciate if you can help me fix this. Many thanks!

@wxn0000
Copy link

wxn0000 commented Feb 7, 2014

chmod 600 ~/.netrc

solved it!

@wxn0000
Copy link

wxn0000 commented Feb 7, 2014

To solve the "&" issue, try changing:

href = item['href'].encode('utf-8').replace('\n', '')
desc = item['description'].encode('utf-8').replace('\n', '')

to

href = item['href'].encode('utf-8').replace('\n', '').replace('&', '&amp;)
desc = item['description'].encode('utf-8').replace('\n', '').replace('&', 'and')

In case there are "&" present in your pinboard bookmark description or url.

@jmjeong
Copy link

jmjeong commented Feb 20, 2014

@valpackett
Copy link
Author

Updated to use urllib2 (no deps!) and API token auth instead of password auth.

@floer32
Copy link

floer32 commented Mar 24, 2019

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment