Simpy and Powershell
I have spent a lot of time lately working with Powershell, Microsoft's next generation command-line environment. Built on the .NET architecture, Powershell is extremely versatile and robust. It provides excellent support for dynamic manipulation of XML content, a feature that is particularly useful when used in conjunction with .NET's Internet functionality.
Earlier this week, I did a bit of experimentation and figured out how to use Powershell to interact with the Simpy social bookmark service. When I developed Ruby bindings for the Simpy REST API, the most frustrating impediment was Simpy's mildly awkward redirect system. Ruby's Net::HTTP class doesn't handle redirects automatically, so I had to manually implement support for handling a 302 response. I also had to manually create the authentication string for the header using Ruby's Base64 encoding library. Powershell handles both of those things automatically. The .NET Net.NetworkCredential object automatically generates the proper header string when provided with login information, and the Net.WebClient object's downloadString method does proper redirect handling on its own without necessitating further intervention.
Powershell handles XML very well, which also made the task much easier. Certain aspects of the XML API seem needlessly verbose or a little bit eccentric. For instance, when you use the select-object Cmdlet to access an element node, it returns the node itself rather than the value of the node in some cases. Based on my own experiments, I think that it fails to show the actual text value when the contents of the node are wrapped in a CDATA block. In order to extract the text value, one must use the get_innerText method.
The following example demonstrates how to use Simpy's REST API from the command-line to display the nicknames and tags of recent bookmarks:
> $connect = new-object Net.WebClient
> $connect.credentials = new-object Net.NetworkCredential("segphault", "XXXXXX")
> $links = [xml]$connect.downloadString("http://simpy.com/simpy/api/rest/GetLinks.do")
> $links.links.link | select {$_.nickname.get_innertext()}, {$_.tags.tag | % {$_.get_innnertext()}}
$_.nickname.get_innertext() $_.tags.tag | % {$_.get_innertext()}
--------------------------- ------------------------------------
GNOME Journal article about Tinymail {development, software, email, GNOME...
Comparison of various open source gr... {development, software, graphics, Li...
Agile programming considered (mostly... development
Metaprogramming with Ruby {Ruby, development, metaprogramming}
Linus talks like a pirate {LinuxArs, Linus, Linux Kernal, soft...
Mark Shuttleworth talks about Ubuntu... {LinuxArs, Ubuntu, Debian}
Optimal use of fonts on Linux {LinuxArs, X11, fonts}
IBM to provide commercial support fo... {LinuxArs, Eclipse, IBM}
McDonalds changes McFlurry cups to s... strange
GNOME orphaned thumbnail remover {LinuxArs, GNOME, Glade, Python...}
Note that the inability to consistently extract the text value of a node with select makes it necessary to use a loop in order to display the tags as a list. If CDATA blocks weren't so troublesome, the select invocation would be a lot more concise. Despite the minor deficiencies, Powershell is well suited for this sort of work.
I also experimented with listing tag information. The following demonstrates how to display a list of tags and the number of bookmarks associated with each tag:
> ([xml]$connect.downloadString("http://simpy.com/simpy/api/rest/GetTags.do")).tags.tag
name count
---- -----
LinuxArs 42
software 22
GNOME 8
strange 6
Mono 5
science 4
Qt 4
...
If I can find some time for further experimentation, I might throw together a few Powershell Cmdlets to automate link and tag manipulation.
Tags: shell, powershell, simpy, programming, dotnet
Posted on 2006-09-300 comments
