« 10 Slightly Unusual Ideas to Mildly Perturb Microsoft | Main | Discovering Objects in Monad »

June 25, 2005

Monad and RSS

Since Monad and RSS are both extra-cool right now, I wrote a couple of scripts to scan RSS feeds in Monad.

The first one is used as follows:

add-feed http://www.proudlyserving.com/index.xml

It stores the URI in the registry for use later (see below):

# add-feed.msh

$regpath = "HKCU:\Software\Microsoft\MshReader"
$feedpath = $args[0]

# make sure name starts with "http://" (case-insensitive comparison)

if ($feedpath.Substring(0,7) -ine "http://") {
    write-host "Feed name `"$feedpath`" does not start with `"http://`""
    exit
}

# feed name is domain name

$feedname = $feedpath.Substring(7).Split("/")[0]

# make sure our overall path exists

if (!$(test-path $regpath)) {
    new-item $regpath
}

# create the key for this feed...

$newpath = combine-path $regpath $feedname

new-item $newpath | out-null

# ...and the value for the URI

new-item $newpath -Name "URI" -Type String -Value $feedpath | out-null

# if it worked, then print a message

if ($(test-path $newpath)) {
    write-host "Created feed for `"$feedpath`" named `"$feedname`""
}

The second script uses the registry information stored by add-feed.msh to dump out the titles and dates of every item in the RSS feeds. It uses the XML support in Monad (the [xml] cast in the code below) to convert the feed into an object that can be accessed like any other object in Monad:

# get-feeds.msh

$regpath = "HKCU:\Software\Microsoft\MshReader"
$feeds = get-childitem $regpath

# loop through all stored feeds

foreach ($f in $feeds) {

    # get the URI for the feed from the registry

    $feedpath = combine-path $regpath $f.MshChildName
    $uripath = combine-path $feedpath "URI"
    $feeduri = $(get-property $uripath)."(default)"
    write-host feeduri $feeduri

    # read the content from $feeduri as XML

    $wc = new-object System.Net.WebClient
    $s = $wc.OpenRead($feeduri)
    $sr = new-object System.IO.StreamReader($s)
    $rssdata = [xml]$sr.ReadToEnd()

    # display title

    write-host $rssdata.rss.channel.title

    # display title and date of each item

    $rssx.rss.channel.item |
        foreach-object {
            write-host "-" $_.title
            write-host "     " $_.pubDate
        }

}

If you run get-feeds, you get a display that looks like:

feeduri http://www.proudlyserving.com/index.xml
Proudly Serving My Corporate Masters
- 10 Slightly Unusual Ideas to Mildly Perturb Microsoft
     Thu, 23 Jun 2005 22:26:25 -0800
- Microsoft: We Are Professional Grade?
     Wed, 22 Jun 2005 16:44:19 -0800
- Building Community at Microsoft
     Sun, 19 Jun 2005 22:09:39 -0800
...

(NOTE: The web and registry access code could probably be cleaned up, but I was stealing from some other code that does it this way, so bear with me.)

In the next part, we will improve get-feeds so it only displays feeds that have been updated...or at least I hope we will do that!

Posted by AdamBa at June 25, 2005 10:38 PM

Trackback Pings

TrackBack URL for this entry:
http://proudlyserving.com/cgi-bin/mt-tb.cgi/254

Comments

With the exception of the XML parsing bits which look cool, why does this look like it takes about 5 times as many lines as equivalent VBscript?

Posted by: Blonkas at June 26, 2005 12:37 AM

looks kind of like an uglier perl

Posted by: grant at June 26, 2005 08:33 AM

To each his/her own...if you like VBscript or Perl, then Monad can launch those scripts for you.

Monad is leveraging the underlying .Net classes. Now, I did discover that my HTTP access could be done more easily. Instead of having:

$s = $wc.OpenRead($feeduri)

$sr = new-object System.IO.StreamReader($s)

$rssdata = [xml]$sr.ReadToEnd()

I could just do:

$rssdata = [xml]$wc.DownloadString($feeduri)

which would simplify the code a bit.

- adam

Posted by: Adam Barr at June 26, 2005 02:11 PM

Instead of trying to parse the URL by hand, why not use the System.Uri class and retrieve the Scheme property? Then you would have a good way to support https as well as http.

Posted by: Keith J. Farmer at June 27, 2005 03:08 PM

Keith - the only reason is lack of knowledge on my part! Excellent idea. And the nice thing about Monad is I can just do it, I don't have to wait for some intermediate code to support it. Oops, sounding like a shameless Monad shill, but it IS cool.

- adam

Posted by: Adam Barr at June 27, 2005 03:32 PM

Shell-shill away -- you folk have a great thing going.

.. So I was suggesting to the IronPython devs that IP and Monad could do some deeper integration. Normal exits only return an int -- why not (optionally) allow a richer return. Provide an interface for console apps to optionally implement and you could use that as an alternate entry point. It's a more app-ish version of a cmdlet, I think.

And then there's the idea I posted to Lee's blog, I believe, about hooking up with the C-omega folks at MSR to figure out a good way to mount a database to the shell, as you do the registry and filesystem, such that you can navigate the data, execute procs, and otherwise do yet more things shells haven't, traditionally, done. Some dynamic code generation to create a strongly-typed database proxy, I figure, and you could do it. Ditto with Web Services (which you're practically doing now).

(Make a OpenLDAP provider, and you'll solve an annoying problem at my office.)

You already have the framework...

Don't mind me, I'm sick.

Posted by: Keith J. Farmer at June 27, 2005 11:56 PM

And I still think a CPAN-like facility would be a good way to distribute and install .msh files.

Posted by: Keith J. Farmer at June 28, 2005 12:05 AM