Alternative Proxy / Media URL for uhwot's dzunlock

https://dzunlock-nutz.deno.dev/

Explicit songs might not work due to overused ARL


  • Uses updated ARL/cookie from r/freedeezerarl somewhere™️, meaning...
  • Proper Deezer Hi-Fi (FLAC) instead of the current proxy's Deezer Free (128k MP3)
  • Fix for regional track ID/MS2002/Track token has no sufficient rights on requested media. error via userscript patch
  • Miscellaneous edgecase fixes that you probably won't run into

Easiest way to use this is to just replace the url on the line with media_url, i.e.

1
2
3
4
5
...
            if (id >= 0 && !is_quality_available) {
                const media_server = GM_getValue('media_server', 'https://dzunlock-nutz.deno.dev')
                url = `${media_server}/get_url`
...

Hacky patch to fix the MS2002 error:

...
        } else if (url.startsWith('https://www.deezer.com/ajax/gw-light.php?method=log.listen')) {
            const json = await resp.json()

            if (typeof json.results === 'string') {
                json.results = playerTokenPatch(json.results)
            }

            resp = new Response(JSON.stringify(json), resp)
        } else if (url.startsWith('https://www.deezer.com/ajax/gw-light.php')) {
            function crawlAndCollectSongIds(obj) {
                const objType = Object.prototype.toString.call(obj).split(' ')[1].split(']')[0]
                if (objType === 'Array') {
                    return [].concat(...new Set(obj.map(crawlAndCollectSongIds)))
                } else if (objType === 'Object') {
                    if (obj.SNG_ID && parseInt(obj.SNG_ID) > 0) {
                        return [obj.SNG_ID]
                    }
                    return [].concat(...new Set(Object.values(obj).map(crawlAndCollectSongIds))).filter(id => id) // TODO: Why do undefineds appear?
                }
            }
            let json = await resp.json()
            const songIdList = crawlAndCollectSongIds(json)
            if (songIdList.length > 0) {
                const songReplaceRes = await fetch(`${GM_getValue('media_server', 'https://dzunlock-nutz.deno.dev')}/get_song`, {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({ids: songIdList})
                })
                if (songReplaceRes.status >= 200 && songReplaceRes.status < 300) {
                    const songReplaceList = await songReplaceRes.json()
                    function crawlAndReplaceSongs(obj) {
                        const objType = Object.prototype.toString.call(obj).split(' ')[1].split(']')[0]
                        if (objType === 'Array') {
                            for (const index in obj) {
                                obj[index] = crawlAndReplaceSongs(obj[index])
                            }
                        } else if (objType === 'Object') {
                            if (obj.SNG_ID && parseInt(obj.SNG_ID) > 0) {
                                return songReplaceList.find(song => song.SNG_ID.toString() === obj.SNG_ID.toString()) || obj
                            }
                            for (const index in obj) {
                                obj[index] = crawlAndReplaceSongs(obj[index])
                            }
                        }
                        return obj
                    }
                    json = crawlAndReplaceSongs(json)
                }
            }
            resp = new Response(JSON.stringify(json), resp)
        }

        return resp
    };
})(unsafeWindow.fetch);

Patch to remove hydration and force API (fix MS2002 when directly loading URLs):

1
2
3
4
5
...
window.addEventListener('DOMContentLoaded', (_) => {
    delete unsafeWindow.__DZR_APP_STATE__;
    unsafeWindow.dzPlayer.setTrackList = (function (old) {
...

P.S. The server might become slow every hour or so (including when first using it), due to whack deezer account settings

Edit
Pub: 20 Feb 2023 13:08 UTC
Edit: 06 Apr 2023 23:14 UTC
Views: 604