<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>toxicsoftware.com &#187; pinboard</title>
	<atom:link href="http://toxicsoftware.com/tag/pinboard/feed/" rel="self" type="application/rss+xml" />
	<link>http://toxicsoftware.com</link>
	<description>RANDOMIZE USR 0</description>
	<lastBuildDate>Sun, 01 Aug 2010 17:49:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Add to Pinboard</title>
		<link>http://toxicsoftware.com/add-to-pinboard/</link>
		<comments>http://toxicsoftware.com/add-to-pinboard/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 15:12:37 +0000</pubDate>
		<dc:creator>schwa</dc:creator>
				<category><![CDATA[Default]]></category>
		<category><![CDATA[pinboard]]></category>

		<guid isPermaLink="false">http://toxicsoftware.com/?p=450</guid>
		<description><![CDATA[In my previous post I suggested adapting my Python script for use in a Snow Leopard service. I decided to quickly whip this up myself. So here is a (Snow Leopard only!) service that can add URLs to pinboard.in. Unzip &#8230; <a href="http://toxicsoftware.com/add-to-pinboard/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://toxicsoftware.com/wordpress/uploads/Add%20to%20pinboard.zip">previous post</a> I suggested adapting my Python script for use in a Snow Leopard service. I decided to quickly whip this up myself. So <a href="http://toxicsoftware.com/wordpress/uploads/Add%20to%20pinboard.zip">here is</a> a (Snow Leopard only!) service that can add URLs to <a href="http://pinboard.in">pinboard.in</a>. Unzip the file and copy it to ~/Library/Services then run this little shell script to set up a keychain item for your pinboard account:</p>

<pre><code>#!/bin/sh

HOST=api.pinboard.in
read -p "Username: " USERNAME
read -p "Password: " -s PASSWORD
security add-internet-password -U -r http -s "$HOST" -a "$USERNAME" -w "$PASSWORD"
</code></pre>

<p>And the script also uses the <a href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup 3rd party</a> python module to extract the title of the webpage you&#8217;re linking to. You&#8217;ll need to install beautiful soup:</p>

<pre><code>sudo easy_install beautifulsoup
</code></pre>

<p>If you&#8217;ve correctly installed the service you can enable/disable it and assign it a keyboard shortcut from the Keyboard preference pane:</p>

<div style="text-align:center;"><a href="http://www.flickr.com/photos/61285556@N00/4192220957" title="View 'Screen shot 2009-12-17 at 10.09.36' on Flickr.com"><img border="0" width="100" alt="Screen shot 2009-12-17 at 10.09.36" src="http://farm5.static.flickr.com/4044/4192220957_32687ff498_t.jpg" height="91"/></a></div>

<p>When enabled you should be able to see an entry in the application&#8217;s service menu:</p>

<div style="text-align:center;"><a href="http://www.flickr.com/photos/61285556@N00/4192209095" title="View 'Screen shot 2009-12-17 at 10.03.06' on Flickr.com"><img border="0" width="100" alt="Screen shot 2009-12-17 at 10.03.06" src="http://farm3.static.flickr.com/2783/4192209095_7bf4b12223_t.jpg" height="51"/></a></div>
]]></content:encoded>
			<wfw:commentRss>http://toxicsoftware.com/add-to-pinboard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webloc to Pinboard</title>
		<link>http://toxicsoftware.com/webloc-to-pinboard/</link>
		<comments>http://toxicsoftware.com/webloc-to-pinboard/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 14:34:40 +0000</pubDate>
		<dc:creator>schwa</dc:creator>
				<category><![CDATA[Default]]></category>
		<category><![CDATA[hazel]]></category>
		<category><![CDATA[pinboard]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[url]]></category>
		<category><![CDATA[webloc]]></category>

		<guid isPermaLink="false">http://toxicsoftware.com/?p=445</guid>
		<description><![CDATA[If I want to keep a URL around for later I generally drag the URL from Safari&#8217;s URL bar onto the desktop. This creates an &#8220;internet clipping file&#8221; (with a .webloc file extension). These files are like little self contained &#8230; <a href="http://toxicsoftware.com/webloc-to-pinboard/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If I want to keep a URL around for later I generally drag the URL from Safari&#8217;s URL bar onto the desktop. This creates an &#8220;internet clipping file&#8221; (with a .webloc file extension). These files are like little self contained bookmarks that, when double clicked open the linked webpage in Safari. Because they&#8217;re just ordinary files, you can manage them like any other file, store them in folders, copy them around, delete them, etc.</p>

<p>Eventually these clippings will get deleted or filed in a folder and forgotten. In the past I&#8217;ve written Spotlight importers to try and gather all these clippings and then export them in a format I could use in a bookmark manager application, such as WebNoteHappy. But most bookmark manager apps tend to be quite limited and I&#8217;ve found online services such as <a href="http://delicious.com">delicious</a>, <a href="http://instapaper.com">instapaper</a> and now <a href="http://pinboard.in">pinboard.in</a> to be far superior to any desktop application.</p>

<p>But getting from an internet clipping on my desktop to an entry in an online bookmark manager usually involves a lot of manual labour.</p>

<p>I&#8217;ve found a great solution using <a href="http://www.noodlesoft.com/hazel.php">Hazel</a> and a custom Python script. I have a Hazel rule that finds files with a &#8220;.webloc&#8221; file extension on my desktop. The rule then runs a single python script to add the URL to my pinboard.in account and then moves the file into the trash. Usually Hazel notices the clipping, adds it to pinboard.in and trashes the file within a couple of seconds.</p>

<div style="text-align:center;"><a href="http://www.flickr.com/photos/61285556@N00/4192151805" title="View 'Screen shot 2009-12-17 at 09.12.35' on Flickr.com"><img border="0" width="100" alt="Screen shot 2009-12-17 at 09.12.35" src="http://farm3.static.flickr.com/2495/4192151805_d5b0ce0737_t.jpg" height="77"/></a></div>

<p>The python script is where all the magic happens:</p>

<pre><code>#!/usr/bin/python

import sys
import urllib
import urllib2
import re
import subprocess
import Foundation
from Carbon import File, Files, Res

def infoForWebloc(inPath):
    theDisplayName = Foundation.NSFileManager.defaultManager().displayNameAtPath_(inPath)
    resNum = Res.FSOpenResourceFile(inPath, File.FSGetResourceForkName(), Files.fsRdPerm)
    Res.UseResFile(resNum)
    theResource = Res.Get1Resource('url ', 256)
    theURLFromResource = theResource.data
    Res.CloseResFile(resNum)
    theData = Foundation.NSData.dataWithContentsOfFile_(inPath)
    thePropertyList = Foundation.NSPropertyListSerialization.propertyListWithData_options_format_error_(theData, 0, None, None)
    theURLFromData = thePropertyList['URL'] 
    return theDisplayName, theURLFromResource

def getAccount(inServer):
    theArguments = ['security', 'find-internet-password', '-s', inServer, '-g']
    thePipe = subprocess.Popen(theArguments, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    theOutput = thePipe.stdout.read()
    theMatch = re.search(r'"acct"&lt;blob&gt;="(.+)"', theOutput)
    theUsername = theMatch.groups()[0]
    theOutput = thePipe.stderr.read()
    theMatch = re.match(r'^password: "(.+)"$', theOutput)
    thePassword = theMatch.groups()[0]
    return theUsername, thePassword

def upload(inURL, inDescription):
    password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
    top_level_url = "https://api.pinboard.in/v1"
    theUsername, thePassword = getAccount('api.pinboard.in')
    password_mgr.add_password(None, top_level_url, theUsername, thePassword)
    handler = urllib2.HTTPBasicAuthHandler(password_mgr)
    opener = urllib2.build_opener(handler)
    inURL = urllib.quote(inURL)
    inDescription = urllib.quote(inDescription)
    theURL = 'https://api.pinboard.in/v1/posts/add?url=%s&amp;shared=no&amp;replace=yes&amp;description=%s' % (inURL, inDescription)
    theResult = opener.open(theURL)

def main(args):
    for thePath in args:
        theDescription, theURL = infoForWebloc(thePath)
        upload(theURL, theDescription)

if __name__ == '__main__':
    main(sys.argv[1:])
</code></pre>

<p>This script reads the .webloc file to extract the URL (.webloc files store the URL in both the Carbon resource fork and in the data fork in a property list format, this script extracts the URL from both locations but only uses the URL from the resource fork.</p>

<p>Then script uploads the URL to pinboard.in via pinboard.in&#8217;s delicious style API. The script gets your pinboard.in username and password from your keychain. To add the username and password to your keychain you&#8217;ll want to run this little shell script.</p>

<pre><code>#!/bin/sh

HOST=api.pinboard.in
read -p "Username: " USERNAME
read -p "Password: " -s PASSWORD
security add-internet-password -U -r http -s "$HOST" -a "$USERNAME" -w "$PASSWORD"
</code></pre>

<p>You can download the Hazel rule <a href="http://toxicsoftware.com/wordpress/uploads/Desktop.hazelrules.zip">here</a>, but do remember to set up your pinboard.in keychain item before installing it.</p>

<p>Instead of using the entire desktop as a sort of a dropbox for URLs you could easily adapt the script and put it into a automator action or perhaps a system service.</p>
]]></content:encoded>
			<wfw:commentRss>http://toxicsoftware.com/webloc-to-pinboard/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
