diff --git a/Build/build-anti-bogus-domain.js b/Build/build-anti-bogus-domain.js deleted file mode 100644 index 3f8759d61..000000000 --- a/Build/build-anti-bogus-domain.js +++ /dev/null @@ -1,30 +0,0 @@ -const { fetchWithRetry } = require('./lib/fetch-retry'); -const fs = require('fs'); -const path = require('path'); -const { isIP } = require('net'); - -(async () => { - console.time('Total Time - build-anti-bogus-domain'); - console.time('* Download bogus-nxdomain-list') - const res = (await (await fetchWithRetry('https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/bogus-nxdomain.china.conf')).text()) - .split('\n') - .map(line => { - if (line.startsWith('bogus-nxdomain=')) { - return line.replace('bogus-nxdomain=', ''); - } - - return null - }) - .filter(ip => typeof ip === 'string' && isIP(ip) !== 0); - console.timeEnd('* Download bogus-nxdomain-list') - - const filePath = path.resolve(__dirname, '../List/ip/reject.conf'); - const content = (await fs.promises.readFile(filePath, 'utf-8')) - .replace( - '# --- [Anti Bogus Domain Replace Me] ---', - res.map(ip => `IP-CIDR,${ip}/32,no-resolve`).join('\n') - ); - - await fs.promises.writeFile(filePath, content, 'utf-8'); - console.timeEnd('Total Time - build-anti-bogus-domain'); -})(); diff --git a/Build/build-apple-cdn.js b/Build/build-apple-cdn.js deleted file mode 100644 index 0e472a23a..000000000 --- a/Build/build-apple-cdn.js +++ /dev/null @@ -1,35 +0,0 @@ -const { fetchWithRetry } = require('./lib/fetch-retry'); -const fs = require('fs'); -const path = require('path'); - -const rDomain = /^(((?!\-))(xn\-\-)?[a-z0-9\-_]{0,61}[a-z0-9]{1,1}\.)*(xn\-\-)?([a-z0-9\-]{1,61}|[a-z0-9\-]{1,30})\.[a-z]{2,}$/m; - -(async () => { - console.time('Total Time - build-apple-cdn-conf'); - - const res = (await (await fetchWithRetry('https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/apple.china.conf')).text()) - .split('\n') - .map(line => { - if (line.startsWith('server=/') && line.endsWith('/114.114.114.114')) { - return line.replace('server=/', '').replace('/114.114.114.114', ''); - } - - return null - }) - .filter(domain => typeof domain === 'string' && rDomain.test(domain)); - - await Promise.all([ - fs.promises.writeFile( - path.resolve(__dirname, '../List/non_ip/apple_cdn.conf'), - res.map(domain => `DOMAIN-SUFFIX,${domain}`).join('\n') + '\n', - 'utf-8' - ), - fs.promises.writeFile( - path.resolve(__dirname, '../List/domainset/apple_cdn.conf'), - res.map(i => `.${i}`).join('\n') + '\n', - 'utf-8' - ) - ]) - - console.timeEnd('Total Time - build-apple-cdn-conf'); -})(); diff --git a/Build/build-cdn-conf.js b/Build/build-cdn-conf.js deleted file mode 100644 index 94268718e..000000000 --- a/Build/build-cdn-conf.js +++ /dev/null @@ -1,36 +0,0 @@ -const { fetchWithRetry } = require('./lib/fetch-retry'); -const fs = require('fs'); -const path = require('path'); - -(async () => { - console.time('Total Time - build-cdn-conf'); - - const domains = (await (await fetchWithRetry('https://publicsuffix.org/list/public_suffix_list.dat')).text()).split('\n'); - - const S3OSSDomains = domains.filter(line => { - if (line) { - return ( - line.startsWith('s3-') - || line.startsWith('s3.') - ) - && ( - line.endsWith('.amazonaws.com') - || line.endsWith('.scw.cloud') - ) - && !line.includes('cn-') - } - - return false; - }) - - const filePath = path.resolve(__dirname, '../List/non_ip/cdn.conf'); - const content = (await fs.promises.readFile(filePath, 'utf-8')) - .replace( - '# --- [AWS S3 Replace Me] ---', - S3OSSDomains.map(domain => `DOMAIN-SUFFIX,${domain}`).join('\n') - ); - - await fs.promises.writeFile(filePath, content, 'utf-8'); - - console.timeEnd('Total Time - build-cdn-conf'); -})(); diff --git a/Build/build-chn-cidr.js b/Build/build-chn-cidr.js deleted file mode 100644 index 777e6d802..000000000 --- a/Build/build-chn-cidr.js +++ /dev/null @@ -1,32 +0,0 @@ -const { fetchWithRetry } = require('./lib/fetch-retry'); -const { promises: fsPromises } = require('fs'); -const { resolve: pathResolve } = require('path'); - -(async () => { - console.time('Total Time - build-chnroutes-cidr'); - - const cidr = (await (await fetchWithRetry('https://raw.githubusercontent.com/misakaio/chnroutes2/master/chnroutes.txt')).text()).split('\n'); - - const filteredCidr = cidr.filter(line => { - if (line) { - return !line.startsWith('#') - } - - return false; - }) - - await fsPromises.writeFile(pathResolve(__dirname, '../List/ip/china_ip.conf'), makeCidrList(filteredCidr), { encoding: 'utf-8' }); - - console.timeEnd('Total Time - build-chnroutes-cidr'); -})(); - -function makeCidrList(cidr) { - const date = new Date(); - - return `############################ -# Mainland China IPv4 CIDR -# Data from misaka.io (misakaio @ GitHub) -# Last Updated: ${date.toISOString()} -# Routes: ${cidr.length} -############################\n` + cidr.map(i => `IP-CIDR,${i}`).join('\n') + '\n########### END ############\n'; -}; diff --git a/Build/build-index.html.js b/Build/build-index.html.js deleted file mode 100644 index 2e65aa158..000000000 --- a/Build/build-index.html.js +++ /dev/null @@ -1,59 +0,0 @@ -const listDir = require('@sukka/listdir'); -const path = require('path'); -const fs = require('fs'); - -const rootPath = path.resolve(__dirname, '../'); - -(async () => { - const list = await listDir(rootPath, { - ignoreHidden: true, - ignorePattern: /node_modules|Build|.DS_Store|\.(json|html|md|js)|LICENSE/ - }); - - const html = template(list); - - await fs.promises.writeFile(path.join(rootPath, 'index.html'), html, 'utf-8'); -})(); - -/** - * @param {string[]} urlList - * @returns {string} - */ -function template(urlList) { - return ` - - - - - Surge Ruleset Server | Sukka (@SukkaW) - - - - - - - - - - - - - - - - - -
-

Sukka Surge Ruleset Server

-

Made by Sukka | Source @ GitHub | Licensed under AGPL-3.0

-

Last Updated: ${new Date().toISOString()}

-
-
- -
- - - ` -} diff --git a/Build/build-mitm-hostname.js b/Build/build-mitm-hostname.js deleted file mode 100644 index 7a9eecd17..000000000 --- a/Build/build-mitm-hostname.js +++ /dev/null @@ -1,190 +0,0 @@ -const fsPromises = require('fs').promises; -const pathFn = require('path'); -const table = require('table'); -const listDir = require('@sukka/listdir'); -const { green, yellow } = require('picocolors'); - -const PRESET_MITM_HOSTNAMES = [ - // '*baidu.com', - '*ydstatic.com', - // '*snssdk.com', - '*musical.com', - // '*musical.ly', - // '*snssdk.ly', - 'api.chelaile.net.cn', - 'atrace.chelaile.net.cn', - '*.meituan.net', - 'ctrl.playcvn.com', - 'ctrl.playcvn.net', - 'ctrl.zmzapi.com', - 'ctrl.zmzapi.net', - 'api.zhuishushenqi.com', - 'b.zhuishushenqi.com', - '*.music.126.net', - '*.prod.hosts.ooklaserver.net' -]; - -(async () => { - const folderListPath = pathFn.resolve(__dirname, '../List/'); - const rulesets = await listDir(folderListPath); - let urlRegexPaths = []; - - urlRegexPaths.push( - ...(await fsPromises.readFile(pathFn.join(__dirname, '../Modules/sukka_url_rewrite.sgmodule'), { encoding: 'utf-8' })) - .split('\n') - .filter( - i => !i.startsWith('#') - && !i.startsWith('[') - ) - .map(i => i.split(' ')[0]) - .map(i => ({ - origin: i, - processed: i - .replaceAll('(www.)?', '{www or not}') - .replaceAll('^https?://', '') - .replaceAll('^https://', '') - .replaceAll('^http://', '') - .split('/')[0] - .replaceAll('\\.', '.') - .replaceAll('.+', '*') - .replaceAll('(.*)', '*') - })) - ); - - const bothWwwApexDomains = []; - urlRegexPaths = urlRegexPaths.map(i => { - if (!i.processed.includes('{www or not}')) return i; - - const d = i.processed.replace('{www or not}', ''); - bothWwwApexDomains.push({ - origin: i.origin, - processed: `www.${d}` - }); - - return { - origin: i.origin, - processed: d - }; - }); - - urlRegexPaths.push(...bothWwwApexDomains); - - await Promise.all(rulesets.map(async file => { - const content = (await fsPromises.readFile(pathFn.join(folderListPath, file), { encoding: 'utf-8' })).split('\n'); - urlRegexPaths.push( - ...content - .filter(i => i.startsWith('URL-REGEX')) - .map(i => i.split(',')[1]) - .map(i => ({ - origin: i, - processed: i - .replaceAll('^https?://', '') - .replaceAll('^https://', '') - .replaceAll('^http://', '') - .replaceAll('\\.', '.') - .replaceAll('.+', '*') - .replaceAll('\\d', '*') - .replaceAll('([a-z])', '*') - .replaceAll('[a-z]', '*') - .replaceAll('([0-9])', '*') - .replaceAll('[0-9]', '*') - .replaceAll(/{.+?}/g, '') - .replaceAll(/\*+/g, '*') - })) - ); - })); - - let mitmDomains = new Set(PRESET_MITM_HOSTNAMES); // Special case for parsed failed - const parsedFailures = new Set(); - - const dedupedUrlRegexPaths = [...new Set(urlRegexPaths)]; - - dedupedUrlRegexPaths.forEach(i => { - const result = parseDomain(i.processed); - - if (result.success) { - mitmDomains.add(result.hostname.trim()); - } else { - parsedFailures.add(i.origin); - } - }); - - mitmDomains = [...mitmDomains].filter(i => { - return i.length > 3 - && !i.includes('.mp4') // Special Case - && i !== '(www.)' // Special Case - && !(i !== '*.meituan.net' && i.endsWith('.meituan.net')) - && !i.startsWith('.') - && !i.endsWith('.') - && !i.endsWith('*') - }); - - const mitmDomainsRegExpArray = mitmDomains.map(i => { - return new RegExp( - escapeRegExp(i) - .replaceAll('{www or not}', '(www.)?') - .replaceAll('\\*', '(.*)') - ) - }); - - const parsedDomainsData = []; - dedupedUrlRegexPaths.forEach(i => { - const result = parseDomain(i.processed); - - if (result.success) { - if (matchWithRegExpArray(result.hostname.trim(), mitmDomainsRegExpArray)) { - parsedDomainsData.push([green(result.hostname), i.origin]); - } else { - parsedDomainsData.push([yellow(result.hostname), i.origin]); - } - } - }); - - console.log('Mitm Hostnames:'); - console.log('hostname = %APPEND% ' + mitmDomains.join(', ')); - console.log('--------------------'); - console.log('Parsed Sucessed:'); - console.log(table.table(parsedDomainsData, { - border: table.getBorderCharacters('void'), - columnDefault: { - paddingLeft: 0, - paddingRight: 3 - }, - drawHorizontalLine: () => false - })); - console.log('--------------------'); - console.log('Parsed Failed'); - console.log([...parsedFailures].join('\n')); -})(); - -/** Util function */ -function parseDomain(input) { - try { - const url = new URL(`https://${input}`); - return { - success: true, - hostname: url.hostname - } - } catch { - return { - success: false - } - } -} - -function matchWithRegExpArray(input, regexps = []) { - for (const r of regexps) { - if (r.test(input)) return true; - } - - return false; -} - -function escapeRegExp(string = '') { - const reRegExpChar = /[\\^$.*+?()[\]{}|]/g; - const reHasRegExpChar = RegExp(reRegExpChar.source); - - return string && reHasRegExpChar.test(string) - ? string.replace(reRegExpChar, '\\$&') - : string; -} diff --git a/Build/build-phishing-domainset.js b/Build/build-phishing-domainset.js deleted file mode 100644 index 256b600e6..000000000 --- a/Build/build-phishing-domainset.js +++ /dev/null @@ -1,73 +0,0 @@ -const psl = require('psl'); -const { processFilterRules } = require('./lib/parse-filter.js'); -const fs = require('fs'); -const path = require('path'); - -const WHITELIST_DOMAIN = new Set([]); -const BLACK_TLD = [ - '.xyz', - '.top', - '.win', - '.vip', - '.site', - '.space', - '.online', - '.icu', - '.fun', - '.shop', - '.cool', - '.cyou', - '.id', - '.pro' -]; - -(async () => { - const domainSet = Array.from( - ( - await processFilterRules('https://curbengh.github.io/phishing-filter/phishing-filter-agh.txt') - ).black - ); - const domainCountMap = {}; - - for (let i = 0, len = domainSet.length; i < len; i++) { - const line = domainSet[i]; - // starts with # - if (line.charCodeAt(0) === 35) { - continue; - } - if (line.trim().length === 0) { - continue; - } - - const domain = line.charCodeAt(0) === 46 ? line.slice(1) : line; - - if (line.length > 25) { - const parsed = psl.parse(domain); - - if (parsed.input === parsed.tld) { - continue; - } - const apexDomain = parsed.domain - - if (WHITELIST_DOMAIN.has(apexDomain)) { - continue; - } - - domainCountMap[apexDomain] ||= 0; - domainCountMap[apexDomain] += 1; - } - } - - const results = []; - Object.entries(domainCountMap).forEach(([domain, count]) => { - if ( - count >= 8 - && BLACK_TLD.some(tld => domain.endsWith(tld)) - ) { - results.push('.' + domain); - } - }); - - const filePath = path.resolve(__dirname, '../List/domainset/reject_phishing.conf'); - await fs.promises.writeFile(filePath, results.join('\n'), 'utf-8'); -})(); diff --git a/Build/build-reject-domainset.js b/Build/build-reject-domainset.js deleted file mode 100644 index a11d30087..000000000 --- a/Build/build-reject-domainset.js +++ /dev/null @@ -1,330 +0,0 @@ -const { promises: fsPromises } = require('fs'); -const { resolve: pathResolve } = require('path'); -const Piscina = require('piscina'); -const { processHosts, processFilterRules, preprocessFullDomainSetBeforeUsedAsWorkerData } = require('./lib/parse-filter'); -const cpuCount = require('os').cpus().length; -const { isCI } = require('ci-info'); -const threads = isCI ? cpuCount : cpuCount / 2; - -(async () => { - console.time('Total Time - build-reject-domain-set'); - - /** @type Set */ - const domainSets = new Set(); - - console.log('Downloading hosts file...'); - console.time('* Download and process Hosts'); - - // Parse from remote hosts & domain lists - (await Promise.all([ - processHosts('https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext', true), - processHosts('https://raw.githubusercontent.com/hoshsadiq/adblock-nocoin-list/master/hosts.txt'), - processHosts('https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt') - ])).forEach(hosts => { - hosts.forEach(host => { - if (host) { - domainSets.add(host); - } - }); - }); - - console.timeEnd('* Download and process Hosts'); - - let previousSize = domainSets.size; - console.log(`Import ${previousSize} rules from hosts files!`); - - await fsPromises.readFile(pathResolve(__dirname, '../List/domainset/reject_sukka.conf'), { encoding: 'utf-8' }).then(data => { - data.split('\n').forEach(line => { - const trimmed = line.trim(); - if ( - line.startsWith('#') - || line.startsWith(' ') - || line.startsWith('\r') - || line.startsWith('\n') - || trimmed === '' - ) { - return; - } - - /* if (domainSets.has(line) || domainSets.has(`.${line}`)) { - console.warn(`|${line}| is already in the list!`); - } */ - domainSets.add(trimmed); - }); - }); - - previousSize = domainSets.size - previousSize; - console.log(`Import ${previousSize} rules from reject_sukka.conf!`); - - // Parse from AdGuard Filters - /** @type Set */ - const filterRuleWhitelistDomainSets = new Set([ - 'localhost', - 'broadcasthost', - 'ip6-loopback', - 'ip6-localnet', - 'ip6-mcastprefix', - 'ip6-allnodes', - 'ip6-allrouters', - 'ip6-allhosts', - 'mcastprefix', - 'skk.moe', - 'analytics.google.com', - 'msa.cdn.mediaset.net', // Added manually using DOMAIN-KEYWORDS - 'cloud.answerhub.com', - 'ae01.alicdn.com', - 'whoami.akamai.net', - 'whoami.ds.akahelp.net', - 'pxlk9.net.', // This one is malformed from EasyList, which I will manually add instead - 'instant.page', // No, it doesn't violate anyone's privacy. I will whitelist it - 'piwik.pro', - 'mixpanel.com', - 'cdn.mxpnl.com', - 'heapanalytics.com', - 'segment.com', - 'segmentify.com', - 't.co', // pgl yoyo add t.co to the blacklist - 'survicate.com', // AdGuardDNSFilter - 'perfops.io', // AdGuardDNSFilter - 'd2axgrpnciinw7.cloudfront.net', // ADGuardDNSFilter - 'tb-lb.sb-cd.com', // AdGuard - 'storage.yandexcloud.net', // phishing list - 'login.microsoftonline.com' // phishing list - ]); - - console.time('* Download and process AdBlock Filter Rules'); - (await Promise.all([ - // Easy List - [ - 'https://easylist.to/easylist/easylist.txt', - [ - 'https://easylist-downloads.adblockplus.org/easylist.txt', - 'https://raw.githubusercontent.com/easylist/easylist/gh-pages/easylist.txt', - 'https://secure.fanboy.co.nz/easylist.txt' - ] - ], - // AdGuard DNS Filter - 'https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt', - // uBlock Origin Filter List - 'https://ublockorigin.github.io/uAssetsCDN/filters/filters.txt', - 'https://ublockorigin.github.io/uAssetsCDN/filters/filters-2020.txt', - 'https://ublockorigin.github.io/uAssetsCDN/filters/filters-2021.txt', - 'https://ublockorigin.github.io/uAssetsCDN/filters/filters-2022.txt', - // uBlock Origin Badware Risk List - 'https://ublockorigin.github.io/uAssets/filters/badware.txt', - // uBlock Origin Privacy List - 'https://ublockorigin.github.io/uAssets/filters/privacy.txt', - // uBlock Origin Resource Abuse - 'https://ublockorigin.github.io/uAssets/filters/resource-abuse.txt', - // uBlock Origin Unbreak - 'https://ublockorigin.github.io/uAssets/filters/unbreak.txt', - // AdGuard Base Filter - 'https://filters.adtidy.org/extension/ublock/filters/2_without_easylist.txt', - // AdGuard Mobile AD - 'https://filters.adtidy.org/extension/ublock/filters/11.txt', - // AdGuard Tracking Protection - 'https://filters.adtidy.org/extension/ublock/filters/3.txt', - // AdGuard Japanese filter - 'https://filters.adtidy.org/extension/ublock/filters/7.txt', - // AdGuard Chinese filter (EasyList China + AdGuard Chinese filter) - 'https://filters.adtidy.org/extension/ublock/filters/224.txt', - // Easy Privacy - [ - 'https://easylist.to/easylist/easyprivacy.txt', - [ - 'https://secure.fanboy.co.nz/easyprivacy.txt', - 'https://raw.githubusercontent.com/easylist/easylist/gh-pages/easyprivacy.txt', - 'https://easylist-downloads.adblockplus.org/easyprivacy.txt' - ] - ], - // Curben's UrlHaus Malicious URL Blocklist - // Prefer mirror, since malware-filter.gitlab.io has not been updated for a while - 'https://curbengh.github.io/urlhaus-filter/urlhaus-filter-agh-online.txt', - // [ - // 'https://malware-filter.pages.dev/urlhaus-filter-agh-online.txt', - // [ - // 'https://malware-filter.gitlab.io/urlhaus-filter/urlhaus-filter-agh-online.txt' - // ] - // ], - // Curben's Phishing URL Blocklist - // Prefer mirror, since malware-filter.gitlab.io has not been updated for a while - 'https://curbengh.github.io/phishing-filter/phishing-filter-agh.txt', - // [ - // 'https://phishing-filter.pages.dev/phishing-filter-agh.txt', - // [ - // 'https://malware-filter.gitlab.io/malware-filter/phishing-filter-agh.txt' - // ] - // ], - // Curben's PUP Domains Blocklist - 'https://curbengh.github.io/pup-filter/pup-filter-agh.txt', - // Prefer mirror, since malware-filter.gitlab.io has not been updated for a while - // [ - // 'https://pup-filter.pages.dev/pup-filter-agh.txt', - // [ - // 'https://malware-filter.gitlab.io/malware-filter/pup-filter-agh.txt' - // ] - // ], - // GameConsoleAdblockList - 'https://raw.githubusercontent.com/DandelionSprout/adfilt/master/GameConsoleAdblockList.txt', - // PiHoleBlocklist - 'https://raw.githubusercontent.com/Perflyst/PiHoleBlocklist/master/SmartTV-AGH.txt', - // Spam404 - 'https://raw.githubusercontent.com/Spam404/lists/master/adblock-list.txt' - ].map(input => { - if (typeof input === 'string') { - return processFilterRules(input); - } - if (Array.isArray(input) && input.length === 2) { - return processFilterRules(input[0], input[1]); - } - }))).forEach(({ white, black }) => { - white.forEach(i => filterRuleWhitelistDomainSets.add(i)); - black.forEach(i => domainSets.add(i)); - }); - - console.timeEnd('* Download and process AdBlock Filter Rules'); - - previousSize = domainSets.size - previousSize; - console.log(`Import ${previousSize} rules from adguard filters!`); - - // Read DOMAIN Keyword - const domainKeywordsSet = new Set(); - const domainSuffixSet = new Set(); - await fsPromises.readFile(pathResolve(__dirname, '../List/non_ip/reject.conf'), { encoding: 'utf-8' }).then(data => { - data.split('\n').forEach(line => { - if (line.startsWith('DOMAIN-KEYWORD')) { - const [, ...keywords] = line.split(','); - domainKeywordsSet.add(keywords.join(',').trim()); - } else if (line.startsWith('DOMAIN-SUFFIX')) { - const [, ...keywords] = line.split(','); - domainSuffixSet.add(keywords.join(',').trim()); - } - }); - }); - - // Read Special Phishing Suffix list - await fsPromises.readFile(pathResolve(__dirname, '../List/domainset/reject_phishing.conf'), { encoding: 'utf-8' }).then(data => { - data.split('\n').forEach(line => { - const trimmed = line.trim(); - if ( - line.startsWith('#') - || line.startsWith(' ') - || line.startsWith('\r') - || line.startsWith('\n') - || trimmed === '' - ) { - return; - } - - /* if (domainSets.has(line) || domainSets.has(`.${line}`)) { - console.warn(`|${line}| is already in the list!`); - } */ - domainSuffixSet.add(trimmed); - }); - }); - - console.log(`Import ${domainKeywordsSet.size} black keywords and ${domainSuffixSet.size} black suffixes!`); - - previousSize = domainSets.size; - // Dedupe domainSets - console.log(`Start deduping from black keywords/suffixes! (${previousSize})`); - console.time(`* Dedupe from black keywords/suffixes`); - - for (const domain of domainSets) { - let isTobeRemoved = false; - - for (const keyword of domainKeywordsSet) { - if (domain.includes(keyword)) { - isTobeRemoved = true; - break; - } - } - - if (!isTobeRemoved) { - for (const suffix of domainSuffixSet) { - if (domain.endsWith(suffix)) { - isTobeRemoved = true; - break; - } - } - } - - if (!isTobeRemoved) { - for (const white of filterRuleWhitelistDomainSets) { - if (domain.includes(white) || white.includes(domain)) { - isTobeRemoved = true; - break; - } - } - } - - if (isTobeRemoved) { - domainSets.delete(domain); - } - } - - console.timeEnd(`* Dedupe from black keywords/suffixes`); - console.log(`Deduped ${previousSize} - ${domainSets.size} = ${previousSize - domainSets.size} from black keywords and suffixes!`); - - previousSize = domainSets.size; - // Dedupe domainSets - console.log(`Start deduping! (${previousSize})`); - - const START_TIME = Date.now(); - - const piscina = new Piscina({ - filename: pathResolve(__dirname, 'worker/build-reject-domainset-worker.js'), - workerData: preprocessFullDomainSetBeforeUsedAsWorkerData([...domainSets]), - idleTimeout: 50, - minThreads: threads, - maxThreads: threads - }); - - console.log(`Launching ${threads} threads...`) - - const tasksArray = Array.from(domainSets) - .reduce((result, element, index) => { - const chunk = index % threads; - result[chunk] ??= []; - - result[chunk].push(element); - return result; - }, []); - - ( - await Promise.all( - Array.from(domainSets) - .reduce((result, element, index) => { - const chunk = index % threads; - result[chunk] ??= []; - result[chunk].push(element); - return result; - }, []) - .map(chunk => piscina.run({ chunk }, { name: 'dedupe' })) - ) - ).forEach((result, taskIndex) => { - const chunk = tasksArray[taskIndex]; - result.forEach((value, index) => { - if (value === 1) { - domainSets.delete(chunk[index]) - } - }) - }); - - console.log(`* Dedupe from covered subdomain - ${(Date.now() - START_TIME) / 1000}s`); - console.log(`Deduped ${previousSize - domainSets.size} rules!`); - - await Promise.all([ - fsPromises.writeFile( - pathResolve(__dirname, '../List/domainset/reject.conf'), - `${[...domainSets].join('\n')}\n`, - { encoding: 'utf-8' } - ), - piscina.destroy() - ]); - - console.timeEnd('Total Time - build-reject-domain-set'); - if (piscina.queueSize === 0) { - process.exit(0); - } -})(); diff --git a/Build/build-telegram-cidr.js b/Build/build-telegram-cidr.js deleted file mode 100644 index 12b4422f7..000000000 --- a/Build/build-telegram-cidr.js +++ /dev/null @@ -1,34 +0,0 @@ -const { fetchWithRetry } = require('./lib/fetch-retry'); -const fs = require('fs'); -const path = require('path'); -const { isIPv4, isIPv6 } = require('net'); - -(async () => { - console.time('Total Time - build-telegram-cidr'); - - const resp = await fetchWithRetry('https://core.telegram.org/resources/cidr.txt'); - const lastModified = new Date(resp.headers.get('last-modified')); - - const res = (await resp.text()) - .split('\n') - .filter(line => line.trim() !== ''); - - await fs.promises.writeFile( - path.resolve(__dirname, '../List/ip/telegram.conf'), - '# Telegram CIDR (https://core.telegram.org/resources/cidr.txt)' + '\n' + - '# Last Updated: ' + lastModified.toISOString() + '\n' + - res.map(ip => { - const [subnet] = ip.split('/'); - if (isIPv4(subnet)) { - return `IP-CIDR,${ip},no-resolve`; - } - if (isIPv6(subnet)) { - return `IP-CIDR6,${ip},no-resolve`; - } - return ''; - }).join('\n') + '\n', - 'utf-8' - ); - - console.timeEnd('Total Time - build-telegram-cidr'); -})(); diff --git a/Build/lib/fetch-retry.js b/Build/lib/fetch-retry.js deleted file mode 100644 index 13c8a8ee1..000000000 --- a/Build/lib/fetch-retry.js +++ /dev/null @@ -1,3 +0,0 @@ -const { fetch } = require('undici'); -const fetchWithRetry = require('@vercel/fetch-retry')(fetch); -module.exports.fetchWithRetry = fetchWithRetry; diff --git a/Build/lib/parse-filter.js b/Build/lib/parse-filter.js deleted file mode 100644 index 0338c5bf4..000000000 --- a/Build/lib/parse-filter.js +++ /dev/null @@ -1,248 +0,0 @@ -const { isIP } = require('net'); -const { fetchWithRetry } = require('./fetch-retry'); - -const rDomain = /^(((?!\-))(xn\-\-)?[a-z0-9\-_]{0,61}[a-z0-9]{1,1}\.)*(xn\-\-)?([a-z0-9\-]{1,61}|[a-z0-9\-]{1,30})\.[a-z]{2,}$/m - -const DEBUG_DOMAIN_TO_FIND = null; // example.com | null - -const warnOnceUrl = new Set(); -const warnOnce = (url, isWhite, ...message) => { - const key = `${url}${isWhite ? 'white' : 'black'}`; - if (warnOnceUrl.has(key)) { - return; - } - warnOnceUrl.add(key); - console.warn(url, isWhite ? '(white)' : '(black)', ...message); -} - -/** - * @param {string | URL} domainListsUrl - */ -async function processDomainLists (domainListsUrl) { - if (typeof domainListsUrl === 'string') { - domainListsUrl = new URL(domainListsUrl); - } - - /** @type Set */ - const domainSets = new Set(); - /** @type string[] */ - const domains = (await (await fetchWithRetry(domainListsUrl)).text()).split('\n'); - domains.forEach(line => { - if ( - line.startsWith('#') - || line.startsWith('!') - || line.startsWith(' ') - || line === '' - || line.startsWith('\r') - || line.startsWith('\n') - ) { - return; - } - - const domainToAdd = line.trim(); - - if (DEBUG_DOMAIN_TO_FIND && domainToAdd.includes(DEBUG_DOMAIN_TO_FIND)) { - warnOnce(domainListsUrl.toString(), false, DEBUG_DOMAIN_TO_FIND); - } - - domainSets.add(domainToAdd); - }); - - return [...domainSets]; -} - -/** - * @param {string | URL} hostsUrl - */ -async function processHosts (hostsUrl, includeAllSubDomain = false) { - console.time(` - processHosts: ${hostsUrl}`); - - if (typeof hostsUrl === 'string') { - hostsUrl = new URL(hostsUrl); - } - - /** @type Set */ - const domainSets = new Set(); - - /** @type string[] */ - const hosts = (await (await fetchWithRetry(hostsUrl)).text()).split('\n'); - hosts.forEach(line => { - if (line.includes('#')) { - return; - } - if (line.startsWith(' ') || line.startsWith('\r') || line.startsWith('\n') || line.trim() === '') { - return; - } - const [, ...domains] = line.split(' '); - const domain = domains.join(' ').trim(); - - if (DEBUG_DOMAIN_TO_FIND && domain.includes(DEBUG_DOMAIN_TO_FIND)) { - warnOnce(hostsUrl.toString(), false, DEBUG_DOMAIN_TO_FIND); - } - - if (rDomain.test(domain)) { - if (includeAllSubDomain) { - domainSets.add(`.${domain}`); - } else { - domainSets.add(domain); - } - } - }); - - console.timeEnd(` - processHosts: ${hostsUrl}`); - - return [...domainSets]; -} - -/** - * @param {string | URL} filterRulesUrl - * @param {(string | URL)[] | undefined} fallbackUrls - * @returns {Promise<{ white: Set, black: Set }>} - */ -async function processFilterRules (filterRulesUrl, fallbackUrls) { - console.time(` - processFilterRules: ${filterRulesUrl}`); - - /** @type Set */ - const whitelistDomainSets = new Set(); - /** @type Set */ - const blacklistDomainSets = new Set(); - - let filterRules; - try { - /** @type string[] */ - filterRules = ( - await Promise.any( - [filterRulesUrl, ...(fallbackUrls || [])].map( - async url => (await fetchWithRetry(url)).text() - ) - ) - ).split('\n').map(line => line.trim()); - } catch (e) { - console.log('Download Rule for [' + filterRulesUrl + '] failed'); - throw e; - } - - filterRules.forEach(line => { - const lineStartsWithDoubleVerticalBar = line.startsWith('||'); - - if ( - line === '' - || line.includes('#') - || line.includes('!') - || line.includes('*') - || line.includes('/') - || line.includes('[') - || line.includes('$') && !lineStartsWithDoubleVerticalBar - || line === '' - || isIP(line) !== 0 - ) { - return; - } - - const lineEndsWithCaret = line.endsWith('^'); - const lineEndsWithCaretVerticalBar = line.endsWith('^|'); - - if (lineStartsWithDoubleVerticalBar && line.endsWith('^$badfilter')) { - const domain = line.replace('||', '').replace('^$badfilter', '').trim(); - if (rDomain.test(domain)) { - if (DEBUG_DOMAIN_TO_FIND && domain.includes(DEBUG_DOMAIN_TO_FIND)) { - warnOnce(filterRulesUrl.toString(), true, DEBUG_DOMAIN_TO_FIND); - } - - whitelistDomainSets.add(domain); - } - } else if (line.startsWith('@@||') - && ( - lineEndsWithCaret - || lineEndsWithCaretVerticalBar - || line.endsWith('^$badfilter') - || line.endsWith('^$1p') - ) - ) { - const domain = line - .replaceAll('@@||', '') - .replaceAll('^$badfilter', '') - .replaceAll('^$1p', '') - .replaceAll('^|', '') - .replaceAll('^', '') - .trim(); - if (rDomain.test(domain)) { - if (DEBUG_DOMAIN_TO_FIND && domain.includes(DEBUG_DOMAIN_TO_FIND)) { - warnOnce(filterRulesUrl.toString(), true, DEBUG_DOMAIN_TO_FIND); - } - - whitelistDomainSets.add(domain); - } - } else if ( - lineStartsWithDoubleVerticalBar - && ( - lineEndsWithCaret - || lineEndsWithCaretVerticalBar - || line.endsWith('^$all') - ) - ) { - const domain = line - .replaceAll('||', '') - .replaceAll('^|', '') - .replaceAll('^$all', '') - .replaceAll('^', '') - .trim(); - if (rDomain.test(domain)) { - - if (DEBUG_DOMAIN_TO_FIND && domain.includes(DEBUG_DOMAIN_TO_FIND)) { - warnOnce(filterRulesUrl.toString(), false, DEBUG_DOMAIN_TO_FIND); - } - - blacklistDomainSets.add(`.${domain}`); - } - } else if (line.startsWith('://') - && ( - lineEndsWithCaret - || lineEndsWithCaretVerticalBar - ) - ) { - const domain = `${line.replaceAll('://', '').replaceAll('^|', '').replaceAll('^', '')}`.trim(); - if (rDomain.test(domain)) { - - if (DEBUG_DOMAIN_TO_FIND && domain.includes(DEBUG_DOMAIN_TO_FIND)) { - warnOnce(filterRulesUrl.toString(), false, DEBUG_DOMAIN_TO_FIND); - } - - blacklistDomainSets.add(domain); - } - } - }); - - console.timeEnd(` - processFilterRules: ${filterRulesUrl}`); - - return { - white: whitelistDomainSets, - black: blacklistDomainSets - }; -} - -function preprocessFullDomainSetBeforeUsedAsWorkerData (data) { - return data.filter(domain => ( - domain.charCodeAt(0) === 46 - && !canExcludeFromDedupe(domain) - )); -} - -// duckdns.org domain will not overlap and doesn't need dedupe -function canExcludeFromDedupe (domain) { - if ( - // starts with a dot - domain.charCodeAt(0) === 46 - && domain.length === 23 - && domain.endsWith('.duckdns.org') - ) { - return true; - } - return false; -} - -module.exports.processDomainLists = processDomainLists; -module.exports.processHosts = processHosts; -module.exports.processFilterRules = processFilterRules; -module.exports.preprocessFullDomainSetBeforeUsedAsWorkerData = preprocessFullDomainSetBeforeUsedAsWorkerData; -module.exports.canExcludeFromDedupe = canExcludeFromDedupe; diff --git a/Build/validate-cdn-conf.js b/Build/validate-cdn-conf.js deleted file mode 100644 index c1673bfd5..000000000 --- a/Build/validate-cdn-conf.js +++ /dev/null @@ -1,57 +0,0 @@ -const psl = require('psl'); -const picocolors = require('picocolors'); - -const fs = require('fs'); -const path = require('path'); - -(async () => { - const domainSetContent = await fs.promises.readFile( - path.resolve(__dirname, '../List/domainset/cdn.conf'), - { encoding: 'utf-8' } - ); - - const domainSetLines = domainSetContent.split('\n'); - for (let i = 0, len = domainSetLines.length; i < len; i++) { - const line = domainSetLines[i]; - // starts with # - if (line.charCodeAt(0) === 35) { - continue; - } - if (line.trim().length === 0) { - continue; - } - - const domain = line.charCodeAt(0) === 46 ? line.slice(1) : line; - const parsed = psl.parse(domain); - - if (parsed.listed && parsed.input === parsed.tld) { - console.error('Domain', picocolors.yellow(domain), picocolors.red('is in public suffix list!')); - } - } - - const rulesetContent = await fs.promises.readFile( - path.resolve(__dirname, '../List/non_ip/cdn.conf'), - { encoding: 'utf-8' } - ); - const rulesetLines = rulesetContent.split('\n'); - - for (let i = 0, len = rulesetLines.length; i < len; i++) { - const line = rulesetLines[i]; - // starts with # - if (line.charCodeAt(0) === 35) { - continue; - } - if (line.trim().length === 0) { - continue; - } - - if (line.startsWith('DOMAIN-SUFFIX')) { - const domain = line.slice(14); - const parsed = psl.parse(domain); - - if (parsed.input !== parsed.tld) { - console.error('Domain', picocolors.yellow(domain), picocolors.green('is not in public suffix list!')); - } - } - } -})(); diff --git a/Build/worker/build-reject-domainset-worker.js b/Build/worker/build-reject-domainset-worker.js deleted file mode 100644 index 9c2849f58..000000000 --- a/Build/worker/build-reject-domainset-worker.js +++ /dev/null @@ -1,56 +0,0 @@ -const Piscina = require('piscina'); -const { canExcludeFromDedupe } = require('../lib/parse-filter') - -const fullsetDomainStartsWithADot = Piscina.workerData -const totalLen = fullsetDomainStartsWithADot.length; - -module.exports.dedupe = ({ chunk }) => { - const chunkLength = chunk.length; - const outputToBeRemoved = new Int8Array(chunkLength); - - for (let i = 0; i < chunkLength; i++) { - const domainFromInput = chunk[i]; - - if (canExcludeFromDedupe(domainFromInput)) { - continue; - } - - for (let j = 0; j < totalLen; j++) { - const domainFromFullSet = fullsetDomainStartsWithADot[j]; - // domainFromFullSet is now startsWith a "." - - if (domainFromFullSet === domainFromInput) continue; - - const domainFromInputLen = domainFromInput.length; - const domainFromFullSetLen = domainFromFullSet.length; - - // !domainFromInput.starsWith('.') && `.${domainFromInput}` === domainFromFullSet - if (domainFromInput.charCodeAt(0) !== 46) { - if (domainFromInputLen + 1 === domainFromFullSetLen) { - - let shouldBeRemoved = true; - - for (let k = 0; k < domainFromInputLen; k++) { - if (domainFromFullSet.charCodeAt(k + 1) !== domainFromInput.charCodeAt(k)) { - shouldBeRemoved = false; - break; - } - } - - if (shouldBeRemoved) { - outputToBeRemoved[i] = 1; - break; - } - } - } else if (domainFromInputLen > domainFromFullSetLen) { - // domainFromInput is now startsWith a "." - if (domainFromInput.endsWith(domainFromFullSet)) { - outputToBeRemoved[i] = 1; - break; - } - } - } - } - - return Piscina.move(outputToBeRemoved); -}; diff --git a/List/ip/china_ip.conf b/List/ip/china_ip.conf index 08192a591..afe62445e 100644 --- a/List/ip/china_ip.conf +++ b/List/ip/china_ip.conf @@ -1,7 +1,7 @@ ############################ # Mainland China IPv4 CIDR # Data from misaka.io (misakaio @ GitHub) -# Last Updated: 2022-11-01T12:14:31.663Z +# Last Updated: 2022-11-01T12:19:49.696Z # Routes: 3183 ############################ IP-CIDR,1.2.4.0/24 diff --git a/index.html b/index.html index 7f9c700d0..278df0ed7 100644 --- a/index.html +++ b/index.html @@ -24,7 +24,7 @@

Sukka Surge Ruleset Server

Made by Sukka | Source @ GitHub | Licensed under AGPL-3.0

-

Last Updated: 2022-11-01T12:16:42.581Z

+

Last Updated: 2022-11-01T12:21:57.063Z



    diff --git a/package.json b/package.json deleted file mode 100644 index da6fc8b65..000000000 --- a/package.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "name": "ruleset.skk.moe", - "version": "0.0.0", - "private": true, - "description": "", - "scripts": { - "build": "wireit", - "build:anti-bogus-domain": "wireit", - "build:apple-cdn": "wireit", - "build:cdn-conf": "wireit", - "build:index-html": "wireit", - "build:reject-domainset": "wireit", - "build:phishing-domainset": "wireit", - "build:telegram-cidr": "wireit", - "build:chn-cidr": "wireit", - "validate:cdn-conf": "wireit" - }, - "wireit": { - "build:anti-bogus-domain": { - "command": "node ./Build/build-anti-bogus-domain.js" - }, - "build:apple-cdn": { - "command": "node ./Build/build-apple-cdn.js" - }, - "build:cdn-conf": { - "command": "node ./Build/build-cdn-conf.js" - }, - "build:phishing-domainset": { - "command": "node ./Build/build-phishing-domainset.js" - }, - "build:reject-domainset": { - "command": "node ./Build/build-reject-domainset.js", - "dependencies": [ - "build:phishing-domainset" - ] - }, - "build:telegram-cidr": { - "command": "node ./Build/build-telegram-cidr.js" - }, - "build:chn-cidr": { - "command": "node ./Build/build-chn-cidr.js" - }, - "build:index-html": { - "command": "node ./Build/build-index.html.js", - "dependencies": [ - "build:anti-bogus-domain", - "build:apple-cdn", - "build:cdn-conf", - "build:reject-domainset", - "build:telegram-cidr" - ] - }, - "validate:cdn-conf": { - "command": "node ./Build/validate-cdn-conf.js" - }, - "build": { - "dependencies": [ - "build:anti-bogus-domain", - "build:apple-cdn", - "build:cdn-conf", - "build:reject-domainset", - "build:telegram-cidr", - "build:chn-cidr", - "build:index-html", - "validate:cdn-conf" - ] - } - }, - "repository": { - "type": "git", - "url": "git+https://github.com/SukkaW/Surge.git" - }, - "author": "", - "license": "ISC", - "dependencies": { - "@sukka/listdir": "^0.2.0", - "@vercel/fetch-retry": "^5.1.3", - "ci-info": "^3.5.0", - "picocolors": "^1.0.0", - "piscina": "^3.2.0", - "psl": "^1.9.0", - "table": "^6.8.0", - "undici": "5.11.0" - }, - "devDependencies": { - "wireit": "^0.7.2" - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index 35c509d32..000000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,477 +0,0 @@ -lockfileVersion: 5.4 - -specifiers: - '@sukka/listdir': ^0.2.0 - '@vercel/fetch-retry': ^5.1.3 - ci-info: ^3.5.0 - picocolors: ^1.0.0 - piscina: ^3.2.0 - psl: ^1.9.0 - table: ^6.8.0 - undici: 5.11.0 - wireit: ^0.7.2 - -dependencies: - '@sukka/listdir': 0.2.0 - '@vercel/fetch-retry': 5.1.3 - ci-info: 3.5.0 - picocolors: 1.0.0 - piscina: 3.2.0 - psl: 1.9.0 - table: 6.8.0 - undici: 5.11.0 - -devDependencies: - wireit: 0.7.2 - -packages: - - /@assemblyscript/loader/0.10.1: - resolution: {integrity: sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==} - dev: false - - /@nodelib/fs.scandir/2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat/2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk/1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.13.0 - dev: true - - /@sukka/listdir/0.2.0: - resolution: {integrity: sha512-UyVirNhAOXKwjiDehjUaGtpfk0QwNHyiXrlLb/FmWMtI+BGhaEvB9MypSfEAtiiMI3g6QTfG38ayNAorEuz5ow==} - dev: false - - /@vercel/fetch-retry/5.1.3: - resolution: {integrity: sha512-UIbFc4VsEZHOr6dWuE+kxY4NxnOLXFMCWm0fSKRRHUEtrIzaJLzHpWk2QskCXTSzFgFvhkLAvSrBK2XZg7NSzg==} - peerDependencies: - node-fetch: ^2.6.7 - dependencies: - async-retry: 1.3.3 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false - - /ajv/8.8.2: - resolution: {integrity: sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: false - - /ansi-regex/5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: false - - /ansi-styles/4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: false - - /anymatch/3.1.2: - resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /astral-regex/2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - dev: false - - /async-retry/1.3.3: - resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} - dependencies: - retry: 0.13.1 - dev: false - - /base64-js/1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: false - - /binary-extensions/2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: true - - /braces/3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /busboy/1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - dependencies: - streamsearch: 1.1.0 - dev: false - - /chokidar/3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.2 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.2 - dev: true - - /ci-info/3.5.0: - resolution: {integrity: sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==} - dev: false - - /color-convert/2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: false - - /color-name/1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: false - - /debug/4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: false - - /emoji-regex/8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: false - - /eventemitter-asyncresource/1.0.0: - resolution: {integrity: sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==} - dev: false - - /fast-deep-equal/3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: false - - /fast-glob/3.2.11: - resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fastq/1.13.0: - resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} - dependencies: - reusify: 1.0.4 - dev: true - - /fill-range/7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /fsevents/2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /glob-parent/5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /graceful-fs/4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - dev: true - - /hdr-histogram-js/2.0.1: - resolution: {integrity: sha512-uPZxl1dAFnjUFHWLZmt93vUUvtHeaBay9nVNHu38SdOjMSF/4KqJUqa1Seuj08ptU1rEb6AHvB41X8n/zFZ74Q==} - dependencies: - '@assemblyscript/loader': 0.10.1 - base64-js: 1.5.1 - pako: 1.0.11 - dev: false - - /hdr-histogram-percentiles-obj/3.0.0: - resolution: {integrity: sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==} - dev: false - - /is-binary-path/2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - dev: true - - /is-extglob/2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-fullwidth-code-point/3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: false - - /is-glob/4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-number/7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /json-schema-traverse/1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: false - - /jsonc-parser/3.0.0: - resolution: {integrity: sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==} - dev: true - - /lodash.truncate/4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - dev: false - - /merge2/1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /micromatch/4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /ms/2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: false - - /nice-napi/1.0.2: - resolution: {integrity: sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==} - os: ['!win32'] - requiresBuild: true - dependencies: - node-addon-api: 3.2.1 - node-gyp-build: 4.3.0 - dev: false - optional: true - - /node-addon-api/3.2.1: - resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} - dev: false - optional: true - - /node-gyp-build/4.3.0: - resolution: {integrity: sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==} - hasBin: true - dev: false - optional: true - - /normalize-path/3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /pako/1.0.11: - resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} - dev: false - - /picocolors/1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: false - - /picomatch/2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /piscina/3.2.0: - resolution: {integrity: sha512-yn/jMdHRw+q2ZJhFhyqsmANcbF6V2QwmD84c6xRau+QpQOmtrBCoRGdvTfeuFDYXB5W2m6MfLkjkvQa9lUSmIA==} - dependencies: - eventemitter-asyncresource: 1.0.0 - hdr-histogram-js: 2.0.1 - hdr-histogram-percentiles-obj: 3.0.0 - optionalDependencies: - nice-napi: 1.0.2 - dev: false - - /proper-lockfile/4.1.2: - resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} - dependencies: - graceful-fs: 4.2.10 - retry: 0.12.0 - signal-exit: 3.0.7 - dev: true - - /psl/1.9.0: - resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} - dev: false - - /punycode/2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} - engines: {node: '>=6'} - dev: false - - /queue-microtask/1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /readdirp/3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /require-from-string/2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: false - - /retry/0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - dev: true - - /retry/0.13.1: - resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} - engines: {node: '>= 4'} - dev: false - - /reusify/1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /run-parallel/1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /signal-exit/3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /slice-ansi/4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: false - - /streamsearch/1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - dev: false - - /string-width/4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: false - - /strip-ansi/6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: false - - /table/6.8.0: - resolution: {integrity: sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==} - engines: {node: '>=10.0.0'} - dependencies: - ajv: 8.8.2 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: false - - /to-regex-range/5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /undici/5.11.0: - resolution: {integrity: sha512-oWjWJHzFet0Ow4YZBkyiJwiK5vWqEYoH7BINzJAJOLedZ++JpAlCbUktW2GQ2DS2FpKmxD/JMtWUUWl1BtghGw==} - engines: {node: '>=12.18'} - dependencies: - busboy: 1.6.0 - dev: false - - /uri-js/4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.1.1 - dev: false - - /wireit/0.7.2: - resolution: {integrity: sha512-Zjq50QH5hguk64hXfJmJJpLGgi8TUy7780w0u2VXK325qWxJtw1fP6HhOYcdjTWeoYLWQDDkTytQ119y/UMseg==} - engines: {node: '>=14.14.0'} - hasBin: true - dependencies: - braces: 3.0.2 - chokidar: 3.5.3 - fast-glob: 3.2.11 - jsonc-parser: 3.0.0 - proper-lockfile: 4.1.2 - dev: true