mirror of
https://github.com/tiennm99/open-domains.git
synced 2026-10-11 03:13:41 +00:00
220 lines
7.6 KiB
JavaScript
220 lines
7.6 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const readline = require('readline');
|
|
|
|
const domainsDir = path.join(__dirname, '../domains');
|
|
|
|
const rl = readline.createInterface({
|
|
input: process.stdin,
|
|
output: process.stdout
|
|
});
|
|
|
|
const sectionMap = {
|
|
1: 'Non-JSON file detection',
|
|
2: 'JSON syntax validation',
|
|
3: 'Owner property validation',
|
|
4: 'Filename format validation',
|
|
5: 'Filename content match validation'
|
|
};
|
|
|
|
function askQuestion(query) {
|
|
return new Promise(resolve => rl.question(query, answer => resolve(answer)));
|
|
}
|
|
|
|
(async () => {
|
|
console.log('Which sections would you like to run?\n');
|
|
|
|
for (const [key, desc] of Object.entries(sectionMap)) {
|
|
console.log(`${key}: ${desc}`);
|
|
}
|
|
|
|
const sectionInput = await askQuestion('\nEnter section numbers separated by spaces (e.g., 1 3 4): ');
|
|
const selectedSections = sectionInput
|
|
.split(' ')
|
|
.map(s => parseInt(s.trim()))
|
|
.filter(num => sectionMap[num]);
|
|
|
|
if (selectedSections.length === 0) {
|
|
console.log('\n❌ No valid sections selected. Exiting.');
|
|
rl.close();
|
|
return;
|
|
}
|
|
|
|
const confirm = await askQuestion(`\nYou selected: ${selectedSections.join(' ')}. Confirm? ((Y)es/(N)o): `);
|
|
|
|
|
|
if (confirm.toLowerCase() !== 'yes' && confirm.toLowerCase() !== 'y') {
|
|
console.log('\n❌ Aborted.');
|
|
rl.close();
|
|
return;
|
|
}
|
|
|
|
console.log('\n✅ Running selected validations...\n');
|
|
rl.close();
|
|
|
|
//==================== SECTION 1: NON-JSON FILE DETECTION ====================//
|
|
if (selectedSections.includes(1)) {
|
|
fs.readdir(domainsDir, (err, files) => {
|
|
if (err) {
|
|
console.error(`Error reading directory: ${err.message}`);
|
|
return;
|
|
}
|
|
|
|
files.forEach(file => {
|
|
if (file === 'reserved') {
|
|
console.log(`Ignoring reserved folder: ${file}`);
|
|
return;
|
|
}
|
|
|
|
if (!file.endsWith('.json')) {
|
|
console.log(`Non-JSON file found: ${file}`);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
//==================== SECTION 2: JSON SYNTAX VALIDATION ====================//
|
|
if (selectedSections.includes(2)) {
|
|
fs.readdir(domainsDir, (err, files) => {
|
|
if (err) {
|
|
console.error(`Error reading directory: ${err.message}`);
|
|
return;
|
|
}
|
|
|
|
files
|
|
.filter(file => file.endsWith('.json'))
|
|
.forEach(file => {
|
|
const filePath = path.join(domainsDir, file);
|
|
fs.readFile(filePath, 'utf8', (err, data) => {
|
|
if (err) {
|
|
console.error(`Error reading file ${file}: ${err.message}`);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
JSON.parse(data);
|
|
} catch (e) {
|
|
console.log(`Invalid JSON file: ${file}`);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
//==================== SECTION 3: OWNER PROPERTY VALIDATION ====================//
|
|
if (selectedSections.includes(3)) {
|
|
fs.readdir(domainsDir, (err, files) => {
|
|
if (err) {
|
|
console.error(`Error reading directory: ${err.message}`);
|
|
return;
|
|
}
|
|
|
|
files
|
|
.filter(file => file.endsWith('.json'))
|
|
.forEach(file => {
|
|
const filePath = path.join(domainsDir, file);
|
|
fs.readFile(filePath, 'utf8', (err, data) => {
|
|
if (err) {
|
|
console.error(`Error reading file ${file}: ${err.message}`);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const parsed = JSON.parse(data);
|
|
const owner = parsed.owner;
|
|
|
|
if (!owner || !owner.email) {
|
|
console.warn(`❌ Missing owner email in: ${file}`);
|
|
return;
|
|
}
|
|
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
if (!emailRegex.test(owner.email)) {
|
|
console.warn(`❌ Invalid owner email format in: ${file}`);
|
|
return;
|
|
}
|
|
|
|
if (owner.repo) {
|
|
const repoRegex = /^https:\/\/github\.com\/.+/;
|
|
if (!repoRegex.test(owner.repo)) {
|
|
console.warn(`❌ Invalid owner repo URL in: ${file}`);
|
|
return;
|
|
}
|
|
}
|
|
|
|
} catch (e) {
|
|
console.log(`❌ Cannot validate owner (invalid JSON) in: ${file}`);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
//==================== SECTION 4: FILENAME FORMAT VALIDATION ====================//
|
|
if (selectedSections.includes(4)) {
|
|
const validRootDomains = [
|
|
'is-a-fullstack.dev',
|
|
'is-cool.dev',
|
|
'is-local.org',
|
|
'is-not-a.dev',
|
|
'localplayer.dev'
|
|
];
|
|
|
|
fs.readdir(domainsDir, (err, files) => {
|
|
if (err) {
|
|
console.error(`Error reading directory: ${err.message}`);
|
|
return;
|
|
}
|
|
|
|
files
|
|
.filter(file => file.endsWith('.json'))
|
|
.forEach(file => {
|
|
const parts = file.split('.');
|
|
if (parts.length < 4) {
|
|
console.warn(`❌ Invalid domain format (missing parts): ${file}`);
|
|
return;
|
|
}
|
|
|
|
const expectedSuffix = validRootDomains.find(domain => file.endsWith(`${domain}.json`));
|
|
|
|
if (!expectedSuffix) {
|
|
console.warn(`❌ Invalid root domain in filename: ${file}`);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
//==================== SECTION 5: FILENAME CONTENT MATCH VALIDATION ====================//
|
|
if (selectedSections.includes(5)) {
|
|
fs.readdir(domainsDir, (err, files) => {
|
|
if (err) {
|
|
console.error(`Error reading directory: ${err.message}`);
|
|
return;
|
|
}
|
|
|
|
files
|
|
.filter(file => file.endsWith('.json'))
|
|
.forEach(file => {
|
|
const filePath = path.join(domainsDir, file);
|
|
fs.readFile(filePath, 'utf8', (err, data) => {
|
|
if (err) {
|
|
console.error(`Error reading file ${file}: ${err.message}`);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const parsed = JSON.parse(data);
|
|
const expectedFileName = `${parsed.subdomain}.${parsed.domain}.json`;
|
|
|
|
if (file !== expectedFileName) {
|
|
console.warn(`❌ Filename mismatch in: ${file}`);
|
|
console.warn(` ↪ Expected: ${expectedFileName}`);
|
|
}
|
|
} catch (e) {
|
|
console.log(`❌ Cannot parse JSON in: ${file}`);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
})(); |