« Discovering Objects in Monad | Main | Flex Time »

June 27, 2005

Monad and RSS, Part 2

Continuing on with our command-line RSS reader, I first cleaned up my add-feed script:

# add-feed.msh

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

# make sure name is a proper URI

if (!$feedpath.IsAbsoluteUri) {
    write-host "Feed name `"$feedpath`" is not a valid URI"
    exit
}

# feed name is domain name

$feedname = $feedpath.Host

# 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

set-property $newpath -Property "URI" -Type String -Value $feedpath.AbsoluteUri | out-null

# if it worked, then print a message

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

I now parse the URI by creating a System.Uri (idea courtesy of Keith Farmer) and I store the URI in a value instead of a subkey (the Monad registry provider treats registry values as "properties").

Next, I improved get-feeds.msh. I changed the registry access to reflect the fact that URI is now a value, not a subkey. More importantly, I added another value SeenList which is a REG_MULTI_SZ that stores which entries have already been viewed (I identify them by pubDate, don't know if that is official RSS reader best practice, but it seems to work). I read the REG_MULTI_SZ out of the registry for each feed, check each pubDate to see if it is in SeenList, if it is I skip it, if it isn't I display it and add it to SeenList. At the end I write SeenList back to the registry:

# 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
    $feeduri = $(get-property $feedpath).URI

    # read the content from $feeduri as XML

    $wc = new-object System.Net.WebClient
    $rssdata = [xml]$wc.DownloadString($feeduri)

    # display title

    write-host $rssdata.rss.channel.title

    # get list of items already seen

    $seenlist = [array]($(get-property $feedpath).SeenList)

    # display title and date of each item

    $rssdata.rss.channel.item |
        foreach-object {
            $seen = $false
            for ($i = 0; $i -lt $seenlist.length; ++$i) {
                if ($seenlist[$i] -eq $_.pubDate) {
                    $seen = $true
                    break
                }
            }
            if (!$seen) {
                write-host "-" $_.title
                write-host "     " $_.pubDate
                if ($seenlist -eq $null) {
                    $seenlist = [array]$_.pubDate
                } else {
                    $seenlist += $_.pubDate
                }
            }
        }

    set-property $feedpath -Property SeenList -Type MultiString -Value $seenlist | out-null
}

It seems to work:

MSH> add-feed "http://www.proudlyserving.com/index.xml"
Created feed for "http://www.proudlyserving.com/index.xml" named "www.proudlyserving.com"
MSH> add-feed "http://radio.weblogs.com/0001011/rss.xml"
Created feed for "http://radio.weblogs.com/0001011/rss.xml" named "radio.weblogs.com"
MSH> get-feeds
Scobleizer: Microsoft Geek Blogger
- SQL Server podcast starts up
     Tue, 28 Jun 2005 02:08:19 GMT
- Blogging food fight breaks out
     Tue, 28 Jun 2005 01:41:00 GMT
...
Proudly Serving My Corporate Masters
- Discovering Objects in Monad
     Sun, 26 Jun 2005 21:24:50 -0800
- Monad and RSS
     Sat, 25 Jun 2005 22:38:53 -0800
...

W00OO00OO00t!! In our next installment, we'll look into how we can display more details about each item (in a nice, user-modifiable, Monad-y way).

Posted by AdamBa at June 27, 2005 10:42 PM

Trackback Pings

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

Comments

And we're not going to mention what happens to performance when the feed gets more than a couple of hundred posts, right?

REG_MULTI_SZ is convenient, but not the most efficient database out there.

Posted by: Larry Osterman at June 28, 2005 06:36 AM

Hmm yes, sample code ya know. Although it would be impressive (but not impossible) if the performance of the registry access actually mattered compared to the download off the web.

- adam

Posted by: Adam Barr at June 28, 2005 10:56 AM

One comment on the add-feed script: using the Host part of the URI isn't sufficiently unique. Consider all the blogs hosted at blogspot.com or livejournal.com.

Thanks for posting this series on Monad. I've got it sitting on my machine but haven't done anything with it yet. This series of posts is encouraging me to go play with it.

Posted by: Tommy Williams at June 28, 2005 11:19 AM

Isolated Storage, perhaps?

Posted by: Keith J. Farmer at June 28, 2005 05:44 PM

Tommy: Yes, I realized that when I added Scoble's feed. I guess there's no reason not to use the full URI (minus "http://", maybe) as the registry key. As of now those key names don't really matter except as a convenience when viewing the registry.

- adam

Posted by: Adam Barr at June 28, 2005 06:48 PM