Last active
August 28, 2025 14:24
-
-
Save wongsyrone/9fb742982a2379ad58954f93c15d812b to your computer and use it in GitHub Desktop.
MoonTV 配置合并worker代码
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Welcome to Cloudflare Workers! This is your first worker. | |
| * | |
| * - Run "npm run dev" in your terminal to start a development server | |
| * - Open a browser tab at http://localhost:8787/ to see your worker in action | |
| * - Run "npm run deploy" to publish your worker | |
| * | |
| * Learn more at https://developers.cloudflare.com/workers/ | |
| */ | |
| addEventListener('fetch', event => { | |
| event.respondWith(handleRequest(event.request)) | |
| }) | |
| function removeDuplicatesByApi(apiSiteData) { | |
| const uniqueApis = new Set(); | |
| const filteredSites = {}; | |
| for (const key in apiSiteData) { | |
| const site = apiSiteData[key]; | |
| if (site.api && !uniqueApis.has(site.api)) { | |
| uniqueApis.add(site.api); | |
| filteredSites[key] = site; | |
| } | |
| } | |
| return filteredSites; | |
| } | |
| async function handleRequest(request) { | |
| try { | |
| // 解析 URL 参数 | |
| const url = new URL(request.url) | |
| const noEncode = url.searchParams.get('noencode'); | |
| const targetUrls = url.searchParams.getAll('url') | |
| if (targetUrls.length == 0) { | |
| return new Response('Missing url parameter', { status: 400 }) | |
| } | |
| let respArr = []; | |
| for (let targetUrl of targetUrls) { | |
| // 验证 URL 格式 | |
| try { | |
| new URL(targetUrl) | |
| } catch { | |
| return new Response('Invalid URL format', { status: 400 }) | |
| } | |
| // 从远程获取 | |
| const response = await fetch(targetUrl) | |
| if (!response.ok) { | |
| return new Response(`Failed to fetch: ${response.status}: ${targetUrl}`, { status: response.status }) | |
| } | |
| const textData = await response.text(); | |
| let dataObj = { | |
| "type": "json", | |
| } | |
| try { | |
| let parsed = JSON.parse(textData); | |
| dataObj["type"] = "json"; | |
| dataObj["data"] = parsed; | |
| } catch (error) { | |
| // not json | |
| dataObj["type"] = "text"; | |
| } | |
| if (dataObj["type"] === "text") { | |
| if (!isBase58(textData)) { | |
| continue; | |
| } | |
| try { | |
| let parsed = JSON.parse(base58Decode(textData)); | |
| dataObj["type"] = "json"; | |
| dataObj["data"] = parsed; | |
| } catch (error) { | |
| // cannot parse, ignore | |
| continue; | |
| } | |
| } | |
| respArr.push(dataObj); | |
| } | |
| let resultObj = {}; | |
| let shortestCacheTime = Number.MAX_SAFE_INTEGER; | |
| for (let data of respArr) { | |
| if (data.type === "json") { | |
| if (Object.hasOwn(data.data, "cache_time")) { | |
| let parsedTime = parseInt(data.data["cache_time"]); | |
| if (parsedTime < shortestCacheTime) { | |
| shortestCacheTime = parsedTime; | |
| } | |
| delete data.data["cache_time"] | |
| } | |
| Object.assign(resultObj, data.data); | |
| } | |
| } | |
| resultObj["cache_time"] = shortestCacheTime; | |
| if (Object.hasOwn(resultObj, "api_site")) { | |
| resultObj.api_site = removeDuplicatesByApi(resultObj.api_site) | |
| } | |
| const jsonStr = JSON.stringify(resultObj); | |
| let body = jsonStr; | |
| if (!noEncode) { | |
| // 对 JSON 做 base58 编码 | |
| body = base58Encode(jsonStr) | |
| } | |
| return new Response(body, { | |
| headers: { | |
| 'Content-Type': 'text/plain;charset=utf-8', | |
| 'Access-Control-Allow-Origin': '*' | |
| } | |
| }) | |
| } catch (error) { | |
| return new Response(`Error: ${error.message}`, { status: 500 }) | |
| } | |
| } | |
| const isBase58 = value => /^[A-HJ-NP-Za-km-z1-9]*$/.test(value); | |
| // Base58 编码实现 | |
| function base58Encode(str) { | |
| const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' | |
| const bytes = new TextEncoder().encode(str) | |
| if (bytes.length === 0) return '' | |
| let num = BigInt('0x' + Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('')) | |
| if (num === 0n) return ALPHABET[0] | |
| let result = '' | |
| while (num > 0n) { | |
| result = ALPHABET[Number(num % 58n)] + result | |
| num = num / 58n | |
| } | |
| // 处理前导零 | |
| for (let i = 0; i < bytes.length && bytes[i] === 0; i++) { | |
| result = ALPHABET[0] + result | |
| } | |
| return result | |
| } | |
| function base58Decode(input) { | |
| const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; | |
| // Handle leading '0' characters | |
| let leadingZeros = 0; | |
| for (let i = 0; i < input.length && input[i] === '0'; i++) { | |
| leadingZeros++; | |
| } | |
| // Convert Base58 string to a large integer (BigInt) | |
| let num = BigInt(0); | |
| for (let i = 0; i < input.length; i++) { | |
| const char = input[i]; | |
| const charIndex = ALPHABET.indexOf(char); | |
| if (charIndex === -1) { | |
| throw new Error('Invalid Base58 character encountered.'); | |
| } | |
| num = num * BigInt(58) + BigInt(charIndex); | |
| } | |
| // Convert the large integer to a byte array | |
| const bytes = []; | |
| while (num > 0) { | |
| bytes.push(Number(num % BigInt(256))); | |
| num = num / BigInt(256); | |
| } | |
| bytes.reverse(); | |
| // Prepend zero bytes | |
| for (let i = 0; i < leadingZeros; i++) { | |
| bytes.unshift(0); | |
| } | |
| const retBytes = new Uint8Array(bytes); | |
| return new TextDecoder().decode(retBytes); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment