diff --git a/dnsconfig.js b/dnsconfig.js index 0ad6d947c3..b43be7405b 100644 --- a/dnsconfig.js +++ b/dnsconfig.js @@ -145,6 +145,16 @@ for (var subdomain in domains) { records.push(TXT("_discord." + subdomainName, "\"" + data.services.discord + "\"")); } } + + if (data.services.vercel) { + if (Array.isArray(data.services.vercel)) { + for (var txt in data.services.vercel) { + records.push(TXT("_vercel." + subdomainName, "\"" + data.services.vercel[txt] + "\"")); + } + } else { + records.push(TXT("_vercel." + subdomainName, "\"" + data.services.vercel + "\"")); + } + } } } diff --git a/tests/domains.test.js b/tests/domains.test.js index 269ba3fc7c..8f9c1fd5e2 100644 --- a/tests/domains.test.js +++ b/tests/domains.test.js @@ -30,10 +30,7 @@ t("Nested subdomains should not exist without a parent subdomain", (t) => { const parent = parts.slice(i).join("."); if (parent.startsWith("_")) continue; - t.true( - files.includes(`${parent}.json`), - `${file}: Parent subdomain "${parent}" does not exist` - ); + t.true(files.includes(`${parent}.json`), `${file}: Parent subdomain "${parent}" does not exist`); } }); }); @@ -111,8 +108,18 @@ t("Disallow nested subdomains when parent has specific service records", (t) => const subdomain = file.replace(/\.json$/, ""); const data = getDomainData(subdomain); - if(data?.services?.discord) { - t.false(files.includes(`_discord.${file}`), `${file}: Nested subdomain "_discord.${subdomain}" should not exist when services.discord is present`); + if (data?.services?.discord) { + t.false( + files.includes(`_discord.${file}`), + `${file}: Nested subdomain "_discord.${subdomain}" should not exist when services.discord is present` + ); + } + + if (data?.services?.vercel) { + t.false( + files.includes(`_vercel.${file}`), + `${file}: Nested subdomain "_vercel.${subdomain}" should not exist when services.vercel is present` + ); } }); diff --git a/tests/json.test.js b/tests/json.test.js index 9171442149..7b58c0fb77 100644 --- a/tests/json.test.js +++ b/tests/json.test.js @@ -154,7 +154,14 @@ async function processFile(file, t) { if (data.services.discord) { t.true( Array.isArray(data.services.discord) || typeof data.services.discord === "string", - `${file}: Discord service should be an array or string` + `${file}: services.discord should be an array or string` + ); + } + + if (data.services.vercel) { + t.true( + Array.isArray(data.services.vercel) || typeof data.services.vercel === "string", + `${file}: services.vercel should be an array or string` ); } } diff --git a/tests/records.test.js b/tests/records.test.js index f6f4e7960b..4792830ed0 100644 --- a/tests/records.test.js +++ b/tests/records.test.js @@ -339,7 +339,7 @@ t("All files should have valid service records", (t) => { discord.forEach((value) => { const token = value.split("=")[1]; - t.true(value.startsWith("dh="), `${file}: Discord service record should start with "dh="`); + t.true(value.startsWith("dh="), `${file}: Invalid Discord service record format`); t.true(token.length === 40, `${file}: Discord service token should be 40 characters long`); t.true( isValidHexadecimal(token), @@ -347,6 +347,15 @@ t("All files should have valid service records", (t) => { ); }); } + + if (data?.services?.vercel) { + const vercel = Array.isArray(data.services.vercel) ? data.services.vercel : [data.services.vercel]; + + vercel.forEach((value) => { + t.true(value.startsWith("vc-domain-verify="), `${file}: Invalid Vercel service record format`); + t.true(value.length > 48, `${file}: Vercel service token should be longer than 48 characters`); + }); + } }); t.pass(); diff --git a/util/raw-api.js b/util/raw-api.js index 2ac24acb78..a4cc181151 100644 --- a/util/raw-api.js +++ b/util/raw-api.js @@ -134,6 +134,28 @@ fs.readdir(directoryPath, function (err, files) { } }); } + + if (item.services.vercel) { + const vercel = Array.isArray(item.services.vercel) ? item.services.vercel : [item.services.vercel]; + + v1.push({ + domain: `_vercel.${item.domain}`, + subdomain: `_vercel.${item.subdomain}`, + owner: item.owner, + record: { + TXT: vercel + } + }); + + v2.push({ + domain: `_vercel.${item.domain}`, + subdomain: `_vercel.${item.subdomain}`, + owner: item.owner, + records: { + TXT: vercel + } + }); + } } processedCount++;