Files
cloudflare-gateway-pihole-s…/cf_list_create.js
T

151 lines
4.0 KiB
JavaScript

import { existsSync } from "fs";
import { resolve } from "path";
import {
createZeroTrustListsAtOnce,
createZeroTrustListsOneByOne,
} from "./lib/api.js";
import {
DRY_RUN,
FAST_MODE,
LIST_ITEM_LIMIT,
LIST_ITEM_SIZE,
PROCESSING_FILENAME,
} from "./lib/constants.js";
import { normalizeDomain } from "./lib/helpers.js";
import {
extractDomain,
isComment,
isValidDomain,
readFile,
} from "./lib/utils.js";
const allowlistFilename = existsSync(PROCESSING_FILENAME.OLD_ALLOWLIST)
? PROCESSING_FILENAME.OLD_ALLOWLIST
: PROCESSING_FILENAME.ALLOWLIST;
const blocklistFilename = existsSync(PROCESSING_FILENAME.OLD_BLOCKLIST)
? PROCESSING_FILENAME.OLD_BLOCKLIST
: PROCESSING_FILENAME.BLOCKLIST;
const allowlist = new Map();
const blocklist = new Map();
const domains = [];
let processedDomainCount = 0;
let unnecessaryDomainCount = 0;
let duplicateDomainCount = 0;
let allowedDomainCount = 0;
// Read allowlist
console.log(`Processing ${allowlistFilename}`);
await readFile(resolve(`./${allowlistFilename}`), (line) => {
const _line = line.trim();
if (!_line) return;
if (isComment(_line)) return;
const domain = normalizeDomain(_line, true);
if (!isValidDomain(domain)) return;
allowlist.set(domain, 1);
});
// Read blocklist
console.log(`Processing ${blocklistFilename}`);
await readFile(resolve(`./${blocklistFilename}`), (line, rl) => {
if (domains.length === LIST_ITEM_LIMIT) {
return;
}
const _line = line.trim();
if (!_line) return;
// Check if the current line is a comment in any format
if (isComment(_line)) return;
// Remove prefixes and suffixes in hosts, wildcard or adblock format
const domain = normalizeDomain(_line);
// Check if it is a valid domain which is not a URL or does not contain
// characters like * in the middle of the domain
if (!isValidDomain(domain)) return;
processedDomainCount++;
// Get all the levels of the domain and check from the highest
// because we are blocking all subdomains
// Example: fourth.third.example.com => ["example.com", "third.example.com", "fourth.third.example.com"]
const anyDomainExists = extractDomain(domain)
.reverse()
.some((item) => {
if (blocklist.has(item)) {
if (item === domain) {
// The exact domain is already blocked
console.log(`Found ${item} in blocklist already - Skipping`);
duplicateDomainCount++;
} else {
// The higher-level domain is already blocked
// so it's not necessary to block this domain
console.log(
`Found ${item} in blocklist already - Skipping ${domain}`
);
unnecessaryDomainCount++;
}
return true;
}
return false;
});
if (anyDomainExists) return;
if (allowlist.has(domain)) {
console.log(`Found ${domain} in allowlist - Skipping`);
allowedDomainCount++;
return;
}
blocklist.set(domain, 1);
domains.push(domain);
if (domains.length === LIST_ITEM_LIMIT) {
console.log(
"Maximum number of blocked domains reached - Stopping processing blocklist..."
);
rl.close();
}
});
const numberOfLists = Math.ceil(domains.length / LIST_ITEM_SIZE);
console.log("\n\n");
console.log(`Number of processed domains: ${processedDomainCount}`);
console.log(`Number of duplicate domains: ${duplicateDomainCount}`);
console.log(`Number of unnecessary domains: ${unnecessaryDomainCount}`);
console.log(`Number of blocked domains: ${domains.length}`);
console.log(`Number of allowed domains: ${allowedDomainCount}`);
console.log(`Number of lists to be created: ${numberOfLists}`);
console.log("\n\n");
(async () => {
if (DRY_RUN) {
console.log(
"Dry run complete - no lists were created. If this was not intended, please remove the DRY_RUN environment variable and try again."
);
return;
}
console.log(
`Creating ${numberOfLists} lists for ${domains.length} domains...`
);
if (FAST_MODE) {
await createZeroTrustListsAtOnce(domains);
return;
}
await createZeroTrustListsOneByOne(domains);
})();