Created
May 8, 2010 10:56
-
-
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!]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"))) + " ♫"; | |
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 <a href="http://blip.fm/{0}">{0}</a><br /><br /><i>", username)); | |
sb.Append(c.Server.HtmlEncode(Map(xnItem, "message", ""))); | |
sb.Append("</i><br />"); | |
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("<br /><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/"); | |
sb.Append(token); | |
sb.Append("&rel=1"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/"); | |
sb.Append(token); | |
sb.Append("&rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object>"); | |
} | |
} | |
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