import { serve } from "https://deno.land/std/http/server.ts"; // Consts const API_URL = "https://88.lxmusic.xn--fiqs8s"; const API_KEY = "lxmusic"; // Base64 编码函数 const handleBase64Encode = (data: string): string => { return btoa(data); }; // 通用 HTTP Fetch 函数 const httpFetch = async (url: string, options?: RequestInit): Promise => { const response = await fetch(url, options); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); // 假设响应是 JSON 格式 }; // 获取音乐 URL const handleGetMusicUrl = async (source: string, musicInfo: any, quality: string): Promise => { if (source === "local") { if (!musicInfo.songmid.startsWith("server_")) { throw new Error("unsupported local file"); } const songId = musicInfo.songmid; const requestBody = { p: songId.replace("server_", "") }; const b = handleBase64Encode(JSON.stringify(requestBody)).replace(/\+/g, "-").replace(/\//g, "_"); const targetUrl = `${API_URL}/local/c?q=${b}`; const request = await httpFetch(targetUrl, { method: "GET", headers: { "Content-Type": "application/json", "User-Agent": "lx-music-request", "X-Request-Key": API_KEY, }, }); const { code, data } = request; if (code === 0 && data && data.file) { const b2 = handleBase64Encode(JSON.stringify(requestBody)).replace(/\+/g, "-").replace(/\//g, "_"); return `${API_URL}/local/u?q=${b2}`; } throw new Error("404 Not Found"); } const songId = musicInfo.hash ?? musicInfo.songmid; const request = await httpFetch(`${API_URL}/lxmusicv3/url/${source}/${songId}/${quality}`, { method: "GET", headers: { "Content-Type": "application/json", "User-Agent": "lx-music-request", "X-Request-Key": API_KEY, }, }); const body = request; console.log(body) if (!body || isNaN(Number(body.code))) { throw new Error("unknown error"); } switch (body.code) { case 0: return body.data; // 成功返回 URL case 1: throw new Error("block ip"); case 2: throw new Error("get music url failed"); case 4: throw new Error("internal server error"); case 5: throw new Error("too many requests"); case 6: throw new Error("param error"); default: throw new Error(body.msg ?? "unknown error"); } }; // 请求处理程序 const requestHandler = async (req: Request) => { const url = new URL(req.url); const method = req.method; // CORS 支持 const headers = new Headers(); headers.set("Access-Control-Allow-Origin", "*"); headers.set("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); headers.set("Access-Control-Allow-Headers", "Content-Type"); headers.set("Content-Type", "application/json"); if (method === "OPTIONS") { return new Response(null, { headers }); } if (url.pathname === "/search") { // 检查请求方法 if (method !== "POST") { return new Response(JSON.stringify({ error: "Method not allowed" }), { status: 405, headers }); } try { // 检查请求体是否为空 const requestBody = await req.text(); if (!requestBody) { return new Response(JSON.stringify({ error: "Request body is empty" }), { status: 400, headers }); } const { action, source, musicInfo, quality } = JSON.parse(requestBody); // 验证必需的参数 if (!action) { return new Response(JSON.stringify({ error: "Missing action parameter" }), { status: 400, headers }); } let responseBody; switch (action) { case "musicUrl": if (!source || !musicInfo || !quality) { return new Response(JSON.stringify({ error: "Missing required parameters: source, musicInfo, or quality" }), { status: 400, headers }); } responseBody = await handleGetMusicUrl(source, musicInfo, quality); break; default: return new Response(JSON.stringify({ error: "action not supported" }), { status: 400, headers }); } return new Response(JSON.stringify({ success: true, data: responseBody }), { headers }); } catch (err) { // 区分JSON解析错误和其他错误 if (err instanceof SyntaxError) { return new Response(JSON.stringify({ error: "Invalid JSON in request body" }), { status: 400, headers }); } return new Response(JSON.stringify({ error: err.message }), { status: 500, headers }); } } return new Response(JSON.stringify({ error: "404 Not Found" }), { status: 404, headers }); }; serve(requestHandler, { port: 8000 }); console.log("HTTP server is running on http://localhost:8000");