diff --git a/README.md b/README.md index c33f10c..10efd7c 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,4 @@ enables deezer hifi features lol - install [violentmonke](https://violentmonkey.github.io/) (other userscript extensions may work, but are not supported) -- click [this link](https://uhwotgit.fly.dev/uhwot/dzunlock/raw/branch/master/dzunlock.user.js) +- click [this link](https://git.freezer.life/uhwot/dzunlock/raw/branch/master/dzunlock.user.js) \ No newline at end of file diff --git a/dzunlock.user.js b/dzunlock.user.js index 0f45cfe..6a69b1e 100644 --- a/dzunlock.user.js +++ b/dzunlock.user.js @@ -3,10 +3,10 @@ // @namespace io.github.uhwot.dzunlock // @description enables deezer hifi features lol // @author uh wot -// @version 1.4.3 +// @version 1.3.3 // @license GPL-3.0-only -// @homepageURL https://git.uhwot.cf/uhwot/dzunlock -// @downloadURL https://uhwotgit.fly.dev/uhwot/dzunlock/raw/branch/master/dzunlock.user.js +// @homepageURL https://git.freezer.life/uhwot/dzunlock +// @downloadURL https://git.freezer.life/uhwot/dzunlock/raw/branch/master/dzunlock.user.js // @icon https://cdns-files.dzcdn.net/cache/images/common/favicon/favicon-96x96.852baf648e79894b668670e115e4a375.png // @include /^https:\/\/www\.deezer\.com\/[a-z]{2}\/($|track|album|artist|playlist|episode|show|profile|channels|podcasts|radio|\?|#)/ // @match https://www.deezer.com/search/* @@ -26,6 +26,65 @@ function log(...args) { } } +// https://github.com/werk85/fetch-intercept/blob/develop/src/attach.js modified for browser support +let interceptors = []; + +function interceptor(fetch, ...args) { + const reversedInterceptors = interceptors.reduce((array, interceptor) => [interceptor].concat(array), []); + let promise = Promise.resolve(args); + + // Register request interceptors + reversedInterceptors.forEach(({ request, requestError }) => { + if (request || requestError) { + promise = promise.then(args => request(...args), requestError); + } + }); + + // Register fetch call + promise = promise.then(args => { + const request = new Request(...args); + return fetch(request).then(response => { + response.request = request; + return response; + }).catch(error => { + error.request = request; + return Promise.reject(error); + }); + }); + + // Register response interceptors + reversedInterceptors.forEach(({ response, responseError }) => { + if (response || responseError) { + promise = promise.then(response, responseError); + } + }); + + return promise; +} + +unsafeWindow.fetch = (function (fetch) { + return function (...args) { + return interceptor(fetch, ...args); + }; +})(unsafeWindow.fetch); + +fetchIntercept = { + register: function (interceptor) { + interceptors.push(interceptor); + return () => { + const index = interceptors.indexOf(interceptor); + if (index >= 0) { + interceptors.splice(index, 1); + } + }; + }, + clear: function () { + interceptors = []; + } +}; + +// main code starts here + const playerTokenKey = [102, 228, 95, 242, 215, 50, 122, 26, 57, 216, 206, 38, 164, 237, 200, 85] const cipher = new aesjs.ModeOfOperation.ecb(playerTokenKey) @@ -67,8 +126,6 @@ function playerTokenPatch(playerToken) { // disables previews playerToken.streaming = true playerToken.limited = false - // disables skip limit on mixes - playerToken.radio_skips = 0 log(playerToken) @@ -95,59 +152,12 @@ window.addEventListener('DOMContentLoaded', (_) => { })(unsafeWindow.dzPlayer.setTrackList); }); -// https://greasyfork.org/en/scripts/38248-websocket-logger/code -unsafeWindow.WebSocket = new Proxy(unsafeWindow.WebSocket, { - construct: function (target, args, _) { - const url = args[0] - const ws = new target(url) - - if (url !== 'wss://messaging.deezer.com/websocket') { - return ws - } else { - log('hooking websocket') - - return new Proxy(ws, { - set: function (target, prop, val) { - if (prop == 'onmessage') { - var onmsg = val; - val = function (e) { - if (e.data.includes('SingleInstancePlayback')) { - log('preventing SingleInstancePlayback pubsub receive') - return - } - onmsg(e) - }; - } - return target[prop] = val - }, - get: function (target, prop) { - var val = target[prop]; - if (prop == 'send') val = function (data) { - if (data.includes('SingleInstancePlayback')) { - log('preventing SingleInstancePlayback pubsub send') - return - } - target.send(data) - }; - else if (typeof val == 'function') val = val.bind(target) - return val - } - }) - } - } -}) - -unsafeWindow.fetch = (function (fetch) { - return async function (url, init) { +fetchIntercept.register({ + request: function (url, config) { + // Modify the url or config here if (url === 'https://media.deezer.com/v1/get_url') { - let track - if (unsafeWindow.dzPlayer.getPosition() === 0) { - track = unsafeWindow.dzPlayer.getCurrentSong() - } else { - track = unsafeWindow.dzPlayer.getNextSong() // gapless playback - } - const quality = unsafeWindow.dzPlayer.control.getAudioQuality() + const track = unsafeWindow.dzPlayer.getCurrentSong() const id = parseInt(track.SNG_ID) let is_subbed = !unsafeWindow.dzPlayer.user_status.can_subscribe @@ -158,7 +168,7 @@ unsafeWindow.fetch = (function (fetch) { } if (id >= 0 && !is_quality_available) { - const media_server = GM_getValue('media_server', 'https://dzmedia.fly.dev') + const media_server = GM_getValue('media_server', 'https://dzmedia.herokuapp.com') url = `${media_server}/get_url` const body = { @@ -174,14 +184,24 @@ unsafeWindow.fetch = (function (fetch) { } } - init.body = JSON.stringify(body) + config.body = JSON.stringify(body) } } - let resp = await fetch(url, init) + return [url, config]; + }, - if (url.startsWith('https://www.deezer.com/ajax/gw-light.php?method=deezer.getUserData')) { - let json = await resp.json() + requestError: function (error) { + // Called when an error occured during another 'request' interceptor call + + return Promise.reject(error); + }, + + response: async function (response) { + // Modify the response object + + if (response.url.startsWith('https://www.deezer.com/ajax/gw-light.php?method=deezer.getUserData')) { + let json = await response.json() // removes upgrade popup stuff json.results.USER.ENTRYPOINTS = {} @@ -195,24 +215,25 @@ unsafeWindow.fetch = (function (fetch) { log(json) - resp = new Response(JSON.stringify(json), resp) - } else if (url.startsWith('https://www.deezer.com/ajax/gw-light.php?method=deezer.userMenu')) { - let json = await resp.json() + return new Response(JSON.stringify(json)) + } - delete json.results.MARKETING_PUSH - delete json.results.MARKETING_PUSH_DATA - - resp = new Response(JSON.stringify(json), resp) - } else if (url.startsWith('https://www.deezer.com/ajax/gw-light.php?method=log.listen')) { - const json = await resp.json() + if (response.url.startsWith('https://www.deezer.com/ajax/gw-light.php?method=log.listen')) { + const json = await response.json() if (typeof json.results === 'string') { json.results = playerTokenPatch(json.results) } - resp = new Response(JSON.stringify(json), resp) + return new Response(JSON.stringify(json)) } - return resp - }; -})(unsafeWindow.fetch); + return response; + }, + + responseError: function (error) { + // Handle an fetch error + + return Promise.reject(error); + } +}); \ No newline at end of file