Skip to content

Instantly share code, notes, and snippets.

@wongsyrone
Last active August 28, 2025 14:24
Show Gist options
  • Select an option

  • Save wongsyrone/9fb742982a2379ad58954f93c15d812b to your computer and use it in GitHub Desktop.

Select an option

Save wongsyrone/9fb742982a2379ad58954f93c15d812b to your computer and use it in GitHub Desktop.
MoonTV 配置合并worker代码
/**
* 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