Skip to content

Instantly share code, notes, and snippets.

@meklarian
Created May 8, 2010 10:56
Show Gist options
  • Save meklarian/394499 to your computer and use it in GitHub Desktop.
Save meklarian/394499 to your computer and use it in GitHub Desktop.
ASP.NET generic handler that converts a blip.fm user's recent blips into RSS 2.0 format, suitable for embedding on flavors.me [.NET 2.0 compatible!]
quick and dirty converter that calls blip.fm's api to pickup recent blips from a user.
some notes:
only plucks the most recent 25
embeds youtube players if the content was sourced from youtube
silverlight support redacted, as i was unable to source the xap from my domain and use it on flavors.me
individual song links on blip.fm are not documented, but the following URL layout works, replace USERNAME and BLIPID with respective items from the api
-> http://blip.fm/profile/USERNAME/blip/BLIPID
i used a stringbuilder because the output size is pretty small, and if the handler dies, i can still override the output and set the content type too.
REF: http://api.blip.fm/
see the results in action here: http://flavors.me/meklarian
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Data;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml;
namespace BlipFMRelay
{
public class DJ2RSS : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
HttpContext c = context;
HttpResponse resp = c.Response;
HttpRequest req = c.Request;
Regex reUser = new Regex(@"^\?\w+$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
string query = req.Url.Query;
if(!reUser.IsMatch(query)){_Abort(resp, 400, "Not a valid user, dude.");return;}
string username = query.Substring(1);
StringBuilder sb = new StringBuilder(8192);
try
{
sb.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?><rss version=\"2.0\"><channel>");
sb.Append(string.Format("<title>{0}'s Blips</title><link>http://blip.fm/{0}</link><description>Recent songs by {0} at blip.fm</description>", username, username));
XmlDocument DOM = new XmlDocument();
DOM.Load(string.Format("http://api.blip.fm/blip/getUserProfile.xml?username={0}", username));
XmlNodeList items = DOM.SelectNodes("/BlipApiResponse/result/collection/Blip");
foreach (XmlNode xnItem in items)
{
sb.Append("<item>");
// Title
string title = c.Server.HtmlEncode(string.Format("{0} - {1}", Map(xnItem, "artist", "Unknown Artist"), Map(xnItem, "title", "Unknown Song"))) + " &#9835;";
sb.Append("<title>");
sb.Append(title);
sb.Append("</title>");
// Link
sb.Append(string.Format("<link>http://blip.fm/profile/{0}/blip/{1}</link>", username, Map(xnItem, "id", "")));
// Description
sb.Append("<description>");
sb.Append(title);
sb.Append(string.Format(" blipped by &lt;a href=&quot;http://blip.fm/{0}&quot;&gt;{0}&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;", username));
sb.Append(c.Server.HtmlEncode(Map(xnItem, "message", "")));
sb.Append("&lt;/i&gt;&lt;br /&gt;");
string blipType = Map(xnItem, "type", "");
switch (blipType)
{
case "youtubeVideo":
emitYouTube(sb, Map(xnItem, "url", ""));
break;
case "songUrl":
// NOTE: doesn't look like we can cross-domain source a silverlight XAP at this time. Too bad.
//emitSilverlight(sb, c.Server.HtmlEncode(Map(xnItem, "url", "")));
break;
// NOTE: don't know how to handle these from the Blip.Fm feed.
case "fuzzSong":
break;
default:
break;
}
sb.Append("</description>");
// Publication Date
sb.Append("<pubDate>");
string unixTimeString = Map(xnItem, "unixTime", "0");
long seconds = 0;
if (!long.TryParse(unixTimeString, out seconds)) { seconds = 0; }
DateTime dt = new DateTime(1970, 1, 1);
dt = dt.AddSeconds(seconds);
sb.Append(dt.ToString("R"));
sb.Append("</pubDate>");
sb.Append("</item>");
}
sb.Append("</channel></rss>");
resp.ContentType = "text/xml";
resp.Write(sb);
}
catch (Exception)
{
_Abort(resp, 500, "Oh snap!");
}
}
public void emitYouTube(StringBuilder sb, string token)
{
if (!string.IsNullOrEmpty(token))
{
sb.Append("&lt;br /&gt;&lt;object width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/");
sb.Append(token);
sb.Append("&amp;rel=1&quot;&gt;&lt;/param&gt;&lt;param name=&quot;wmode&quot; value=&quot;transparent&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/");
sb.Append(token);
sb.Append("&amp;rel=1&quot; type=&quot;application/x-shockwave-flash&quot; wmode=&quot;transparent&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;");
}
}
public void emitSilverlight(StringBuilder sb, string url)
{
if (!string.IsNullOrEmpty(url))
{
// REDACTED: Sorry. I'm unfamiliar with silverlight's security model and embedding doesn't work yet.
}
}
public string Map(XmlNode xn, string xpath, string defaultValue)
{
if (object.ReferenceEquals(xn, null)) { return defaultValue; }
if (string.IsNullOrEmpty(xpath)) { return xn.InnerText ?? defaultValue; }
XmlNode xnTarget = xn.SelectSingleNode(xpath);
return xnTarget.InnerText ?? defaultValue;
}
public void _Abort(HttpResponse resp, int code, string msg)
{
resp.StatusCode = code;
resp.ContentType = "text/plain";
resp.Write(msg);
}
public bool IsReusable
{
get
{
return true;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment