mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-12 01:00:34 +08:00
Add build step to CDN domainset
This commit is contained in:
parent
9fde4a3866
commit
b43c1628d6
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@ node_modules
|
|||||||
public
|
public
|
||||||
|
|
||||||
List/domainset/reject.conf
|
List/domainset/reject.conf
|
||||||
|
List/domainset/cdn.conf
|
||||||
List/domainset/reject_phishing.conf
|
List/domainset/reject_phishing.conf
|
||||||
List/domainset/reject_sukka.conf
|
List/domainset/reject_sukka.conf
|
||||||
List/domainset/apple_cdn.conf
|
List/domainset/apple_cdn.conf
|
||||||
|
|||||||
@ -1,18 +1,28 @@
|
|||||||
const { fetchWithRetry } = require('./lib/fetch-retry');
|
// @ts-check
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { compareAndWriteFile } = require('./lib/string-array-compare');
|
const { compareAndWriteFile } = require('./lib/string-array-compare');
|
||||||
const { withBannerArray } = require('./lib/with-banner');
|
const { withBannerArray } = require('./lib/with-banner');
|
||||||
const { minifyRules } = require('./lib/minify-rules');
|
const { minifyRules } = require('./lib/minify-rules');
|
||||||
|
const { domainDeduper } = require('./lib/domain-deduper');
|
||||||
|
const { shouldIgnoreLine } = require('./lib/should-ignore-line');
|
||||||
|
const { fetchRemoteTextAndCreateReadlineInterface } = require('./lib/fetch-remote-text-by-line');
|
||||||
|
|
||||||
|
const readline = require('readline');
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
console.time('Total Time - build-cdn-conf');
|
console.time('Total Time - build-cdn-conf');
|
||||||
|
|
||||||
const domains = (await (await fetchWithRetry('https://publicsuffix.org/list/public_suffix_list.dat')).text()).split('\n');
|
/**
|
||||||
|
* Extract OSS domain from publicsuffix list
|
||||||
|
* @type {Set<string>}
|
||||||
|
*/
|
||||||
|
const S3OSSDomains = new Set();
|
||||||
|
|
||||||
const S3OSSDomains = domains.filter(line => {
|
for await (const line of await fetchRemoteTextAndCreateReadlineInterface('https://publicsuffix.org/list/public_suffix_list.dat')) {
|
||||||
if (line) {
|
if (
|
||||||
return (
|
line
|
||||||
|
&& (
|
||||||
line.startsWith('s3-')
|
line.startsWith('s3-')
|
||||||
|| line.startsWith('s3.')
|
|| line.startsWith('s3.')
|
||||||
)
|
)
|
||||||
@ -20,18 +30,16 @@ const { minifyRules } = require('./lib/minify-rules');
|
|||||||
line.endsWith('.amazonaws.com')
|
line.endsWith('.amazonaws.com')
|
||||||
|| line.endsWith('.scw.cloud')
|
|| line.endsWith('.scw.cloud')
|
||||||
)
|
)
|
||||||
&& !line.includes('cn-');
|
&& !line.includes('cn-')
|
||||||
|
) {
|
||||||
|
S3OSSDomains.add(line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
const content = (await fs.promises.readFile(path.resolve(__dirname, '../Source/non_ip/cdn.conf'), 'utf-8'))
|
||||||
});
|
|
||||||
|
|
||||||
const filePath = path.resolve(__dirname, '../Source/non_ip/cdn.conf');
|
|
||||||
const resultPath = path.resolve(__dirname, '../List/non_ip/cdn.conf');
|
|
||||||
const content = (await fs.promises.readFile(filePath, 'utf-8'))
|
|
||||||
.replace(
|
.replace(
|
||||||
'# --- [AWS S3 Replace Me] ---',
|
'# --- [AWS S3 Replace Me] ---',
|
||||||
S3OSSDomains.map(domain => `DOMAIN-SUFFIX,${domain}`).join('\n')
|
Array.from(S3OSSDomains).map(domain => `DOMAIN-SUFFIX,${domain}`).join('\n')
|
||||||
);
|
);
|
||||||
|
|
||||||
await compareAndWriteFile(
|
await compareAndWriteFile(
|
||||||
@ -47,7 +55,39 @@ const { minifyRules } = require('./lib/minify-rules');
|
|||||||
new Date(),
|
new Date(),
|
||||||
minifyRules(content.split('\n'))
|
minifyRules(content.split('\n'))
|
||||||
),
|
),
|
||||||
resultPath
|
path.resolve(__dirname, '../List/non_ip/cdn.conf')
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dedupe cdn.conf
|
||||||
|
*/
|
||||||
|
/** @type {Set<string>} */
|
||||||
|
const cdnDomains = new Set();
|
||||||
|
|
||||||
|
for await (const line of readline.createInterface({
|
||||||
|
input: fs.createReadStream(path.resolve(__dirname, '../Source/domainset/cdn.conf'), 'utf-8'),
|
||||||
|
crlfDelay: Infinity
|
||||||
|
})) {
|
||||||
|
const l = shouldIgnoreLine(line);
|
||||||
|
if (l) {
|
||||||
|
cdnDomains.add(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await compareAndWriteFile(
|
||||||
|
withBannerArray(
|
||||||
|
'Sukka\'s Surge Rules - CDN Domains',
|
||||||
|
[
|
||||||
|
'License: AGPL 3.0',
|
||||||
|
'Homepage: https://ruleset.skk.moe',
|
||||||
|
'GitHub: https://github.com/SukkaW/Surge',
|
||||||
|
'',
|
||||||
|
'This file contains object storage and static assets CDN domains.'
|
||||||
|
],
|
||||||
|
new Date(),
|
||||||
|
minifyRules(domainDeduper(Array.from(cdnDomains)))
|
||||||
|
),
|
||||||
|
path.resolve(__dirname, '../List/domainset/cdn.conf')
|
||||||
);
|
);
|
||||||
|
|
||||||
console.timeEnd('Total Time - build-cdn-conf');
|
console.timeEnd('Total Time - build-cdn-conf');
|
||||||
|
|||||||
@ -11,6 +11,7 @@ const Trie = require('./lib/trie');
|
|||||||
const { HOSTS, ADGUARD_FILTERS, PREDEFINED_WHITELIST, PREDEFINED_ENFORCED_BACKLIST } = require('./lib/reject-data-source');
|
const { HOSTS, ADGUARD_FILTERS, PREDEFINED_WHITELIST, PREDEFINED_ENFORCED_BACKLIST } = require('./lib/reject-data-source');
|
||||||
const { withBannerArray } = require('./lib/with-banner');
|
const { withBannerArray } = require('./lib/with-banner');
|
||||||
const { compareAndWriteFile } = require('./lib/string-array-compare');
|
const { compareAndWriteFile } = require('./lib/string-array-compare');
|
||||||
|
const { shouldIgnoreLine } = require('./lib/should-ignore-line');
|
||||||
|
|
||||||
/** Whitelists */
|
/** Whitelists */
|
||||||
const filterRuleWhitelistDomainSets = new Set(PREDEFINED_WHITELIST);
|
const filterRuleWhitelistDomainSets = new Set(PREDEFINED_WHITELIST);
|
||||||
@ -109,19 +110,10 @@ const domainSuffixSet = new Set();
|
|||||||
});
|
});
|
||||||
|
|
||||||
for await (const line of rl1) {
|
for await (const line of rl1) {
|
||||||
if (
|
const l = shouldIgnoreLine(line);
|
||||||
line.startsWith('#')
|
if (l) {
|
||||||
|| line.startsWith(' ')
|
domainSets.add(l);
|
||||||
|| line.startsWith('\r')
|
|
||||||
|| line.startsWith('\n')
|
|
||||||
) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const trimmed = line.trim();
|
|
||||||
if (trimmed === '') continue;
|
|
||||||
|
|
||||||
domainSets.add(trimmed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
previousSize = domainSets.size - previousSize;
|
previousSize = domainSets.size - previousSize;
|
||||||
@ -146,19 +138,10 @@ const domainSuffixSet = new Set();
|
|||||||
crlfDelay: Infinity
|
crlfDelay: Infinity
|
||||||
});
|
});
|
||||||
for await (const line of rl3) {
|
for await (const line of rl3) {
|
||||||
if (
|
const l = shouldIgnoreLine(line);
|
||||||
line.startsWith('#')
|
if (l) {
|
||||||
|| line.startsWith(' ')
|
domainSets.add(l);
|
||||||
|| line.startsWith('\r')
|
|
||||||
|| line.startsWith('\n')
|
|
||||||
) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const trimmed = line.trim();
|
|
||||||
if (trimmed === '') continue;
|
|
||||||
|
|
||||||
domainSuffixSet.add(trimmed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Import ${domainKeywordsSet.size} black keywords and ${domainSuffixSet.size} black suffixes!`);
|
console.log(`Import ${domainKeywordsSet.size} black keywords and ${domainSuffixSet.size} black suffixes!`);
|
||||||
|
|||||||
27
Build/lib/domain-deduper.js
Normal file
27
Build/lib/domain-deduper.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
const Trie = require('./trie');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} inputDomains
|
||||||
|
*/
|
||||||
|
const domainDeduper = (inputDomains) => {
|
||||||
|
const trie = Trie.from(inputDomains);
|
||||||
|
const sets = new Set(inputDomains);
|
||||||
|
|
||||||
|
for (let j = 0, len = inputDomains.length; j < len; j++) {
|
||||||
|
const d = inputDomains[j];
|
||||||
|
if (d[0] !== '.') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
trie.find(d, false).forEach(f => sets.delete(f));
|
||||||
|
|
||||||
|
const a = d.slice(1);
|
||||||
|
if (trie.has(a)) {
|
||||||
|
sets.delete(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(sets);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.domainDeduper = domainDeduper;
|
||||||
29
Build/lib/should-ignore-line.js
Normal file
29
Build/lib/should-ignore-line.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* eslint-disable camelcase -- cache index access */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} line
|
||||||
|
*/
|
||||||
|
module.exports.shouldIgnoreLine = (line) => {
|
||||||
|
if (line === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const line_0 = line[0];
|
||||||
|
|
||||||
|
if (
|
||||||
|
line_0 === '#'
|
||||||
|
|| line_0 === ' '
|
||||||
|
|| line_0 === '\r'
|
||||||
|
|| line_0 === '\n'
|
||||||
|
|| line_0 === '!'
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const trimmed = line.trim();
|
||||||
|
if (trimmed === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return trimmed;
|
||||||
|
};
|
||||||
@ -81,6 +81,7 @@ class Trie {
|
|||||||
$suffix = suffixStack.pop();
|
$suffix = suffixStack.pop();
|
||||||
node = nodeStack.pop();
|
node = nodeStack.pop();
|
||||||
|
|
||||||
|
// eslint-disable-next-line guard-for-in -- plain object
|
||||||
for (k in node) {
|
for (k in node) {
|
||||||
if (k === SENTINEL) {
|
if (k === SENTINEL) {
|
||||||
if (includeEqualWithSuffix) {
|
if (includeEqualWithSuffix) {
|
||||||
@ -89,7 +90,6 @@ class Trie {
|
|||||||
matches.push($suffix);
|
matches.push($suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,8 +161,9 @@ class Trie {
|
|||||||
node = node[token];
|
node = node[token];
|
||||||
|
|
||||||
// Prefix does not exist
|
// Prefix does not exist
|
||||||
if (typeof node === 'undefined')
|
if (typeof node === 'undefined') {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Keeping track of a potential branch to prune
|
// Keeping track of a potential branch to prune
|
||||||
if (toPrune !== null) {
|
if (toPrune !== null) {
|
||||||
@ -170,14 +171,11 @@ class Trie {
|
|||||||
toPrune = null;
|
toPrune = null;
|
||||||
tokenToPrune = null;
|
tokenToPrune = null;
|
||||||
}
|
}
|
||||||
}
|
} else if (Object.keys(node).length < 2) {
|
||||||
else {
|
|
||||||
if (Object.keys(node).length < 2) {
|
|
||||||
toPrune = parent;
|
toPrune = parent;
|
||||||
tokenToPrune = token;
|
tokenToPrune = token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!(SENTINEL in node)) return false;
|
if (!(SENTINEL in node)) return false;
|
||||||
|
|
||||||
@ -206,9 +204,10 @@ class Trie {
|
|||||||
token = suffix[i];
|
token = suffix[i];
|
||||||
node = node[token];
|
node = node[token];
|
||||||
|
|
||||||
if (typeof node === 'undefined')
|
if (typeof node === 'undefined') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return SENTINEL in node;
|
return SENTINEL in node;
|
||||||
}
|
}
|
||||||
@ -217,7 +216,7 @@ class Trie {
|
|||||||
* @return {string[]}
|
* @return {string[]}
|
||||||
*/
|
*/
|
||||||
dump() {
|
dump() {
|
||||||
let node = this.root;
|
const node = this.root;
|
||||||
const nodeStack = [];
|
const nodeStack = [];
|
||||||
const prefixStack = [];
|
const prefixStack = [];
|
||||||
// Resolving initial prefix
|
// Resolving initial prefix
|
||||||
@ -238,6 +237,7 @@ class Trie {
|
|||||||
currentNode = nodeStack.pop();
|
currentNode = nodeStack.pop();
|
||||||
currentPrefix = prefixStack.pop();
|
currentPrefix = prefixStack.pop();
|
||||||
|
|
||||||
|
// eslint-disable-next-line guard-for-in -- plain object
|
||||||
for (k in currentNode) {
|
for (k in currentNode) {
|
||||||
if (k === SENTINEL) {
|
if (k === SENTINEL) {
|
||||||
hasValue = true;
|
hasValue = true;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user