diff --git a/Deezify.crx b/Deezify.crx new file mode 100644 index 0000000..eec7a5b Binary files /dev/null and b/Deezify.crx differ diff --git a/README.md b/README.md index c6a7b33..d068a4c 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,6 @@ Deezify Due to some priorities, and a lack of time, Deezify is now open source! Thanks all for your support! -Chrome extension: https://chrome.google.com/webstore/detail/deezify/kpkbhaapafmlmgodhicgpngihalhepll +Match and download any track from your favorite streaming music service, without limit or ads! -ZeNy. +ps: Use google chrome canary to import extension \ No newline at end of file diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 7316993..70213c6 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -16,6 +16,19 @@ "message": "The submited captcha was erroned" }, + "spotifyDownloadMessage": { + "message": "Download" + }, + "spotifyDownloadMatching": { + "message": "Matching..." + }, + "spotifyDownloadError": { + "message": "Unavailable" + }, + "spotifyCaptchaError": { + "message": "Error" + }, + "xboxMusicDownloadMessage": { "message": "Download the current track" }, @@ -35,4 +48,4 @@ "globalCaptchaSubmit": { "message": "Submit" } -} \ No newline at end of file +} diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 99fb1a8..ac9a81c 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -15,6 +15,19 @@ "deezerCaptchaError": { "message": "Le captcha renvoyé est erroné" }, + + "spotifyDownloadMessage": { + "message": "Télécharger" + }, + "spotifyDownloadMatching": { + "message": "Recherche..." + }, + "spotifyDownloadError": { + "message": "indisponible" + }, + "spotifyCaptchaError": { + "message": "Erreur" + }, "xboxMusicDownloadMessage": { "message": "Télécharger cette piste audio" @@ -35,4 +48,4 @@ "globalCaptchaSubmit": { "message": "Envoyer" } -} \ No newline at end of file +} diff --git a/manifest.json b/manifest.json index 8ed21c3..23eaba7 100644 --- a/manifest.json +++ b/manifest.json @@ -26,10 +26,9 @@ "media/css/deezify.css" ], "js": [ - "media/js/include.js" + "src/include.js" ], - "all_frames" : false, - "run_at": "document_idle" + "all_frames" : false } ] -} \ No newline at end of file +} diff --git a/media/css/deezify.css b/media/css/deezify.css index 9346e65..5a682a3 100644 --- a/media/css/deezify.css +++ b/media/css/deezify.css @@ -69,3 +69,7 @@ display: none; opacity: 0; } + + a.deezify-link { + color: #fff; + } \ No newline at end of file diff --git a/media/js/include.js b/media/js/include.js index 91fc6e6..c17b45c 100644 --- a/media/js/include.js +++ b/media/js/include.js @@ -1,5 +1,5 @@ /* - * Deezify - 1.0 + * Deezify - 1.0.1 * @author: Alexis (@_SuckMyLuck) Bize * @about: Match and download any track from your favorite streaming music service, without limit or ads */ @@ -50,8 +50,6 @@ deezifyLinkContainer = null, deezifyTextContainer = null; - var hostInjectionPlayerContainer = null; - var captchaBackground = document.createElement('div'); captchaBackground.className = 'deezify-captcha-background'; document.body.appendChild(captchaBackground); @@ -69,108 +67,16 @@ captchaAction.className = 'deezify-captcha-action'; captchaContainer.appendChild(captchaAction); - switch (currentHost) - { - case hostsList.rdio: - break; - case hostsList.deezer: - - hostLocales.downloadMp3 = chrome.i18n.getMessage('deezerDownloadMessage'); - hostLocales.undefinedMp3 = chrome.i18n.getMessage('deezerDownloadError'); - hostLocales.matchingMp3 = chrome.i18n.getMessage('deezerDownloadMatching'); - hostLocales.captchaError = chrome.i18n.getMessage('deezerCaptchaError'); - - hostPlayer = document.getElementsByClassName('player')[0]; - if (typeof hostPlayer === 'undefined') - break; - - var hostPlayerTrackInfoContainer = hostPlayer.getElementsByClassName('track-info')[0]; - hostPlayerTrackInfoContainer.addEventListener('DOMSubtreeModified', dzrPlayerReady); - - function dzrPlayerReady(e) - { - if (e.srcElement.id === 'player_track_title') - { - hostPlayerTrackInfoContainer.removeEventListener('DOMSubtreeModified', dzrPlayerReady); - hostSongData.title_container = document.getElementById('player_track_title'); - hostSongData.performer_container = document.getElementById('player_track_artist_container'); - - hostInjectionPlayerContainer = document.getElementsByClassName('topbar')[0].getElementsByClassName('nav')[0]; - deezifyPrimaryContainer = document.createElement('li'); - deezifyPrimaryContainer.className = 'deezify-container'; - hostInjectionPlayerContainer.appendChild(deezifyPrimaryContainer); - - deezifyLinkContainer = document.createElement('a'); - deezifyLinkContainer.className = 'deezify-link'; - deezifyLinkContainer.setAttribute('data-deezify-ref', 'player'); - deezifyPrimaryContainer.appendChild(deezifyLinkContainer); - - deezifyTextContainer = document.createElement('span'); - deezifyTextContainer.className = 'deezify-text'; - deezifyTextContainer.innerText = hostLocales.downloadMp3; - deezifyLinkContainer.appendChild(deezifyTextContainer); - - deezify.fade('in', deezifyPrimaryContainer, function() { - deezifyLinkContainer.onclick = deezify.initDownload; - deezifyTextContainer.onclick = deezifyLinkContainer.click; - }); - } - } - break; - case hostsList.spotify: - break; - case hostsList.xboxmusic: - - hostLocales.downloadMp3 = chrome.i18n.getMessage('xboxMusicDownloadMessage'); - hostLocales.undefinedMp3 = chrome.i18n.getMessage('xboxMusicDownloadError'); - hostLocales.matchingMp3 = chrome.i18n.getMessage('xboxMusicDownloadMatching'); - hostLocales.captchaError = chrome.i18n.getMessage('xboxMusicCaptchaError'); - - hostPlayer = document.getElementById('player'); - if (typeof hostPlayer === 'undefined') - break; - - hostPlayer.addEventListener('DOMSubtreeModified', xboxMusicPlayerReady); - - function xboxMusicPlayerReady(e) - { - if (e.srcElement.className === 'playerNowPlaying' - && typeof hostPlayer.getElementsByClassName('primaryMetadata')[1] !== 'undefined') - { - hostPlayer.removeEventListener('DOMSubtreeModified', xboxMusicPlayerReady); - - hostInjectionPlayerContainer = document.getElementById('navigation').getElementsByTagName('ul')[0]; - deezifyPrimaryContainer = document.createElement('li'); - deezifyPrimaryContainer.className = 'deezify-container'; - hostInjectionPlayerContainer.appendChild(deezifyPrimaryContainer); - - deezifyLinkContainer = document.createElement('a'); - deezifyLinkContainer.className = 'deezify-link'; - deezifyLinkContainer.setAttribute('data-deezify-ref', 'player'); - deezifyPrimaryContainer.appendChild(deezifyLinkContainer); - - deezifyIconContainer = document.createElement('span'); - deezifyIconContainer.className = 'iconRowSecondaryAdd'; - deezifyLinkContainer.appendChild(deezifyIconContainer); - - deezifyTextContainer = document.createElement('span'); - deezifyTextContainer.className = 'deezify-text'; - deezifyTextContainer.innerText = hostLocales.downloadMp3; - deezifyLinkContainer.appendChild(deezifyTextContainer); - - deezify.fade('in', deezifyPrimaryContainer, function() { - deezifyLinkContainer.onclick = deezify.initDownload; - deezifyTextContainer.onclick = deezifyLinkContainer.click; - }); - } - } - break; - case hostsList.beatsmusic: - break; - } - var deezify = { + setLocales: function(host) + { + hostLocales.downloadMp3 = chrome.i18n.getMessage(host + 'DownloadMessage'); + hostLocales.undefinedMp3 = chrome.i18n.getMessage(host + 'DownloadError'); + hostLocales.matchingMp3 = chrome.i18n.getMessage(host + 'DownloadMatching'); + hostLocales.captchaError = chrome.i18n.getMessage(host + 'CaptchaError'); + }, + initDownload: function(e) { if (!downloadEnabled) @@ -183,38 +89,33 @@ deezifyTextContainer.innerText = hostLocales.matchingMp3; - switch(currentHost) + if (downloadRef === 'player') { - case hostsList.deezer: - if (downloadRef === 'player') - { - hostSongData.title = hostSongData.title_container.innerText; - hostSongData.performer = hostSongData.performer_container.innerText; - hostSongData.track_version = deezify.getDzrTrackVersion(); - return deezify.matchData(hostSongData); - } - break; - case hostsList.xboxmusic: - if (downloadRef === 'player') - { - hostSongData.title_container = hostPlayer.getElementsByClassName('primaryMetadata')[1]; - hostSongData.performer_container = hostPlayer.getElementsByClassName('secondaryMetadata')[1]; + if (currentHost === hostsList.deezer) + { + hostSongData.title_container = document.getElementById('player_track_title'); + hostSongData.performer_container = document.getElementById('player_track_artist_container'); + hostSongData.title = hostSongData.title_container.innerText; + hostSongData.performer = hostSongData.performer_container.innerText; + hostSongData.track_version = deezify.getDzrTrackVersion(); + } - hostSongData.title = hostSongData.title_container.innerText.trim(); - hostSongData.performer = hostSongData.performer_container.getElementsByTagName('a')[0].innerText.trim(); - return deezify.matchData(hostSongData); - } - break; - default: - downloadEnabled = true; - return false; - } + else if (currentHost === hostsList.xboxmusic) + { + hostSongData.title_container = hostPlayer.getElementsByClassName('primaryMetadata')[1]; + hostSongData.performer_container = hostPlayer.getElementsByClassName('secondaryMetadata')[1]; + hostSongData.title = hostSongData.title_container.innerText.trim(); + hostSongData.performer = hostSongData.performer_container.getElementsByTagName('a')[0].innerText.trim(); + } + + return deezify.matchData(hostSongData); + } }, matchData: function(songData, captchaData) { captchaData = captchaData || null; - var vkQueryData = { + var apiQueryData = { 'title': songData.performer + ' - ' + songData.title, 'auto_complete': 1, 'access_token': vkParams.app.token, @@ -222,16 +123,28 @@ }; if (songData.track_version) - vkQueryData.track = vkQueryData.track + ' ' + songData.track_version; + apiQueryData.title = apiQueryData.title + ' ' + songData.track_version; if (captchaData !== null) { - vkQueryData.captcha_sid = captchaData.sid; - vkQueryData.captcha_key = captchaData.key; + apiQueryData.captcha_sid = captchaData.sid; + apiQueryData.captcha_key = captchaData.key; } + var trackTitlePatch = { + ' (Album Version Explicit)': '', + ' (Explicit Version)': '', + ' (Skit Explicit)': '', + ' (Album Version Edited)': '', + ' (Motion Picture Soundtrack)': '', + ' (From The Nissan Qashqai Movie)': '' + }; + + for (var patch in trackTitlePatch) + apiQueryData.title = apiQueryData.title.replace(patch, trackTitlePatch[patch]); + xmlhttp = new XMLHttpRequest(); - xmlhttp.open('GET', vkParams.api.url + '/method/execute.' + vkParams.api.method + deezify.encodeQueryData(vkQueryData), true); + xmlhttp.open('GET', vkParams.api.url + '/method/execute.' + vkParams.api.method + deezify.encodeQueryData(apiQueryData), true); xmlhttp.send(); xmlhttp.onreadystatechange = function() { @@ -241,7 +154,7 @@ if (typeof apiResponse.error === 'undefined' && apiResponse.response.count) { var url = document.createElement('a'); - url.download = vkQueryData.title + ' - Deezify.mp3'; + url.download = apiQueryData.title + ' - Deezify.mp3'; url.href = apiResponse.response.items[0].url; url.dataset.downloadurl = ['audio/mpeg', url.download, url.href].join(':'); url.click(); @@ -249,28 +162,25 @@ deezifyTextContainer.innerText = hostLocales.downloadMp3; downloadEnabled = true; } + else if (typeof apiResponse.error === 'undefined' && !apiResponse.response.count) return deezify.setApiError(1); + else if (typeof apiResponse.error !== 'undefined' && captchaRequested) return deezify.setApiError(2); - else + + else if (apiResponse.error.error_code === 14) { - var apiError = apiResponse.error.error_code; - switch (apiError) - { - case 14: - return deezify.setCaptcha({ - 'songData': songData, - 'captchaData': { - 'sid': apiResponse.error.captcha_sid, - 'img': apiResponse.error.captcha_img - } - }); - break; - default: - return deezify.setApiError(1); - } + return deezify.setCaptcha({ + 'songData': songData, + 'captchaData': { + 'sid': apiResponse.error.captcha_sid, + 'img': apiResponse.error.captcha_img + } + }); } + + else return deezify.setApiError(1); } }; return false; @@ -319,9 +229,11 @@ { setTimeout(function() { - deezify.fade('out', deezifyTextContainer, 100, function() { + deezify.fade('out', deezifyTextContainer, 100, function() + { deezifyTextContainer.innerText = hostLocales.downloadMp3; - deezify.fade('in', deezifyTextContainer, 100, function() { + deezify.fade('in', deezifyTextContainer, 100, function() + { downloadEnabled = true; captchaRequested = false; }); @@ -343,11 +255,10 @@ { var xPlayerData = document.createElement('script'); xPlayerData.type = 'text/javascript'; - xPlayerData.text = 'localStorage.setItem("' + localStorageKey + 'trackVersion", (dzPlayer.getCurrentSongInfo().VERSION || ""));'; + xPlayerData.text = 'localStorage.setItem("' + localStorageKey + 'trackVersion", dzPlayer.getCurrentSongInfo().VERSION || "");'; document.body.appendChild(xPlayerData); - var trackVersion = localStorage.getItem(localStorageKey + 'trackVersion'); document.body.removeChild(xPlayerData); - return trackVersion; + return localStorage.getItem(localStorageKey + 'trackVersion');; }, fade: function(type, element, speed, callback) @@ -358,41 +269,142 @@ else speed = parseInt(speed); speed = speed / 10; - switch (type) + if (type === 'in') { - case 'in': - element.style.display = 'block'; - element.style.opacity = 0; - var interval = setInterval(function() + element.style.display = 'block'; + element.style.opacity = 0; + var interval = setInterval(function() + { + var elementOpacity = element.style.opacity; + if (elementOpacity >= 1) { - var elementOpacity = element.style.opacity; - if (elementOpacity >= 1) - { - clearInterval(interval); - element.style.opacity = 1; - if (callback !== null) - return callback(); - } - element.style.opacity = parseFloat(elementOpacity) + 0.05; - }, speed); - break; - case 'out': - element.style.opacity = 1; - var interval = setInterval(function() + clearInterval(interval); + element.style.opacity = 1; + if (callback !== null) + return callback(); + } + element.style.opacity = parseFloat(elementOpacity) + 0.05; + }, speed); + } + + else if (type === 'out') + { + element.style.opacity = 1; + var interval = setInterval(function() + { + var elementOpacity = element.style.opacity; + if (elementOpacity <= 0.1) { - var elementOpacity = element.style.opacity; - if (elementOpacity <= 0.1) - { - element.style.display = 'none'; - clearInterval(interval); - element.style.opacity = 0; - if (callback !== null) - return callback(); - } - element.style.opacity = parseFloat(elementOpacity) - 0.05; - }, speed); - break; + element.style.display = 'none'; + clearInterval(interval); + element.style.opacity = 0; + if (callback !== null) + return callback(); + } + element.style.opacity = parseFloat(elementOpacity) - 0.05; + }, speed); } + } }; + + if (currentHost === hostsList.rdio) + { + // TODO, maybe + } + + else if (currentHost === hostsList.deezer) + { + deezify.setLocales('deezer'); + hostPlayer = document.getElementsByClassName('player')[0]; + if (typeof hostPlayer === 'undefined') + return; + + var deezerTrackInfoContainer = hostPlayer.getElementsByClassName('track-info')[0]; + deezerTrackInfoContainer.addEventListener('DOMSubtreeModified', deezerPlayerReady); + + function deezerPlayerReady(e) + { + if (e.srcElement.id === 'player_track_title') + { + deezerTrackInfoContainer.removeEventListener('DOMSubtreeModified', deezerPlayerReady); + + hostInjectionPlayerContainer = document.getElementsByClassName('topbar')[0].getElementsByClassName('nav')[0]; + deezifyPrimaryContainer = document.createElement('li'); + deezifyPrimaryContainer.className = 'deezify-container'; + hostInjectionPlayerContainer.appendChild(deezifyPrimaryContainer); + + deezifyLinkContainer = document.createElement('a'); + deezifyLinkContainer.className = 'deezify-link'; + deezifyLinkContainer.setAttribute('data-deezify-ref', 'player'); + deezifyPrimaryContainer.appendChild(deezifyLinkContainer); + + deezifyTextContainer = document.createElement('span'); + deezifyTextContainer.className = 'deezify-text'; + deezifyTextContainer.innerText = hostLocales.downloadMp3; + deezifyLinkContainer.appendChild(deezifyTextContainer); + + deezify.fade('in', deezifyPrimaryContainer, function() { + deezifyLinkContainer.onclick = deezify.initDownload; + deezifyTextContainer.onclick = deezifyLinkContainer.click; + }); + } + } + + + } + + else if (currentHost === hostsList.spotify) + { + // TODO, once again + } + + else if (currentHost === hostsList.xboxmusic) + { + deezify.setLocales('xboxMusic'); + hostPlayer = document.getElementsByClassName('player')[0]; + if (typeof hostPlayer === 'undefined') + return; + + hostPlayer.addEventListener('DOMSubtreeModified', xboxMusicPlayerReady); + + function xboxMusicPlayerReady(e) + { + if (e.srcElement.className === 'playerNowPlaying' + && typeof hostPlayer.getElementsByClassName('primaryMetadata')[1] !== 'undefined') + { + hostPlayer.removeEventListener('DOMSubtreeModified', xboxMusicPlayerReady); + + hostInjectionPlayerContainer = document.getElementById('navigation').getElementsByTagName('ul')[0]; + deezifyPrimaryContainer = document.createElement('li'); + deezifyPrimaryContainer.className = 'deezify-container'; + hostInjectionPlayerContainer.appendChild(deezifyPrimaryContainer); + + deezifyLinkContainer = document.createElement('a'); + deezifyLinkContainer.className = 'deezify-link'; + deezifyLinkContainer.setAttribute('data-deezify-ref', 'player'); + deezifyPrimaryContainer.appendChild(deezifyLinkContainer); + + deezifyIconContainer = document.createElement('span'); + deezifyIconContainer.className = 'iconRowSecondaryAdd'; + deezifyLinkContainer.appendChild(deezifyIconContainer); + + deezifyTextContainer = document.createElement('span'); + deezifyTextContainer.className = 'deezify-text'; + deezifyTextContainer.innerText = hostLocales.downloadMp3; + deezifyLinkContainer.appendChild(deezifyTextContainer); + + deezify.fade('in', deezifyPrimaryContainer, function() { + deezifyLinkContainer.onclick = deezify.initDownload; + deezifyTextContainer.onclick = deezifyLinkContainer.click; + }); + } + } + + } + + else if (currentHost === hostsList.beatsmusic) + { + // TODO, or release BeatsMe (rtmp parser) + } \ No newline at end of file diff --git a/src/include.js b/src/include.js new file mode 100644 index 0000000..18d03d9 --- /dev/null +++ b/src/include.js @@ -0,0 +1,440 @@ +/* + * Deezify - 1.0.1 + * @author: Alexis (@_SuckMyLuck) Bize + * @about: Match and download any track from your favorite streaming music service, without limit or ads + */ + + 'use strict'; + + var vkParams = { + 'app': { + 'token': 'aafe2494f3e87bb95a03c75ccbcb2bebeb6e5178d09dae8b7d4fca92cf3441bcec7d6789fef63b1cdc90d' + }, + 'api': { + 'url': 'https://api.vk.com', + 'method': 'getTrack', + 'version': '5.7' + } + }; + + var hostsList = { + 'rdio': 'www.rdio.com', + 'deezer': 'www.deezer.com', + 'spotify': 'play.spotify.com', + 'xboxmusic': 'music.xbox.com', + 'beatsmusic': 'listen.beatsmusic.com' + }; + + var hostPlayer = null, + hostInjectionPlayerContainer = null, + hostPlayerTrackInfoContainer = null, + hostLocales = { + 'downloadMp3': null, + 'undefinedMp3': null, + 'matchingMp3': null, + 'captchaTitle': chrome.i18n.getMessage('globalCaptchaTitle'), + 'captchaSubmit': chrome.i18n.getMessage('globalCaptchaSubmit'), + 'captchaError': null + }, + hostSongData = { + 'title': null, + 'title_container': null, + 'performer': null, + 'performer_container': null, + 'track_version': null + }; + + var currentHost = window.location.host; + var localStorageKey = 'deezify_'; + var downloadEnabled = true, + captchaRequested = false; + + var deezifyPrimaryContainer = null, + deezifyLinkContainer = null, + deezifyTextContainer = null, + deezifyIconContainer = null; + + var captchaBackground = document.createElement('div'); + captchaBackground.className = 'deezify-captcha-background'; + document.body.appendChild(captchaBackground); + + var captchaContainer = document.createElement('div'); + captchaContainer.className = 'deezify-captcha-container'; + captchaBackground.appendChild(captchaContainer); + + var captchaTitle = document.createElement('div'); + captchaTitle.className = 'deezify-captcha-title'; + captchaTitle.innerHTML = '' + hostLocales.captchaTitle + ''; + captchaContainer.appendChild(captchaTitle); + + var captchaAction = document.createElement('div'); + captchaAction.className = 'deezify-captcha-action'; + captchaContainer.appendChild(captchaAction); + + var deezify = { + + setLocales: function(host) + { + hostLocales.downloadMp3 = chrome.i18n.getMessage(host + 'DownloadMessage'); + hostLocales.undefinedMp3 = chrome.i18n.getMessage(host + 'DownloadError'); + hostLocales.matchingMp3 = chrome.i18n.getMessage(host + 'DownloadMatching'); + hostLocales.captchaError = chrome.i18n.getMessage(host + 'CaptchaError'); + }, + + initDownload: function(e) + { + if (!downloadEnabled) + return false; + + downloadEnabled = false; + var downloadRef = e.srcElement.dataset.deezifyRef; + if (typeof downloadRef === 'undefined') + var downloadRef = e.srcElement.parentElement.dataset.deezifyRef; + + deezifyTextContainer.innerText = hostLocales.matchingMp3; + + if (downloadRef === 'player') + { + if (currentHost === hostsList.deezer) + { + hostSongData.title = deezify.getDzrInfo('getSongTitle()'); + hostSongData.performer = deezify.getDzrInfo('getArtistName()'); + hostSongData.track_version = ''; + } + + else if (currentHost === hostsList.xboxmusic) + { + hostSongData.title_container = hostPlayer.getElementsByClassName('primaryMetadata')[1]; + hostSongData.performer_container = hostPlayer.getElementsByClassName('secondaryMetadata')[1]; + hostSongData.title = hostSongData.title_container.innerText.trim(); + hostSongData.performer = hostSongData.performer_container.getElementsByTagName('a')[0].innerText.trim(); + } + + else if (currentHost === hostsList.spotify) + { + hostSongData.title_container = hostPlayer.getElementsByTagName('h3')[0]; + hostSongData.performer_container = hostPlayer.getElementsByTagName('h4')[0]; + hostSongData.title = hostSongData.title_container.innerText.trim(); + hostSongData.performer = hostSongData.performer_container.getElementsByTagName('a')[0].innerText.trim(); + } + + return deezify.matchData(hostSongData); + } + }, + + matchData: function(songData, captchaData) + { + captchaData = captchaData || null; + var apiQueryData = { + 'title': songData.performer + ' - ' + songData.title, + 'auto_complete': 1, + 'access_token': vkParams.app.token, + 'v': vkParams.api.version + }; + + if (songData.track_version) + apiQueryData.title = apiQueryData.title + ' ' + songData.track_version; + + if (captchaData !== null) + { + apiQueryData.captcha_sid = captchaData.sid; + apiQueryData.captcha_key = captchaData.key; + } + + var trackTitlePatch = { + ' (Album Version Explicit)': '', + ' (Explicit Version)': '', + ' (Skit Explicit)': '', + ' (Album Version Edited)': '', + ' (Motion Picture Soundtrack)': '', + ' (From The Nissan Qashqai Movie)': '' + }; + + for (var patch in trackTitlePatch) + apiQueryData.title = apiQueryData.title.replace(patch, trackTitlePatch[patch]); + + var xmlhttp = new XMLHttpRequest(); + xmlhttp.open('GET', vkParams.api.url + '/method/execute.' + vkParams.api.method + deezify.encodeQueryData(apiQueryData), true); + xmlhttp.send(); + xmlhttp.onreadystatechange = function() + { + if (xmlhttp.readyState === 4) + { + var apiResponse = JSON.parse(xmlhttp.response); + if (typeof apiResponse.error === 'undefined' && apiResponse.response.count) + { + deezifyTextContainer.innerText = hostLocales.downloadMp3; + + var xhr = new XMLHttpRequest(); + xhr.open('GET', apiResponse.response.items[0].url, true); + xhr.responseType = 'blob'; + xhr.onload = function(e) { + if (this.status == 200) + { + var blob = new Blob([this.response], {type: 'audio/mpeg'}); + var url = window.URL.createObjectURL(blob); + var a = document.createElement('a'); + a.download = apiQueryData.title + ' - Deezify.mp3'; + a.href = url; + //a.dataset.downloadurl = ['audio/mpeg', url.download, url.href].join(':'); + a.click(); + window.URL.revokeObjectURL(url); + + downloadEnabled = true; + } + }; + xhr.send(); + } + else if (typeof apiResponse.error === 'undefined' && !apiResponse.response.count) + return deezify.setApiError(1); + + else if (typeof apiResponse.error !== 'undefined' && captchaRequested) + return deezify.setApiError(2); + + else if (apiResponse.error.error_code === 14) + { + return deezify.setCaptcha({ + 'songData': songData, + 'captchaData': { + 'sid': apiResponse.error.captcha_sid, + 'img': apiResponse.error.captcha_img + } + }); + } + + else return deezify.setApiError(1); + } + }; + return false; + }, + + setCaptcha: function(data) + { + var captchaImg = document.createElement('img'); + captchaImg.className = 'deezify-captcha-image'; + captchaImg.src = data.captchaData.img; + captchaAction.appendChild(captchaImg); + + var captchaForm = document.createElement('form'); + captchaForm.className = 'deezify-captcha-form'; + captchaForm.innerHTML = ''; + captchaAction.appendChild(captchaForm); + + var captchaSubmit = document.createElement('input'); + captchaSubmit.className = 'deezify-captcha-submit'; + captchaSubmit.type = 'submit'; + captchaSubmit.value = hostLocales.captchaSubmit; + captchaForm.appendChild(captchaSubmit); + + deezify.fade('in', captchaBackground, 100); + captchaRequested = true; + + captchaForm.onsubmit = function(e) + { + e.preventDefault(); + deezify.fade('out', captchaBackground, 100, function() + { + data.captchaData.key = captchaForm.getElementsByClassName('deezify-captcha-input')[0].value; + captchaAction.innerHTML = ''; + return deezify.matchData(data.songData, data.captchaData); + }); + }; + }, + + setApiError: function(errorType) + { + errorType = parseInt(errorType) || 1; + deezify.fade('out', deezifyTextContainer, 100, function() + { + deezifyTextContainer.innerText = errorType === 2 ? hostLocales.captchaError : hostLocales.undefinedMp3; + deezify.fade('in', deezifyTextContainer, 100, function() + { + setTimeout(function() + { + deezify.fade('out', deezifyTextContainer, 100, function() + { + deezifyTextContainer.innerText = hostLocales.downloadMp3; + deezify.fade('in', deezifyTextContainer, 100, function() + { + downloadEnabled = true; + captchaRequested = false; + }); + }); + }, 2000); + }); + }); + }, + + encodeQueryData: function(data) + { + var query = []; + for (var key in data) + query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key])); + return '?' + query.join('&'); + }, + + getDzrInfo: function(prop) + { + var xPlayerData = document.createElement('script'); + xPlayerData.type = 'text/javascript'; + xPlayerData.text = 'localStorage.setItem("' + localStorageKey + 'dzPlayer", dzPlayer.'+prop+' || "");'; + document.body.appendChild(xPlayerData); + document.body.removeChild(xPlayerData); + return localStorage.getItem(localStorageKey + 'dzPlayer'); + }, + + fade: function(type, element, speed, callback) + { + if (typeof callback !== 'function') callback = null; + if (typeof speed === 'function') callback = speed; + else if (typeof speed === 'undefined') speed = 200; + else speed = parseInt(speed); + speed = speed / 10; + + if (type === 'in') + { + element.style.display = 'block'; + element.style.opacity = 0; + var interval = setInterval(function() + { + var elementOpacity = element.style.opacity; + if (elementOpacity >= 1) + { + clearInterval(interval); + element.style.opacity = 1; + if (callback !== null) + return callback(); + } + element.style.opacity = parseFloat(elementOpacity) + 0.05; + }, speed); + } + + else if (type === 'out') + { + element.style.opacity = 1; + var interval = setInterval(function() + { + var elementOpacity = element.style.opacity; + if (elementOpacity <= 0.1) + { + element.style.display = 'none'; + clearInterval(interval); + element.style.opacity = 0; + if (callback !== null) + return callback(); + } + element.style.opacity = parseFloat(elementOpacity) - 0.05; + }, speed); + } + + } + + }; + + if (currentHost === hostsList.rdio) + { + // TODO, maybe + } + + else if (currentHost === hostsList.deezer) + { + deezify.setLocales('deezer'); + var getPlayer = setInterval(function() { + if (document.getElementsByClassName('brand').length > 0) + { + clearInterval(getPlayer); + hostInjectionPlayerContainer = document.getElementsByClassName('brand')[0]; + deezifyPrimaryContainer = document.createElement('div'); + deezifyPrimaryContainer.className = 'deezify-container'; + hostInjectionPlayerContainer.appendChild(deezifyPrimaryContainer); + + deezifyLinkContainer = document.createElement('a'); + deezifyLinkContainer.className = 'deezify-link'; + deezifyLinkContainer.setAttribute('data-deezify-ref', 'player'); + deezifyPrimaryContainer.appendChild(deezifyLinkContainer); + + deezifyTextContainer = document.createElement('span'); + deezifyTextContainer.className = 'deezify-text'; + deezifyTextContainer.innerText = hostLocales.downloadMp3; + deezifyLinkContainer.appendChild(deezifyTextContainer); + + deezify.fade('in', deezifyPrimaryContainer, function() { + deezifyLinkContainer.onclick = deezify.initDownload; + deezifyTextContainer.onclick = deezifyLinkContainer.click; + }); + } + }, 200); + } + + else if (currentHost === hostsList.spotify) + { + deezify.setLocales('spotify'); + var getPlayer = setInterval(function() { + if (!!~document.body.className.indexOf('started')) + { + clearInterval(getPlayer); + hostPlayer = document.getElementById('app-player').contentDocument.getElementById('player'); + + hostInjectionPlayerContainer = document.getElementById('main-nav').getElementsByTagName('ul')[0]; + deezifyPrimaryContainer = document.createElement('li'); + deezifyPrimaryContainer.className = 'deezify-container'; + hostInjectionPlayerContainer.appendChild(deezifyPrimaryContainer); + + deezifyLinkContainer = document.createElement('a'); + deezifyLinkContainer.className = 'deezify-link spoticon-download-32 standard-menu-item'; + deezifyLinkContainer.setAttribute('data-deezify-ref', 'player'); + deezifyPrimaryContainer.appendChild(deezifyLinkContainer); + + deezifyTextContainer = document.createElement('span'); + deezifyTextContainer.className = 'deezify-text nav-text'; + deezifyTextContainer.innerText = hostLocales.downloadMp3; + deezifyLinkContainer.appendChild(deezifyTextContainer); + + deezify.fade('in', deezifyPrimaryContainer, function() { + deezifyLinkContainer.onclick = deezify.initDownload; + deezifyTextContainer.onclick = deezifyLinkContainer.click; + }); + } + }, 200); + } + + else if (currentHost === hostsList.xboxmusic) + { + deezify.setLocales('xboxMusic'); + var getPlayer = setInterval(function() { + if (document.getElementsByClassName('playerNowPlayingMetadata').length) + { + clearInterval(getPlayer); + hostPlayer = document.getElementsByClassName('player')[0]; + + hostInjectionPlayerContainer = document.getElementById('navigation').getElementsByTagName('ul')[0]; + deezifyPrimaryContainer = document.createElement('li'); + deezifyPrimaryContainer.className = 'deezify-container'; + hostInjectionPlayerContainer.appendChild(deezifyPrimaryContainer); + + deezifyLinkContainer = document.createElement('a'); + deezifyLinkContainer.className = 'deezify-link'; + deezifyLinkContainer.setAttribute('data-deezify-ref', 'player'); + deezifyPrimaryContainer.appendChild(deezifyLinkContainer); + + deezifyIconContainer = document.createElement('span'); + deezifyIconContainer.className = 'iconRowSecondaryAdd'; + deezifyLinkContainer.appendChild(deezifyIconContainer); + + deezifyTextContainer = document.createElement('span'); + deezifyTextContainer.className = 'deezify-text'; + deezifyTextContainer.innerText = hostLocales.downloadMp3; + deezifyLinkContainer.appendChild(deezifyTextContainer); + + deezify.fade('in', deezifyPrimaryContainer, function() { + deezifyLinkContainer.onclick = deezify.initDownload; + deezifyTextContainer.onclick = deezifyLinkContainer.click; + }); + } + }, 200); + } + + else if (currentHost === hostsList.beatsmusic) + { + // Meh + }