diff --git a/dist/worker.js b/dist/worker.js index 1eb39a7..ae1fe6d 100644 --- a/dist/worker.js +++ b/dist/worker.js @@ -1,4 +1,4 @@ -!function(t){var e={};function r(n){if(e[n])return e[n].exports;var i=e[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)r.d(n,i,function(e){return t[e]}.bind(null,i));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,r){(function(t){const e=r(6),n=r(7),i=r(8),o=r(9);addEventListener("fetch",t=>{t.respondWith(async function(t){const r=new e;r.get("/track/.*",()=>c("track",t)),r.get("/album/.*",()=>c("album",t)),r.get("/playlist/.*",()=>c("playlist",t));return await r.route(t)}(t.request))});const s=[106,111,54,97,101,121,54,104,97,105,100,50,84,101,105,104],a=[103,52,101,108,53,56,119,99,48,122,118,102,57,110,97,49];function u(t){return Array.from(t).map((function(t){return t.charCodeAt(0)}))}async function h(t){let e=await crypto.subtle.digest("MD5",new Uint8Array(u(t)));e=n.utils.hex.fromBytes(new Uint8Array(e)),key=[];for(let t=0;t<16;t++)key.push(e[t].charCodeAt(0)^e[t+16].charCodeAt(0)^a[t]);return r=key,String.fromCharCode.apply(String,r);var r}const f={64:"10",128:"1",320:"3",misc:"0"};async function c(e,r){if(access_token=await KV.get("access_token"),null===access_token){const t=await fetch("https://connect.deezer.com/oauth/access_token.php?grant_type=client_credentials&client_id=447462&client_secret=a83bf7f38ad2f137e444727cfc3775cf&output=json"),e=await t.json();if(void 0!==e.error)return new Response("Couldn't get access token from Deezer",{status:500,headers:{"content-type":"text/plain"}});access_token=e.access_token,await KV.put("access_token",access_token,{expirationTtl:Number(e.expires)})}const a=new URL(r.url),c=a.pathname.split("/")[2];if(""===c)return new Response("ID needs to be specified",{status:400,headers:{"content-type":"text/plain"}});if(format=a.searchParams.get("f"),null===format)format="320";else if(format=format.toLowerCase(),void 0===f[format]){if(index=Object.values(f).indexOf(format),-1===index)return new Response("Invalid format",{status:400,headers:{"content-type":"text/plain"}});format=Object.keys(f)[index]}var l=a.searchParams.get("t");switch(l="true"===l||"1"===l,e){case"track":return await async function(e,r,a,c){const l=await fetch(`https://api.deezer.com/track/${e}?access_token=${a}`),p=await l.json();if(void 0!==p.error)return new Response(JSON.stringify(p.error),{status:403,headers:{"content-type":"application/json"}});if(result=await async function(t,e){t.alternative&&(t=t.alternative);const r=t.id,i=t.md5_origin,o=t.media_version;r<0&&(e="misc");if("0"===t["filesize_"+e])return new Response("Format unavailable",{status:403,headers:{"content-type":"text/plain"}});return e=f[e],await async function(t,e,r,i){const o=new n.ModeOfOperation.ecb(s);let a=[t,e,r,i].join("¤"),h=await crypto.subtle.digest("MD5",new Uint8Array(u(a)));return h=n.utils.hex.fromBytes(new Uint8Array(h)),a=h+"¤"+a+"¤",a.length%16&&(a+="\0".repeat(16-a.length%16)),a=n.utils.hex.fromBytes(o.encrypt(u(a))),`https://cdns-proxy-${t[0]}.dzcdn.net/mobile/1/${a}`}(i,e,r,o)}(p,r),"object"==typeof result)return result;const g=await fetch(result);if(200!==g.status)return new Response("Couldn't get track stream",{status:403,headers:{"content-type":"text/plain"}});let d;if(c){if(d=new i(t.alloc(0)),d.padding=0,d.setFrame("TIT2",p.title).setFrame("TALB",p.album.title).setFrame("TPE2",p.artist.name),void 0!==p.contributors){contr_list=[];for(const t of p.contributors)contr_list.push(t.name);d.setFrame("TPE1",contr_list)}if(void 0!==p.track_position&&d.setFrame("TRCK",p.track_position),void 0!==p.disk_number&&d.setFrame("TPOS",p.disk_number),""!==p.isrc&&d.setFrame("TSRC",p.isrc),void 0!==p.bpm&&d.setFrame("TBPM",p.bpm),void 0!==p.release_date){const t=p.release_date.split("-");d.setFrame("TYER",t[0]),d.setFrame("TDAT",t[2]+t[1])}if(""!==p.md5_image){const t=`https://cdns-images.dzcdn.net/images/cover/${p.md5_image}/1000x1000-000000-80-0-0.jpg`,e=await fetch(t),r=await e.arrayBuffer();d.setFrame("APIC",{type:3,data:r,description:"cover"})}d.addTag()}let{readable:y,writable:w}=new TransformStream;const v=w.getWriter();d&&v.write(d.arrayBuffer);const m=await h(e),b=Number(g.headers.get("Content-Length"));return async function(t,e,r,n){const i=new o(n,o.MODE.CBC,o.PADDING.NULL);i.setIv("\0");const s=e.getReader({mode:"byob"});let a=0,u=!1;for(;!u;){let e;u=a+2048>r,e=u?new Int8Array(r-a):new Int8Array(2048);let n=0;for(;n!==e.length;){let t=(await s.read(new Int8Array(e.length-n))).value;e.set(t,n),n+=t.length}a%6144!=0||u||(e=i.decode(e,o.TYPE.UINT8_ARRAY)),t.write(e),a+=2048}await s.cancel(),await t.close()}(v,g.body,b,m),new Response(y,{status:200,headers:{"content-type":"audio/mpeg"}})}(c,format,access_token,l);case"album":case"playlist":return await async function(t,e,r,n,i){const o=await fetch(`https://api.deezer.com/${t}/${e}?access_token=${n}&limit=-1`),s=await o.json();if(void 0!==s.error)return new Response(JSON.stringify(s.error),{status:403,headers:{"content-type":"application/json"}});var a="#EXTM3U\n";for(const t of s.tracks.data){t.id<0&&(r="misc");let e=`https://dz.uhwot.workers.dev/track/${t.id}?f=${r}&t=${Number(i)}`;a+=`#EXTINF:${t.duration},${t.title}\n${e}\n`}return new Response(a,{status:200,headers:{"content-type":"audio/mpegurl"}})}(e,c,format,access_token,l)}}}).call(this,r(1).Buffer)},function(t,e,r){"use strict";(function(t){ +!function(t){var e={};function r(n){if(e[n])return e[n].exports;var i=e[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)r.d(n,i,function(e){return t[e]}.bind(null,i));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,r){(function(t){const e=r(6),n=r(7),i=r(8),o=r(9);addEventListener("fetch",t=>{t.respondWith(async function(t){const r=new e;r.get("/track/.*",()=>c("track",t)),r.get("/album/.*",()=>c("album",t)),r.get("/playlist/.*",()=>c("playlist",t));return await r.route(t)}(t.request))});const s=[106,111,54,97,101,121,54,104,97,105,100,50,84,101,105,104],a=[103,52,101,108,53,56,119,99,48,122,118,102,57,110,97,49];function u(t){return Array.from(t).map((function(t){return t.charCodeAt(0)}))}async function h(t){let e=await crypto.subtle.digest("MD5",new Uint8Array(u(t)));e=n.utils.hex.fromBytes(new Uint8Array(e)),key=[];for(let t=0;t<16;t++)key.push(e[t].charCodeAt(0)^e[t+16].charCodeAt(0)^a[t]);return r=key,String.fromCharCode.apply(String,r);var r}const f={64:"10",128:"1",320:"3",misc:"0"};async function c(e,r){if(access_token=await KV.get("access_token"),null===access_token){const t=await fetch("https://connect.deezer.com/oauth/access_token.php?grant_type=client_credentials&client_id=447462&client_secret=a83bf7f38ad2f137e444727cfc3775cf&output=json"),e=await t.json();if(void 0!==e.error)return new Response("Couldn't get access token from Deezer",{status:500,headers:{"content-type":"text/plain"}});access_token=e.access_token,await KV.put("access_token",access_token,{expirationTtl:Number(e.expires)})}const a=new URL(r.url),c=a.pathname.split("/")[2];if(""===c)return new Response("ID needs to be specified",{status:400,headers:{"content-type":"text/plain"}});if(format=a.searchParams.get("f"),null===format)format="320";else if(format=format.toLowerCase(),void 0===f[format]){if(index=Object.values(f).indexOf(format),-1===index)return new Response("Invalid format",{status:400,headers:{"content-type":"text/plain"}});format=Object.keys(f)[index]}var l=a.searchParams.get("t");switch(l="true"===l||"1"===l,e){case"track":return await async function(e,r,a,c){const l=await fetch(`https://api.deezer.com/track/${e}?access_token=${a}`),p=await l.json();if(void 0!==p.error)return new Response(JSON.stringify(p.error),{status:403,headers:{"content-type":"application/json"}});if(result=await async function(t,e){t.alternative&&(t=t.alternative);const r=t.id,i=t.md5_origin,o=t.media_version;r<0&&(e="misc");if("0"===t["filesize_"+e])return new Response("Format unavailable",{status:403,headers:{"content-type":"text/plain"}});return e=f[e],await async function(t,e,r,i){const o=new n.ModeOfOperation.ecb(s);let a=[t,e,r,i].join("¤"),h=await crypto.subtle.digest("MD5",new Uint8Array(u(a)));return h=n.utils.hex.fromBytes(new Uint8Array(h)),a=h+"¤"+a+"¤",a.length%16&&(a+="\0".repeat(16-a.length%16)),a=n.utils.hex.fromBytes(o.encrypt(u(a))),`https://cdns-proxy-${t[0]}.dzcdn.net/mobile/1/${a}`}(i,e,r,o)}(p,r),"object"==typeof result)return result;const g=await fetch(result);if(200!==g.status)return new Response("Couldn't get track stream",{status:403,headers:{"content-type":"text/plain"}});let d;if(c){if(d=new i(t.alloc(0)),d.padding=0,d.setFrame("TIT2",p.title).setFrame("TALB",p.album.title).setFrame("TPE2",p.artist.name),void 0!==p.contributors){contr_list=[];for(const t of p.contributors)contr_list.push(t.name);d.setFrame("TPE1",contr_list)}if(void 0!==p.track_position&&d.setFrame("TRCK",p.track_position),void 0!==p.disk_number&&d.setFrame("TPOS",p.disk_number),""!==p.isrc&&d.setFrame("TSRC",p.isrc),void 0!==p.bpm&&d.setFrame("TBPM",p.bpm),void 0!==p.release_date){const t=p.release_date.split("-");d.setFrame("TYER",t[0]),d.setFrame("TDAT",t[2]+t[1])}if(""!==p.md5_image){const t=`https://cdns-images.dzcdn.net/images/cover/${p.md5_image}/1000x1000-000000-80-0-0.jpg`,e=await fetch(t),r=await e.arrayBuffer();d.setFrame("APIC",{type:3,data:r,description:"cover"})}d.addTag()}let{readable:y,writable:w}=new TransformStream;const v=w.getWriter();d&&v.write(d.arrayBuffer);p.alternative&&(e=p.alternative.id.toString());const m=await h(e),b=Number(g.headers.get("Content-Length"));return async function(t,e,r,n){const i=new o(n,o.MODE.CBC,o.PADDING.NULL);i.setIv("\0");const s=e.getReader({mode:"byob"});let a=0,u=!1;for(;!u;){let e;u=a+2048>r,e=u?new Int8Array(r-a):new Int8Array(2048);let n=0;for(;n!==e.length;){let t=(await s.read(new Int8Array(e.length-n))).value;e.set(t,n),n+=t.length}a%6144!=0||u||(e=i.decode(e,o.TYPE.UINT8_ARRAY)),t.write(e),a+=2048}await s.cancel(),await t.close()}(v,g.body,b,m),new Response(y,{status:200,headers:{"content-type":"audio/mpeg"}})}(c,format,access_token,l);case"album":case"playlist":return await async function(t,e,r,n,i){const o=await fetch(`https://api.deezer.com/${t}/${e}?access_token=${n}&limit=-1`),s=await o.json();if(void 0!==s.error)return new Response(JSON.stringify(s.error),{status:403,headers:{"content-type":"application/json"}});var a="#EXTM3U\n";for(const t of s.tracks.data){t.id<0&&(r="misc");let e=`https://dz.uhwot.workers.dev/track/${t.id}?f=${r}&t=${Number(i)}`;a+=`#EXTINF:${t.duration},${t.title}\n${e}\n`}return new Response(a,{status:200,headers:{"content-type":"audio/mpegurl"}})}(e,c,format,access_token,l)}}}).call(this,r(1).Buffer)},function(t,e,r){"use strict";(function(t){ /*! * The buffer module from node.js, for the browser. * diff --git a/index.js b/index.js index b7f13df..f28394c 100644 --- a/index.js +++ b/index.js @@ -184,6 +184,11 @@ async function track(id, format, access_token, tagging) { writer.write(id3.arrayBuffer) } + // needed if track has fallback, like https://www.deezer.com/track/11835714 + if (json.alternative) { + id = json.alternative.id.toString() + } + const bfKey = await bf_key(id) const length = Number(track.headers.get('Content-Length')) @@ -231,7 +236,7 @@ async function pipeDecryptedStream(writer, body, length, bfKey) { } async function track_url(json, format) { - // needed if track has fallback, like https://www.deezer.com/track/1398759152 + // needed if track has fallback, like https://www.deezer.com/track/11835714 if (json.alternative) { json = json.alternative }