Compare commits
10 Commits
c19c1c2b26
...
e7c610f089
Author | SHA1 | Date |
---|---|---|
uh wot | e7c610f089 | |
uh wot | 86a2b45689 | |
uh wot | 725f846b77 | |
uh wot | a94074382c | |
uh wot | a21c19228b | |
uh wot | 0ac770d844 | |
uh wot | 7891c8a093 | |
uh wot | 795b7fd1bb | |
uh wot | ff1d8d2351 | |
uh wot | 3298f125c7 |
|
@ -6,4 +6,4 @@ enables deezer hifi features lol
|
||||||
|
|
||||||
- install [violentmonke](https://violentmonkey.github.io/) (other userscript extensions may work, but are not supported)
|
- install [violentmonke](https://violentmonkey.github.io/) (other userscript extensions may work, but are not supported)
|
||||||
|
|
||||||
- click [this link](https://git.freezer.life/uhwot/dzunlock/raw/branch/master/dzunlock.user.js)
|
- click [this link](https://uhwotgit.fly.dev/uhwot/dzunlock/raw/branch/master/dzunlock.user.js)
|
||||||
|
|
169
dzunlock.user.js
169
dzunlock.user.js
|
@ -3,10 +3,10 @@
|
||||||
// @namespace io.github.uhwot.dzunlock
|
// @namespace io.github.uhwot.dzunlock
|
||||||
// @description enables deezer hifi features lol
|
// @description enables deezer hifi features lol
|
||||||
// @author uh wot
|
// @author uh wot
|
||||||
// @version 1.3.3
|
// @version 1.4.3
|
||||||
// @license GPL-3.0-only
|
// @license GPL-3.0-only
|
||||||
// @homepageURL https://git.freezer.life/uhwot/dzunlock
|
// @homepageURL https://git.uhwot.cf/uhwot/dzunlock
|
||||||
// @downloadURL https://git.freezer.life/uhwot/dzunlock/raw/branch/master/dzunlock.user.js
|
// @downloadURL https://uhwotgit.fly.dev/uhwot/dzunlock/raw/branch/master/dzunlock.user.js
|
||||||
// @icon https://cdns-files.dzcdn.net/cache/images/common/favicon/favicon-96x96.852baf648e79894b668670e115e4a375.png
|
// @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|\?|#)/
|
// @include /^https:\/\/www\.deezer\.com\/[a-z]{2}\/($|track|album|artist|playlist|episode|show|profile|channels|podcasts|radio|\?|#)/
|
||||||
// @match https://www.deezer.com/search/*
|
// @match https://www.deezer.com/search/*
|
||||||
|
@ -26,65 +26,6 @@ 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 playerTokenKey = [102, 228, 95, 242, 215, 50, 122, 26, 57, 216, 206, 38, 164, 237, 200, 85]
|
||||||
const cipher = new aesjs.ModeOfOperation.ecb(playerTokenKey)
|
const cipher = new aesjs.ModeOfOperation.ecb(playerTokenKey)
|
||||||
|
|
||||||
|
@ -126,6 +67,8 @@ function playerTokenPatch(playerToken) {
|
||||||
// disables previews
|
// disables previews
|
||||||
playerToken.streaming = true
|
playerToken.streaming = true
|
||||||
playerToken.limited = false
|
playerToken.limited = false
|
||||||
|
// disables skip limit on mixes
|
||||||
|
playerToken.radio_skips = 0
|
||||||
|
|
||||||
log(playerToken)
|
log(playerToken)
|
||||||
|
|
||||||
|
@ -152,12 +95,59 @@ window.addEventListener('DOMContentLoaded', (_) => {
|
||||||
})(unsafeWindow.dzPlayer.setTrackList);
|
})(unsafeWindow.dzPlayer.setTrackList);
|
||||||
});
|
});
|
||||||
|
|
||||||
fetchIntercept.register({
|
// https://greasyfork.org/en/scripts/38248-websocket-logger/code
|
||||||
request: function (url, config) {
|
unsafeWindow.WebSocket = new Proxy(unsafeWindow.WebSocket, {
|
||||||
// Modify the url or config here
|
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) {
|
||||||
if (url === 'https://media.deezer.com/v1/get_url') {
|
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 quality = unsafeWindow.dzPlayer.control.getAudioQuality()
|
||||||
const track = unsafeWindow.dzPlayer.getCurrentSong()
|
|
||||||
const id = parseInt(track.SNG_ID)
|
const id = parseInt(track.SNG_ID)
|
||||||
|
|
||||||
let is_subbed = !unsafeWindow.dzPlayer.user_status.can_subscribe
|
let is_subbed = !unsafeWindow.dzPlayer.user_status.can_subscribe
|
||||||
|
@ -168,7 +158,7 @@ fetchIntercept.register({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id >= 0 && !is_quality_available) {
|
if (id >= 0 && !is_quality_available) {
|
||||||
const media_server = GM_getValue('media_server', 'https://dzmedia.herokuapp.com')
|
const media_server = GM_getValue('media_server', 'https://dzmedia.fly.dev')
|
||||||
url = `${media_server}/get_url`
|
url = `${media_server}/get_url`
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
|
@ -184,24 +174,14 @@ fetchIntercept.register({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config.body = JSON.stringify(body)
|
init.body = JSON.stringify(body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [url, config];
|
let resp = await fetch(url, init)
|
||||||
},
|
|
||||||
|
|
||||||
requestError: function (error) {
|
if (url.startsWith('https://www.deezer.com/ajax/gw-light.php?method=deezer.getUserData')) {
|
||||||
// Called when an error occured during another 'request' interceptor call
|
let json = await resp.json()
|
||||||
|
|
||||||
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
|
// removes upgrade popup stuff
|
||||||
json.results.USER.ENTRYPOINTS = {}
|
json.results.USER.ENTRYPOINTS = {}
|
||||||
|
@ -215,25 +195,24 @@ fetchIntercept.register({
|
||||||
|
|
||||||
log(json)
|
log(json)
|
||||||
|
|
||||||
return new Response(JSON.stringify(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()
|
||||||
|
|
||||||
if (response.url.startsWith('https://www.deezer.com/ajax/gw-light.php?method=log.listen')) {
|
delete json.results.MARKETING_PUSH
|
||||||
const json = await response.json()
|
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 (typeof json.results === 'string') {
|
if (typeof json.results === 'string') {
|
||||||
json.results = playerTokenPatch(json.results)
|
json.results = playerTokenPatch(json.results)
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Response(JSON.stringify(json))
|
resp = new Response(JSON.stringify(json), resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return resp
|
||||||
},
|
};
|
||||||
|
})(unsafeWindow.fetch);
|
||||||
responseError: function (error) {
|
|
||||||
// Handle an fetch error
|
|
||||||
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
Loading…
Reference in New Issue