Created
February 25, 2011 17:37
-
-
Save shoban/844161 to your computer and use it in GitHub Desktop.
Patch for scrobbling songs played on Pandora.
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
diff --git a/chromescrobbler.js b/chromescrobbler.js | |
index 13f59d1..ce18132 100644 | |
--- a/chromescrobbler.js | |
+++ b/chromescrobbler.js | |
@@ -5,6 +5,7 @@ var nowPlayingURL = "http://post.audioscrobbler.com:80/np_1.2"; | |
var submissionURL = "http://post2.audioscrobbler.com:80/protocol_1.2"; | |
function handshake() { | |
+ console.log('handshake(): '); | |
var username = localStorage.username; | |
var password = localStorage.password; | |
var currentTime = parseInt(new Date().getTime() / 1000.0); | |
@@ -12,6 +13,11 @@ function handshake() { | |
var http_request = new XMLHttpRequest(); | |
http_request.onreadystatechange = function() { | |
if (http_request.readyState == 4 && http_request.status == 200) { | |
+ response = http_request.responseText.split("\n")[0]; | |
+ console.log('handshake(): ' + http_request.responseText); | |
+ if (response != "OK") { | |
+ console.log('handshake(): failed. ' + response); | |
+ } | |
sessionID = http_request.responseText.split("\n")[1]; | |
nowPlayingURL = http_request.responseText.split("\n")[2]; | |
submissionURL = http_request.responseText.split("\n")[3]; | |
@@ -26,10 +32,18 @@ function handshake() { | |
} | |
function nowPlaying(sender) { | |
- var params = "s=" + sessionID + "&a=" + song.artist + "&t=" + song.track + "&b=&l=" + song.duration + "&m=&n="; | |
+ var params = "s=" + sessionID + "&a=" + song.artist + "&t=" + song.track + "&b="; | |
+ if (song.duration != 0) { | |
+ params += "&l=" + song.duration; | |
+ } else { | |
+ params += "&l="; | |
+ } | |
+ params += "&m=&n="; | |
+ console.log('nowPlaying(): params=' + params); | |
var http_request = new XMLHttpRequest(); | |
http_request.onreadystatechange = function() { | |
if (http_request.readyState == 4 && http_request.status == 200) | |
+ console.log('nowPlaying(): rsp=' + http_request.responseText); | |
if (http_request.responseText.split("\n")[0] == "BADSESSION") {handshake(); nowPlaying();} | |
else { | |
//Executes updateTitle function in youtube.js, only when there is a successfull session id. If user had wrong pass or uname, it will not update the title | |
@@ -45,10 +59,22 @@ function submit() { | |
nowPlayingTab = null; | |
var playTime = parseInt(new Date().getTime() / 1000.0) - song.startTime; | |
if (playTime > 30 && playTime > Math.min(240, song.duration / 2)) { | |
- var params = "s=" + sessionID + "&a[0]=" + song.artist + "&t[0]=" + song.track + "&i[0]=" + song.startTime + "&o[0]=P&r[0]=&l[0]=" + song.duration + "&b[0]=&m[0]=&n[0]="; | |
+ var params = "s=" + sessionID + "&a[0]=" + song.artist; | |
+ params += "&t[0]=" + song.track; | |
+ params += "&i[0]=" + song.startTime; | |
+ params += "&o[0]=" + song.source; | |
+ params += "&r[0]="; | |
+ if (song.duration != 0) { | |
+ params += "&l[0]=" + song.duration; | |
+ } else { | |
+ params += "&l[0]="; | |
+ } | |
+ params += "&b[0]=&m[0]=&n[0]="; | |
+ console.log('submit(): params=' + params); | |
var http_request = new XMLHttpRequest(); | |
http_request.onreadystatechange = function() { | |
if (http_request.readyState == 4 && http_request.status == 200) | |
+ console.log('submit(): rsp=' + http_request.responseText); | |
if (http_request.responseText.split("\n")[0] == "BADSESSION") {handshake(); submit();} | |
}; | |
http_request.open("POST", submissionURL, true); | |
@@ -57,8 +83,7 @@ function submit() { | |
} | |
} | |
-chrome.extension.onRequest.addListener( | |
- function(request, sender, sendResponse) { | |
+chrome.extension.onRequest.addListener( | |
function(request, sender, sendResponse) { | |
switch(request.type) { | |
case "nowPlaying": | |
if (nowPlayingTab != null) submit(); | |
@@ -66,6 +91,7 @@ chrome.extension.onRequest.addListener( | |
song = { "artist" : request.artist, | |
"track" : request.track, | |
"duration" : request.duration, | |
+ "source" : request.source, | |
"startTime" : parseInt(new Date().getTime() / 1000.0)}; | |
if (sessionID == "") handshake(); | |
nowPlaying(sender); | |
diff --git a/manifest.json b/manifest.json | |
index 0c2dc53..fdbb7fa 100644 | |
--- a/manifest.json | |
+++ b/manifest.json | |
@@ -17,6 +17,11 @@ | |
"matches": ["http://www.youtube.com/watch?v=*"], | |
"js": ["youtube.js"], | |
"css": ["youtube.css"] | |
- } | |
+ }, | |
+ { | |
+ "matches": ["http://www.pandora.com/*"], | |
+ "js": ["pandora.js"], | |
+ "run_at": "document_end" | |
+ } | |
] | |
} | |
diff --git a/pandora-lfm-inject.js b/pandora-lfm-inject.js | |
new file mode 100644 | |
index 0000000..e041cc9 | |
--- /dev/null | |
+++ b/pandora-lfm-inject.js | |
@@ -0,0 +1,81 @@ | |
+// alert('pandora-lfm-inject.js load'); | |
+ | |
+var pandoraInjApiTries = 0; | |
+ | |
+function pandoraInjApiLoaded() | |
+{ | |
+ // alert('pandoraInjApiLoaded()'); | |
+ if (pandoraInjApiTries < 30) { | |
+ if (typeof(Pandora) == "undefined") { | |
+ pandoraInjApiTries++; | |
+ window.setTimeout("pandoraInjApiLoaded()", 5000); | |
+ } else { | |
+ pandoraInjInitialize(); | |
+ } | |
+ } else { | |
+ // error unable to register event handlers. | |
+ } | |
+} | |
+ | |
+window.setTimeout("pandoraInjApiLoaded()", 5000); | |
+ | |
+function pandoraInjInitialize() | |
+{ | |
+ if (typeof(Pandora) == "undefined") { | |
+ // error unable to register event handlers. | |
+ return; | |
+ } | |
+ // alert('pandoraInjInitialize()'); | |
+ | |
+ Pandora.setEventHandler("SongPlayed", function(data) { | |
+ pandoraInjSongPlayEvent(data.songName, data.artistName); | |
+ }); | |
+ Pandora.setEventHandler("SongPaused", function(data) { | |
+ pandoraInjSongPauseEvent(data.songName, data.artistName); | |
+ }); | |
+ Pandora.setEventHandler("SongEnded", function(data) { | |
+ pandoraInjSongEndEvent(data.songName, data.artistName); | |
+ }); | |
+} | |
+ | |
+function pandoraInjSendEvent(e, song, artist) | |
+{ | |
+ var comDiv = document.getElementById('pandoraInjEventsDiv'); | |
+ if (!comDiv) { | |
+ // error unable to send event. | |
+ alert('ERROR: pandoraInjEventsDiv not found.'); | |
+ return; | |
+ } | |
+ | |
+ comDiv.setAttribute('song', song); | |
+ comDiv.setAttribute('artist', artist); | |
+ comDiv.dispatchEvent(e); | |
+} | |
+ | |
+var pandoraInjPlayEventObj = document.createEvent('Event'); | |
+var pandoraInjPauseEventObj = document.createEvent('Event'); | |
+var pandoraInjEndEventObj = document.createEvent('Event'); | |
+pandoraInjPlayEventObj.initEvent('pandoraInjPlayEvent', true, true); | |
+pandoraInjPauseEventObj.initEvent('pandoraInjPauseEvent', true, true); | |
+pandoraInjEndEventObj.initEvent('pandoraInjEndEvent', true, true); | |
+ | |
+function pandoraInjSongPlayEvent(song, artist) | |
+{ | |
+ // alert('PLAY: ' + artist + ' - ' + song); | |
+ pandoraInjSendEvent(pandoraInjPlayEventObj, | |
+ song, artist); | |
+} | |
+ | |
+function pandoraInjSongPauseEvent(song, artist) | |
+{ | |
+ // alert('PAUSE: ' + artist + ' - ' + song); | |
+ pandoraInjSendEvent(pandoraInjPauseEventObj, | |
+ song, artist); | |
+} | |
+ | |
+function pandoraInjSongEndEvent(song, artist) | |
+{ | |
+ // alert('END: ' + artist + ' - ' + song); | |
+ pandoraInjSendEvent(pandoraInjEndEventObj, | |
+ song, artist); | |
+} | |
diff --git a/pandora.js b/pandora.js | |
new file mode 100644 | |
index 0000000..14da03a | |
--- /dev/null | |
+++ b/pandora.js | |
@@ -0,0 +1,174 @@ | |
+function Log(type, str) | |
+{ | |
+ console.log(type.toUpperCase() + ': ' + str); | |
+} | |
+function LogD(str) { Log('debug', str); } | |
+function LogE(str) { Log('error', str); } | |
+ | |
+var g_song = ""; | |
+var g_artist = ""; | |
+var g_playedDuration = 0; | |
+var g_startTime = 0; | |
+var g_songPaused = false; | |
+ | |
+function getTime() | |
+{ | |
+ var d = new Date(); | |
+ return d.getTime(); | |
+} | |
+ | |
+function pandoraClearSong() | |
+{ | |
+ g_song = ""; | |
+ g_artist = ""; | |
+ g_playedDuration = 0; | |
+ g_startTime = 0; | |
+ g_songPaused = false; | |
+} | |
+ | |
+function pandoraSongPauseEvent() | |
+{ | |
+ LogD('PauseEvent: '); | |
+ var ev_div = document.getElementById('pandoraInjEventsDiv'); | |
+ if (!ev_div) { | |
+ return; | |
+ } | |
+ | |
+ song = ev_div.getAttribute('song'); | |
+ artist = ev_div.getAttribute('artist'); | |
+ | |
+ LogD('PauseEvent: ' + artist + ' - ' + song); | |
+ if (song == g_song && artist == g_artist) { | |
+ g_songPaused = true; | |
+ g_playedDuration += getTime() - g_startTime; | |
+ g_startTime = 0; | |
+ } | |
+} | |
+ | |
+function pandoraSongPlayEvent() | |
+{ | |
+ LogD('PlayEvent: '); | |
+ | |
+ var ev_div = document.getElementById('pandoraInjEventsDiv'); | |
+ if (!ev_div) { | |
+ return; | |
+ } | |
+ | |
+ song = ev_div.getAttribute('song'); | |
+ artist = ev_div.getAttribute('artist'); | |
+ | |
+ LogD('PlayEvent: ' + artist + ' - ' + song); | |
+ if (g_song == "" && g_artist == "") { | |
+ // New song start. | |
+ g_song = song; | |
+ g_artist = artist; | |
+ g_playedDuration = 0; | |
+ g_startTime = getTime(); | |
+ g_songPaused = false; | |
+ pandoraSendNowPlaying(); | |
+ } else { | |
+ // Continuation of same song. | |
+ g_startTime = getTime(); | |
+ } | |
+} | |
+ | |
+function pandoraSongEndEvent() | |
+{ | |
+ LogD('EndEvent: '); | |
+ var ev_div = document.getElementById('pandoraInjEventsDiv'); | |
+ if (!ev_div) { | |
+ return; | |
+ } | |
+ | |
+ song = ev_div.getAttribute('song'); | |
+ artist = ev_div.getAttribute('artist'); | |
+ | |
+ LogD('EndEvent: ' + artist + ' - ' + song); | |
+ | |
+ if (song == g_song && artist == g_artist) { | |
+ g_playedDuration += getTime() - g_startTime; | |
+ | |
+ // Only submit songs which have played more than 2mins. | |
+ LogD('EndEvent: g_playedDuration=' + g_playedDuration); | |
+ if (g_playedDuration > 120000) { | |
+ pandoraSendPlayed(); | |
+ } | |
+ } | |
+ | |
+ pandoraClearSong(); | |
+} | |
+ | |
+function pandoraInitialize() | |
+{ | |
+ LogD('pandoraInitialize(): '); | |
+ if (!document.getElementById("tunerEventListenerDiv")) { | |
+ var api = document.createElement('script'); | |
+ api.setAttribute('language', 'javascript'); | |
+ api.setAttribute('type', 'text/javascript'); | |
+ api.setAttribute('src', 'http://www.pandora.com/include/PandoraAPIv2.js'); | |
+ api.setAttribute('id', 'evntjs'); | |
+ document.getElementsByTagName('head')[0].appendChild(api); | |
+ LogD('Injecting PandoraAPIv2.js'); | |
+ } | |
+ | |
+ var ev_div = document.createElement('div'); | |
+ ev_div.setAttribute('style', 'display:none'); | |
+ ev_div.setAttribute('id', 'pandoraInjEventsDiv'); | |
+ document.getElementsByTagName('body')[0].appendChild(ev_div); | |
+ LogD('pandoraInjEventsDiv: created.'); | |
+ | |
+ ev_div.addEventListener('pandoraInjPlayEvent', function() { | |
+ pandoraSongPlayEvent(); | |
+ }); | |
+ ev_div.addEventListener('pandoraInjPauseEvent', function() { | |
+ pandoraSongPauseEvent(); | |
+ }); | |
+ ev_div.addEventListener('pandoraInjEndEvent', function() { | |
+ pandoraSongEndEvent(); | |
+ }); | |
+ LogD('pandoraInjEventsDiv: events registered.'); | |
+ | |
+ var lfm_inj = document.createElement('script'); | |
+ lfm_inj.setAttribute('language', 'javascript'); | |
+ lfm_inj.setAttribute('type', 'text/javascript'); | |
+ lfm_inj.setAttribute('src', | |
+ chrome.extension.getURL('pandora-lfm-inject.js')); | |
+ lfm_inj.setAttribute('id', 'lfminjjs'); | |
+ document.getElementsByTagName('head')[0].appendChild(lfm_inj); | |
+ LogD('Injecting pandora-lfm-inject.js'); | |
+ | |
+ pandoraClearSong(); | |
+} | |
+ | |
+ | |
+function pandoraSendNowPlaying() | |
+{ | |
+ var validationURL = "http://ws.audioscrobbler.com/2.0/?" + | |
+ "method=track.getinfo" + | |
+ "&api_key=44c7aeb27b91eb0e4e913098a9dc2378" + | |
+ "&artist="+ g_artist + "&track=" + g_song; | |
+ LogD('pandoraSendNowPlaying(): '); | |
+ LogD('pandoraSendNowPlaying(): validationURL=' + validationURL); | |
+ | |
+ chrome.extension.sendRequest({type: "xhr", url: validationURL}, | |
+ function(response) { | |
+ if (response.text != "You must supply either an artist and track name OR a musicbrainz id.") { | |
+ LogD('pandoraSendNowPlaying(): send nowPlaying.'); | |
+ chrome.extension.sendRequest({type: "nowPlaying", | |
+ artist: g_artist, track: g_song, duration: 0, | |
+ source: "R"}); | |
+ }; | |
+ }); | |
+ LogD('pandoraSendNowPlaying(): auth.'); | |
+} | |
+ | |
+function pandoraSendPlayed() | |
+{ | |
+ LogD('pandoraSendPlayed(): '); | |
+ chrome.extension.sendRequest({type: "submit"}, | |
+ function(r) { | |
+ LogD('pandoraSendPlayed(): submitted.'); | |
+ }); | |
+} | |
+ | |
+pandoraInitialize(); | |
diff --git a/youtube.js b/youtube.js | |
index 89cc246..70fc339 100644 | |
--- a/youtube.js | |
+++ b/youtube.js | |
@@ -10,7 +10,8 @@ chrome.extension.sendRequest({type: "xhr", url: googleURL}, function(response) { | |
var validationURL = "http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key=44c7aeb27b91eb0e4e913098a9dc2378&artist="+ artist + "&track=" + track; | |
chrome.extension.sendRequest({type: "xhr", url: validationURL}, function(response) { | |
if (response.text != "You must supply either an artist and track name OR a musicbrainz id.") { | |
- chrome.extension.sendRequest({type: "nowPlaying", artist: artist, track: track, duration: duration}); | |
+ chrome.extension.sendRequest({type: "nowPlaying", artist: artist, track: track, | |
+ duration: duration, source: "P"}); | |
}; | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment