dzserver/index.js

89 lines
3.4 KiB
JavaScript

const Router = require('./router')
const aesjs = require('aes-js');
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
const AESKEY = [106, 111, 54, 97, 101, 121, 54, 104, 97, 105, 100, 50, 84, 101, 105, 104]
url_gen = {
"cipher": new aesjs.ModeOfOperation.ecb(AESKEY),
"resolve": async function(md5_origin, format, id, media_version) { // Track URL generation function
result = [md5_origin, format, id, media_version].join('\xa4')
var buf = new ArrayBuffer(result.length);
var result_hash = new Uint8Array(buf);
for (var i=0; i < result.length; i++) {
result_hash[i] = result.charCodeAt(i);
}
result_hash = await crypto.subtle.digest('MD5', result_hash)
result_hash = Array.from(new Uint8Array(result_hash))
result_hash = result_hash.reduce(function(previous, current) {
return previous + "0".concat(current.toString(16)).substr(-2, 2);
}, ''),
result = result_hash + '\xa4' + result + '\xa4'
// padding
result += '\x00'.repeat(result.length % 16 ? 16 - result.length % 16 : 0)
// converting to array for encryption / hex string
result = Array.from(result).map(function(item) {
return item.charCodeAt(0);
})
// encryption / hex string
result = (result = url_gen.cipher.encrypt(result)).reduce(function(previous, current) {
return previous + "0".concat(current.toString(16)).substr(-2, 2);
}, '')
// cdn template with first character of md5 string + hash
return `https://e-cdns-proxy-${md5_origin[0]}.dzcdn.net/api/1/${result}`
}
}
async function track(request) {
const id = request.url.split('/')[4]
if (id === "") {
return new Response("Track ID needs to be specified", {status: 400, headers: {'content-type': "text/plain"}})
}
access_token = await KV.get("access_token")
if (access_token === null) {
const response = await fetch("https://connect.deezer.com/oauth/access_token.php?grant_type=client_credentials&client_id=447462&client_secret=a83bf7f38ad2f137e444727cfc3775cf&output=json")
const json = await response.json()
if (json.error !== undefined) {
return new Response("Couldn't get access token from Deezer", {status: 500, headers: {'content-type': "text/plain"}})
}
access_token = json.access_token
await KV.put("access_token", access_token, {expirationTtl: Number(json.expires)})
}
const response = await fetch(`https://api.deezer.com/track/${id}?access_token=${access_token}`)
const json = await response.json()
if (json.error !== undefined) {
return new Response(JSON.stringify(json.error), {status: 403, headers: {'content-type': "application/json"}})
}
const md5_origin = json.md5_origin
const format = "3"
const media_version = json.media_version
const url = await url_gen.resolve(md5_origin, format, id, media_version)
return new Response(null, {status: 302, headers: {'location': url}})
}
async function handleRequest(request) {
const r = new Router()
// Replace with the appropriate paths and handlers
r.get('/track/.*', () => track(request))
r.get('/', () => new Response('Hello worker!')) // return a default message for the root route
const resp = await r.route(request)
return resp
}