ArrayBuffer.prototype.toString = function (encode) { switch (encode) { case 'base64': return btoa(String.fromCharCode.apply(null, new Uint8Array(this))) default: return Object.prototype.toString.call(this) } } const Buffer = { from: string => { const buffer = new ArrayBuffer(string.length) const array = new Uint8Array(buffer) Array.from(Array(string.length).keys()).forEach(index => array[index] = string.charCodeAt(index)) return buffer } } const iv = Buffer.from('0102030405060708') const presetKey = Buffer.from('0CoJUm6Qyw8W8jud') const customKey = Buffer.from('XPDvTQADC4UeVHpm') const encSecKey = 'ac890df3613ca8fd38e9614d282482326cbeee4aa035003411bb9f82446d7e8731b8a9eaa73c34d5707e9570444b6b7e011b8da2b4f2e9ec44da6883263eec19047e75bb28599b05e863e4249a128265c8a6c75ef39b85c04e2e88773e6b42f8b46141e004649d50c03ed951948cd6029837a153af86c81c88695ec0e1ab8386' const weapi = async (text) => { const cryptoPresetKey = await crypto.subtle.importKey('raw', presetKey, 'AES-CBC', true, ['encrypt']) const stage = await crypto.subtle.encrypt({ name: 'AES-CBC', iv }, cryptoPresetKey, Buffer.from(text || '')) const cryptoCustomKey = await crypto.subtle.importKey('raw', customKey, 'AES-CBC', true, ['encrypt']) const final = await crypto.subtle.encrypt({ name: 'AES-CBC', iv }, cryptoCustomKey, Buffer.from(stage.toString('base64'))) const params = final.toString('base64') return new URLSearchParams({ params, encSecKey }).toString() } const purify = object => (Object.keys(object).forEach(key => !object[key] && delete object[key]), object) const handleRequest = async request => { const { headers } = request const CORS = purify({ 'Access-Control-Allow-Credentials': true, 'Access-Control-Allow-Origin': headers.get('Origin'), 'Access-Control-Allow-Methods': headers.get('Access-Control-Request-Method'), 'Access-Control-Allow-Headers': headers.get('Access-Control-Request-Headers'), }) if (request.method === 'OPTIONS') return new Response(null, { status: 204, headers: CORS }) const path = new URL(request.url).pathname.replace(/^\/*\w*api/, '').slice(1) // const contentType = headers.get('content-type') || '' // const badRequest = new Response(null, { status: 400, headers: CORS }) // if (!path || !contentType.includes('application/json')) return badRequest // let data = {} // try { data = await request.json() } catch(_) { return badRequest } // data.header = { os: 'pc' } // const text = JSON.stringify(data) const text = await request.text() const body = await weapi(text) let response = await fetch(`https://music.163.com/weapi/${path}`, { method: 'POST', body, headers: purify({ 'Cookie': headers.get('Cookie'), 'User-Agent': headers.get('User-Agent'), // 'X-Real-IP': headers.get('CF-Connecting-IP'), 'Content-Type': 'application/x-www-form-urlencoded', }) }) response = new Response(response.body, response) Object.entries(CORS).forEach(([name, value]) => response.headers.set(name, value)) return response } addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) })