Skip to content

Instantly share code, notes, and snippets.

@burningtree
Created March 15, 2012 14:31
Show Gist options
  • Select an option

  • Save burningtree/2044485 to your computer and use it in GitHub Desktop.

Select an option

Save burningtree/2044485 to your computer and use it in GitHub Desktop.
Last.fm Linker (What.cd + Spotify) - greasemonkey script
// ==UserScript==
// @name Last.fm Linker (What.cd + Spotify)
// @namespace ?
// @description Inserts What.cd and Spotify links on Last.fm
// @include http://last.fm/*
// @include http://*.last.fm/*
// @include http://lastfm.*/*
// @include http://*.lastfm.*/*
// ==/UserScript==
// Last.fm seems to urlencode strings twice so remove the second urlencode step.
function cleanurl(str) {
return str.replace(/%25([0-9]{2})/, '%$1');
}
// Remove whitespace in the beginning and end
function trim(str) {
return str.replace(/^\s+/, '').replace(/\s+$/, '');
}
function createSpotifyLink(link) {
var a = document.createElement('a');
a.href = link;
a.title = 'Listen in Spotify'
a.setAttribute('extLink', true);
var img = document.createElement('img');
img.style.border = 'none';
img.style.marginLeft = '3px';
img.src = 'data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGlJREFUeNpi%2BP%2F%2FPwMMuy1j%2BA%2FEBchiIMzEgAn63ZczzkcWwKaoEYgdgAr7cSraGfm%2FAUgZAnECPpNACj8AqQd4FQGtKgBSB2B8FqigArLxQPABaNoEFEVAcB6IBZCsW4DPdwewWQ8QYACnBy8V7gSvaAAAAABJRU5ErkJggg%3D%3D';
a.appendChild(img);
return a;
}
function createWhatcdLink(link) {
var a = document.createElement('a');
a.href = link;
a.title = 'Search on What.cd'
a.setAttribute('extLink', true);
a.target = "_blank";
var img = document.createElement('img');
img.style.border = 'none';
img.style.marginLeft = '3px';
// generated with http=>//www.greywyvern.com/code/php/binary2base64
img.src = 'data:image/png;base64,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%3D';
a.appendChild(img);
return a;
}
// Add links for the content under this element.
function addLinks(topElem) {
// Check if we already added links for this content
if (topElem.hasAttribute('extraLinksAdded'))
return;
topElem.setAttribute('extraLinksAdded', true);
// This is a last.fm url that we want to rewrite
var re = /^http:\/\/(.*\.|)(last\.fm|lastfm\.[^\/]+)\/music\/([^\?#]*)$/i;
var elems = topElem.getElementsByTagName('a');
for (var i = 0; i < elems.length; i++) {
var elem = elems[i];
// Ignore image links
if (!elem.href || trim(elem.textContent) == '' || elem.className.match(/\blfmButton\b/))
continue;
// Check if the link matches
if (m = re.exec(elem.href)) {
var found = false;
// Go though parts and check if it is an url that we want to change
parts = m[3].split('/');
for (var j = 0; j < parts.length; j++) {
if (parts[j][0] == '+') {
found = true;
break;
}
}
if (found)
continue;
// Ignore links in the left menu and some other places
var p = elem;
while (p != null) {
if (p.id && p.id.match(/^(secondaryNavigation|featuredArtists)$/) || p.className && p.className.match(/\b(pagehead|image|artistsMegaWithFeatured)\b/)) {
found = true;
break;
}
p = p.parentNode;
}
if (found)
continue;
var ext = document.createElement('span');
// Create the spotify url
q = ['artist%3a%22'+ cleanurl(parts[0]) +'%22'];
if (parts[1] && parts[1] != '_')
q.push('album%3a%22'+ cleanurl(parts[1]) +'%22');
if (parts[2])
q.push('track%3a%22'+ cleanurl(parts[2]) +'%22');
var b = createSpotifyLink('spotify:search:'+ q.join('%20'));
ext.appendChild(b);
// Create the whatcd url
var q = [cleanurl(parts[0])];
if (parts[1] && parts[1] != '_')
q.push(cleanurl(parts[1]));
//a = createLink('http://what.cd/artist.php?artistname='+ q.join('%20'));
//q.push('album%3a%22'+ cleanurl(parts[1]) +'%22');
if (!parts[2])
{
if(q.length == 1)
var baseUrl = 'http://what.cd/artist.php?artistname=';
else
var baseUrl = 'http://what.cd/torrents.php?searchstr=';
var a = createWhatcdLink(baseUrl + q.join('%20'));
ext.appendChild(a);
}
// Insert the link after the found link
// Check if it already have a spotify url
if (!elem.nextSibling || !elem.nextSibling.hasAttribute || !elem.nextSibling.hasAttribute('extLink')) {
elem.parentNode.insertBefore(ext, elem.nextSibling);
}
}
}
}
// Add listener so if the content changes we add links to the new content
document.addEventListener('DOMSubtreeModified', function(ev){ addLinks(ev.originalTarget); }, true);
// Add links to titles like the artist name on the artist page.
var body = document.body;
var div = document.getElementById('catalogueHead');
if (body.className && div) {
if (body.className.match(/\br\-artist\b/)) {
// artist page
var h1 = div.getElementsByTagName('h1')[0];
var ext = document.createElement('span');
ext.appendChild(createSpotifyLink('spotify:search:artist%3a%22'+ encodeURIComponent(h1.textContent) +'%22'));
ext.appendChild(createWhatcdLink('http://what.cd/artist.php?artistname='+ encodeURIComponent(h1.textContent)));
h1.appendChild(ext);
} else if (body.className.match(/\br\-album\b/)) {
// album page
var h1 = div.getElementsByTagName('h1')[0];
var ext = document.createElement('span');
ext.appendChild(createSpotifyLink('spotify:search:artist%3a%22'+ encodeURIComponent(h1.firstChild.textContent) +'%22%20album%3a%22'+ encodeURIComponent(h1.lastChild.textContent) +'%22'));
ext.appendChild(createWhatcdLink('http://what.cd/artist.php?artistname='+ encodeURIComponent(h1.firstChild.textContent) +'%3a%22'+ encodeURIComponent(h1.lastChild.textContent) +'%22'));
h1.appendChild(ext);
div.previousSibling.previousSibling.getElementsByTagName('h1')[0].appendChild(ext.cloneNode(true))
} else if (body.className.match(/\br\-track\b/)) {
// track page
var h1 = div.getElementsByTagName('h1')[0];
var a = createLink('spotify:search:artist%3a%22'+ encodeURIComponent(h1.firstChild.textContent) +'%22%20track%3a%22'+ encodeURIComponent(h1.lastChild.textContent.substring(3)) +'%22');
h1.appendChild(a);
div.previousSibling.previousSibling.getElementsByTagName('h1')[0].appendChild(a.cloneNode(true))
}
}
// Find links and add spotify links to them
addLinks(body);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment