last.fm listings with amazon intergration via coldfusion
So I have to admit that i've become a bit of a last.fm addict. It's a great application and the personal radio is just great. Now for some reason I like the whole thing about people being able to see what music ones been listening to. I have an affliate account with amazon and thougth hey - would it be cool to intergrate with amazon from my song listings, so this is what i came up with to intergrate with Rays BlogCFC. Just remove the cfmodule tag to make it stand alone. (Please remember this is the 1st draft)
/**
* Get xml datafeeds for last.fm and links the artists from the page to you amazon account
*
* @param AmazonTagID Your amazonID, you can get this from vreating a link in the amazon affiliate area.(Required)
* @author Nick Tong (n.tong@talkwebsolutions.co.uk)
* @version 0.1, April 3, 2006
* IF USED PLEASE CREDIT ME :)
*/
--->
<cfsetting enablecfoutputonly=true>
<cfoutput>
<cfsavecontent variable="request.JSHeader">
<script type="text/javascript" src="includes/javascript/tipster.js"></script>
<style type="text/css">
.musictable{
width:100%;
}
th{
text-align:left;
font:12px;
}
tr.even{
padding-top: 2px;
padding-bottom: 2px;
border-right: 1px solid ##000000;
padding-left: 3px;
padding-right: 3px;
background-color: ##E0DFCB;
}
tr.odd{
padding-top: 2px;
padding-bottom: 2px;
border-right: 1px solid ##000000;
padding-left: 3px;
padding-right: 3px;
background-color: ##FFFFF;
}
</style>
</cfsavecontent>
<cfhtmlhead text="#request.JSHeader#">
</cfoutput>
<cfif structKEyExists(url,"clearList")>
<cfset tmp = structdelete(application,"recent")>
<cfset tmp = structdelete(application,"lastfetch")>
</cfif>
<cfmodule template="tags/layout.cfm" title="My Last.FM Listing">
<!--- lets not run the page on every request - lets load the page into the application scope and reload it every 10 mins (this can be changed) --->
<cftry>
<!---Make sure we have data in the cache for the key--->
<cfparam name="application.recent" default="">
<cfparam name="application.lastFetch" default="#now()#">
<!---Get the expiration date for the data, in mins--->
<cfset maxDate = DateAdd("n",10,application.lastFetch)>
<!---Does the key contain content and is the expiration date greater than the current date, if not lets get the data again--->
<cfif len(application.recent) AND DateCompare(maxDate,Now()) EQ 1>
<cfoutput>
#application.recent#
</cfoutput>
<cfelse>
<!--- n.tong@talkwebsolutions.co.uk | get the feeds --->
<cfhttp url="http://ws.audioscrobbler.com/1.0/user/quiksilv/recenttracks.xml" method="get"></cfhttp>
<cfset recenttracks = XmlParse(cfhttp.FileContent) />
<cfset recenttracksDetail = XmlSearch(recenttracks, "/recenttracks/track") />
<cfset recenttracksShowCount = ArrayLen(recenttracksDetail)>
<cfhttp url="http://ws.audioscrobbler.com/1.0/user/quiksilv/topartists.xml" method="get"></cfhttp>
<cfset topartists = XmlParse(cfhttp.FileContent) />
<cfset topArtistNames = XmlSearch(topartists, "/topartists/artist") />
<cfset topArtistShowCount = 20> <!--- ArrayLen(topArtistNames) --->
<cfhttp url="http://ws.audioscrobbler.com/1.0/user/quiksilv/topalbums.xml" method="get"></cfhttp>
<cfset topAlbums = XmlParse(cfhttp.FileContent) />
<cfset topAlbumsNames = XmlSearch(topalbums, "/topalbums/album") />
<cfset topAlbumsShowCount = ArrayLen(topAlbumsNames)>
<cfhttp url="http://ws.audioscrobbler.com/1.0/user/quiksilv/toptracks.xml" method="get"></cfhttp>
<cfset toptracks = XmlParse(cfhttp.FileContent) />
<cfset toptracksNames = XmlSearch(toptracks, "/toptracks/track") />
<cfset toptracksShowCount = ArrayLen(toptracksNames)>
<!--- n.tong@talkwebsolutions.co.uk | set the amazonTagID --->
<cfset request.amazonTagID = "YOUR-AMAZON-TAG-HERE" />
<cfoutput>
<cfsavecontent variable="application.Recent">
<script type="text/javascript"><!--
// First, create a new tip object, and pass it its own name so it can reference itself. var docTips = new TipObj('docTips');
with (docTips)
{
template = '%3%';
<cfloop index="z" from="1" to="#topAlbumsShowCount#">
<cfif len(topalbumsNames[z].mbid.XmlText)>
tips.#rereplace(topalbumsNames[z].mbid.XmlText,"[^a-z]","","all")# = new Array(5, 5, 150, '<img src=#topalbumsNames[z].image.small.XmlText#>');
</cfif>
</cfloop>
}
//--></script> <div id="docTipsLayer" style="position: absolute; z-index: 10000; visibility: hidden;
left: 0px; top: 0px; width: 10px"> </div>
<h2>Recent Tracks</h2>
<table title="My Recent Tracks" summary="Check out my most recent songs and artisits." class="musictable">
<tr>
<th>Played</th>
<th>Track</th>
<th>Artist</th>
</tr>
<cfloop index="z" from="1" to="#recenttracksShowCount#">
<tr class="<cfif z mod 2>even<cfelse>odd</cfif>">
<td>
#recenttracksDetail[z].date.XmlText#
</td>
<td>
#recenttracksDetail[z].name.XmlText#
</td>
<td>
<a href="http://www.amazon.co.uk/exec/obidos/redirect?link_code=ur2&tag=#request.amazonTagID#&camp=1634&creative=6738&path=external-search%3Fsearch-type=ss%26index=blended%26keyword=#recenttracksDetail[z].artist.XmlText#" target="_blank">#recenttracksDetail[z].artist.XmlText#</a><img src="http://www.assoc-amazon.co.uk/e/ir?t=#request.amazonTagID#&l=ur2&o=2" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
</td>
</tr>
</cfloop>
</table>
<h2>Top Artists</h2>
<table title="My Top Artists" summary="Check out my most recent songs and artisits." class="musictable">
<tr>
<th>Rank</th>
<th>Artists</th>
<th>PlayCount</th>
</tr>
<cfloop index="z" from="1" to="#topArtistShowCount#">
<tr class="<cfif z mod 2>even<cfelse>odd</cfif>">
<td valign="top">
#topArtistNames[z].rank.XmlText#
</td>
<td valign="top">
<a href="http://www.amazon.co.uk/exec/obidos/redirect?link_code=ur2&tag=#request.amazonTagID#&camp=1634&creative=6738&path=external-search%3Fsearch-type=ss%26index=blended%26keyword=#topArtistNames[z].name.XmlText#" target="_blank">#topArtistNames[z].name.XmlText#</a><img src="http://www.assoc-amazon.co.uk/e/ir?t=#request.amazonTagID#&l=ur2&o=2" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
</td>
<td valign="top">
#topArtistNames[z].playcount.XmlText#
</td>
</tr>
</cfloop>
</table>
<h2>Top Albums</h2>
<table title="My Tops Albums" summary="Check out my most recent songs and artisits." class="musictable">
<tr>
<th>Rank</th>
<th>Album</th>
<th>Artist</th>
<th>PlayCount</th>
</tr>
<cfloop index="z" from="1" to="#topAlbumsShowCount#">
<tr class="<cfif z mod 2>even<cfelse>odd</cfif>">
<td valign="top">
#topalbumsNames[z].rank.XmlText#
</td>
<td valign="top" onmouseover="docTips.show('#rereplace(topalbumsNames[z].mbid.XmlText,"[^a-z]","","all")#')"
onmouseout="docTips.hide()" >
#topalbumsNames[z].name.XmlText#
</td>
<td valign="top">
<a href="http://www.amazon.co.uk/exec/obidos/redirect?link_code=ur2&tag=#request.amazonTagID#&camp=1634&creative=6738&path=external-search%3Fsearch-type=ss%26index=blended%26keyword=#topalbumsNames[z].artist.XmlText#" target="_blank">#topalbumsNames[z].artist.XmlText#</a><img src="http://www.assoc-amazon.co.uk/e/ir?t=#request.amazonTagID#&l=ur2&o=2" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
</td>
<td valign="top">
#topalbumsNames[z].playcount.XmlText#
</td>
</tr>
</cfloop>
</table>
<h2>Top Tracks</h2>
<table title="Top Tracks" summary="Check out my most recent songs and artisits." class="musictable">
<tr>
<th>Rank</th>
<th>Track</th>
<th>Artist</th>
<th>PlayCount</th>
</tr>
<cfloop index="z" from="1" to="#toptracksShowCount#">
<tr class="<cfif z mod 2>even<cfelse>odd</cfif>">
<td valign="top">
#toptracksNames[z].rank.XmlText#
</td>
<td valign="top">
#toptracksNames[z].name.XmlText#
</td>
<td valign="top">
<a href="http://www.amazon.co.uk/exec/obidos/redirect?link_code=ur2&tag=#request.amazonTagID#&camp=1634&creative=6738&path=external-search%3Fsearch-type=ss%26index=blended%26keyword=#toptracksNames[z].artist.XmlText#" target="_blank">#toptracksNames[z].artist.XmlText#</a><img src="http://www.assoc-amazon.co.uk/e/ir?t=#request.amazonTagID#&l=ur2&o=2" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
</td>
<td valign="top">
#toptracksNames[z].playcount.XmlText#
</td>
</tr>
</cfloop>
</table>
</cfsavecontent>
<!--- output the content --->
#application.recent#
</cfoutput>
</cfif>
<cfcatch>
<cfoutput>Service Unavailable</cfoutput>
</cfcatch>
</cftry>
</cfmodule>
<cfsetting enablecfoutputonly=false>
Thats massively to audioscrobbler for providing the xml files. Let me know what you think. You can view the result here http://www.succor.co.uk/lastfm.cfm.





An error occured while Parsing an XML document. The processing instruction target matching "[xX][mM][lL]" is not allowed.
The previous XML file content is ending up in the new return. I think this happens because my calls are going out to a url that doesn't specify a filename. An XML file is just returned based on uri vars sent. Any suggestions on how to handle this?
Actually, I'm trying to code a wrapper for a payment gateway in the UK which requires several back and forth https calls to provide card authorisation. I found that the issue was two pronged : First, the encoding that the gateway company was using wasn't ISO-Latin or ASCII so I had to use the charset attribute on the CFHTTP call. Second, the XML response they sent back contained spaces so I had to trim the response before sending the next call.
Lesson learned I guess. I hope this thread serves as a "what to watch for" for others trying the same. Your article was useful, thanks for the help!
Alex