Chore: new way to attach description

This commit is contained in:
SukkaW 2025-07-21 15:57:35 +08:00
parent de1f817eec
commit 3a7f15ca6c
10 changed files with 74 additions and 71 deletions

View File

@ -12,14 +12,14 @@ export const buildAppleCdn = task(require.main === module, __filename)(async (sp
return new DomainsetOutput(span, 'apple_cdn') return new DomainsetOutput(span, 'apple_cdn')
.withTitle('Sukka\'s Ruleset - Apple CDN') .withTitle('Sukka\'s Ruleset - Apple CDN')
.withDescription([ .appendDescription(SHARED_DESCRIPTION)
...SHARED_DESCRIPTION, .appendDescription(
'', '',
'This file contains Apple\'s domains using their China mainland CDN servers.', 'This file contains Apple\'s domains using their China mainland CDN servers.',
'', '',
'Data from:', 'Data from:',
' - https://github.com/felixonmars/dnsmasq-china-list' ' - https://github.com/felixonmars/dnsmasq-china-list'
]) )
.bulkAddDomainSuffix(res) .bulkAddDomainSuffix(res)
.write(); .write();
}); });

View File

@ -75,21 +75,21 @@ export const buildCdnDownloadConf = task(require.main === module, __filename)(as
return Promise.all([ return Promise.all([
new DomainsetOutput(span, 'cdn') new DomainsetOutput(span, 'cdn')
.withTitle('Sukka\'s Ruleset - CDN Domains') .withTitle('Sukka\'s Ruleset - CDN Domains')
.withDescription([ .appendDescription(SHARED_DESCRIPTION)
...SHARED_DESCRIPTION, .appendDescription(
'', '',
'This file contains object storage and static assets CDN domains.' 'This file contains object storage and static assets CDN domains.'
]) )
.addFromDomainset(cdnDomainsList) .addFromDomainset(cdnDomainsList)
.write(), .write(),
new DomainsetOutput(span, 'download') new DomainsetOutput(span, 'download')
.withTitle('Sukka\'s Ruleset - Large Files Hosting Domains') .withTitle('Sukka\'s Ruleset - Large Files Hosting Domains')
.withDescription([ .appendDescription(SHARED_DESCRIPTION)
...SHARED_DESCRIPTION, .appendDescription(
'', '',
'This file contains domains for software updating & large file hosting.' 'This file contains domains for software updating & large file hosting.'
]) )
.addFromDomainset(downloadDomainSet) .addFromDomainset(downloadDomainSet)
.write() .write()
]); ]);

View File

@ -21,18 +21,16 @@ export const buildChnCidr = task(require.main === module, __filename)(async (spa
return Promise.all([ return Promise.all([
new IPListOutput(span, 'china_ip', false) new IPListOutput(span, 'china_ip', false)
.withTitle('Sukka\'s Ruleset - Mainland China IPv4 CIDR') .withTitle('Sukka\'s Ruleset - Mainland China IPv4 CIDR')
.withDescription([ .withDescription(description)
...description, .appendDataSource('https://chnroutes2.cdn.skk.moe/chnroutes.txt')
'Data from https://misaka.io (misakaio @ GitHub)'
])
.bulkAddCIDR4(filteredCidr4) .bulkAddCIDR4(filteredCidr4)
.write(), .write(),
new IPListOutput(span, 'china_ip_ipv6', false) new IPListOutput(span, 'china_ip_ipv6', false)
.withTitle('Sukka\'s Ruleset - Mainland China IPv6 CIDR') .withTitle('Sukka\'s Ruleset - Mainland China IPv6 CIDR')
.withDescription([ .withDescription(description)
...description, .appendDataSource(
'Data from https://github.com/gaoyifan/china-operator-ip' 'https://github.com/gaoyifan/china-operator-ip'
]) )
.bulkAddCIDR6(cidr6) .bulkAddCIDR6(cidr6)
.write() .write()
]); ]);

View File

@ -16,11 +16,9 @@ export const buildCloudMounterRules = task(require.main === module, __filename)(
].map(cidr => `AND,((${domain}),(SRC-IP,${cidr}))`) ].map(cidr => `AND,((${domain}),(SRC-IP,${cidr}))`)
])); ]));
const description = SHARED_DESCRIPTION;
return new RulesetOutput(span, 'cloudmounter', 'non_ip') return new RulesetOutput(span, 'cloudmounter', 'non_ip')
.withTitle('Sukka\'s Ruleset - CloudMounter / RaiDrive') .withTitle('Sukka\'s Ruleset - CloudMounter / RaiDrive')
.withDescription(description) .withDescription(SHARED_DESCRIPTION)
.addFromRuleset(results) .addFromRuleset(results)
.write(); .write();
}); });

View File

@ -89,29 +89,29 @@ export const buildDomesticRuleset = task(require.main === module, __filename)(as
return Promise.all([ return Promise.all([
new RulesetOutput(span, 'domestic', 'non_ip') new RulesetOutput(span, 'domestic', 'non_ip')
.withTitle('Sukka\'s Ruleset - Domestic Domains') .withTitle('Sukka\'s Ruleset - Domestic Domains')
.withDescription([ .appendDescription(
...SHARED_DESCRIPTION, SHARED_DESCRIPTION,
'', '',
'This file contains known addresses that are avaliable in the Mainland China.' 'This file contains known addresses that are avaliable in the Mainland China.'
]) )
.addFromRuleset(domestics) .addFromRuleset(domestics)
.write(), .write(),
new RulesetOutput(span, 'direct', 'non_ip') new RulesetOutput(span, 'direct', 'non_ip')
.withTitle('Sukka\'s Ruleset - Direct Rules') .withTitle('Sukka\'s Ruleset - Direct Rules')
.withDescription([ .appendDescription(
...SHARED_DESCRIPTION, SHARED_DESCRIPTION,
'', '',
'This file contains domains and process that should not be proxied.' 'This file contains domains and process that should not be proxied.'
]) )
.addFromRuleset(directs) .addFromRuleset(directs)
.write(), .write(),
new RulesetOutput(span, 'lan', 'non_ip') new RulesetOutput(span, 'lan', 'non_ip')
.withTitle('Sukka\'s Ruleset - LAN') .withTitle('Sukka\'s Ruleset - LAN')
.withDescription([ .appendDescription(
...SHARED_DESCRIPTION, SHARED_DESCRIPTION,
'', '',
'This file includes rules for LAN DOMAIN and reserved TLDs.' 'This file includes rules for LAN DOMAIN and reserved TLDs.'
]) )
.addFromRuleset(lans) .addFromRuleset(lans)
.write(), .write(),
@ -122,12 +122,12 @@ export const buildDomesticRuleset = task(require.main === module, __filename)(as
const output = new SurgeOnlyRulesetOutput(span, name.toLowerCase(), 'sukka_local_dns_mapping', OUTPUT_MODULES_RULES_DIR) const output = new SurgeOnlyRulesetOutput(span, name.toLowerCase(), 'sukka_local_dns_mapping', OUTPUT_MODULES_RULES_DIR)
.withTitle(`Sukka's Ruleset - Local DNS Mapping (${name})`) .withTitle(`Sukka's Ruleset - Local DNS Mapping (${name})`)
.withDescription([ .appendDescription(
...SHARED_DESCRIPTION, SHARED_DESCRIPTION,
'', '',
'This is an internal rule that is only referenced by sukka_local_dns_mapping.sgmodule', 'This is an internal rule that is only referenced by sukka_local_dns_mapping.sgmodule',
'Do not use this file in your Rule section, all rules are included in non_ip/domestic.conf already.' 'Do not use this file in your Rule section, all rules are included in non_ip/domestic.conf already.'
]); );
domains.forEach((domain) => { domains.forEach((domain) => {
switch (domain[0]) { switch (domain[0]) {

View File

@ -55,20 +55,16 @@ export const getMicrosoftCdnRulesetPromise = once<Promise<[domains: string[], do
}); });
export const buildMicrosoftCdn = task(require.main === module, __filename)(async (span) => { export const buildMicrosoftCdn = task(require.main === module, __filename)(async (span) => {
const description = [
...SHARED_DESCRIPTION,
'',
'This file contains Microsoft\'s domains using their China mainland CDN servers.',
'',
'Data from:',
' - https://github.com/felixonmars/dnsmasq-china-list'
];
const [domains, domainSuffixes] = await span.traceChildPromise('get microsoft cdn domains', getMicrosoftCdnRulesetPromise()); const [domains, domainSuffixes] = await span.traceChildPromise('get microsoft cdn domains', getMicrosoftCdnRulesetPromise());
return new RulesetOutput(span, 'microsoft_cdn', 'non_ip') return new RulesetOutput(span, 'microsoft_cdn', 'non_ip')
.withTitle('Sukka\'s Ruleset - Microsoft CDN') .withTitle('Sukka\'s Ruleset - Microsoft CDN')
.withDescription(description) .appendDescription(SHARED_DESCRIPTION)
.appendDescription(
'',
'This file contains Microsoft\'s domains using their China mainland CDN servers.'
)
.appendDataSource('https://github.com/felixonmars/dnsmasq-china-list')
.bulkAddDomain(domains) .bulkAddDomain(domains)
.bulkAddDomainSuffix(domainSuffixes) .bulkAddDomainSuffix(domainSuffixes)
.write(); .write();

View File

@ -41,51 +41,50 @@ const adguardFiltersWhitelistsDownloads = ADGUARD_FILTERS_WHITELIST.map(entry =>
export const buildRejectDomainSet = task(require.main === module, __filename)(async (span) => { export const buildRejectDomainSet = task(require.main === module, __filename)(async (span) => {
const rejectDomainsetOutput = new DomainsetOutput(span, 'reject') const rejectDomainsetOutput = new DomainsetOutput(span, 'reject')
.withTitle('Sukka\'s Ruleset - Reject Base') .withTitle('Sukka\'s Ruleset - Reject Base')
.withDescription([ .appendDescription(
...SHARED_DESCRIPTION, SHARED_DESCRIPTION,
'', '',
'The domainset supports AD blocking, tracking protection, privacy protection, anti-mining' 'The domainset supports AD blocking, tracking protection, privacy protection, anti-mining'
]) )
.appendDataSource(HOSTS.map(host => host[0])) .appendDataSource(HOSTS.map(host => host[0]))
.appendDataSource(DOMAIN_LISTS.map(domainList => domainList[0])); .appendDataSource(DOMAIN_LISTS.map(domainList => domainList[0]));
const rejectExtraDomainsetOutput = new DomainsetOutput(span, 'reject_extra') const rejectExtraDomainsetOutput = new DomainsetOutput(span, 'reject_extra')
.withTitle('Sukka\'s Ruleset - Reject Extra') .withTitle('Sukka\'s Ruleset - Reject Extra')
.withDescription([ .appendDescription(
...SHARED_DESCRIPTION, SHARED_DESCRIPTION,
'', '',
'The domainset supports AD blocking, tracking protection, privacy protection, anti-mining' 'The domainset supports AD blocking, tracking protection, privacy protection, anti-mining'
]) )
.appendDataSource(HOSTS_EXTRA.map(host => host[0])) .appendDataSource(HOSTS_EXTRA.map(host => host[0]))
.appendDataSource(DOMAIN_LISTS_EXTRA.map(domainList => domainList[0])); .appendDataSource(DOMAIN_LISTS_EXTRA.map(domainList => domainList[0]));
const rejectPhisingDomainsetOutput = new DomainsetOutput(span, 'reject_phishing') const rejectPhisingDomainsetOutput = new DomainsetOutput(span, 'reject_phishing')
.withTitle('Sukka\'s Ruleset - Reject Phishing') .withTitle('Sukka\'s Ruleset - Reject Phishing')
.withDescription([ .appendDescription(
...SHARED_DESCRIPTION, SHARED_DESCRIPTION,
'', '',
'The domainset is specifically designed for anti-phishing' 'The domainset is specifically designed for anti-phishing'
]) )
.appendDataSource(PHISHING_HOSTS_EXTRA.map(host => host[0])) .appendDataSource(PHISHING_HOSTS_EXTRA.map(host => host[0]))
.appendDataSource(PHISHING_DOMAIN_LISTS_EXTRA.map(domainList => domainList[0])); .appendDataSource(PHISHING_DOMAIN_LISTS_EXTRA.map(domainList => domainList[0]));
const rejectNonIpRulesetOutput = new RulesetOutput(span, 'reject', 'non_ip') const rejectNonIpRulesetOutput = new RulesetOutput(span, 'reject', 'non_ip')
.withTitle('Sukka\'s Ruleset - Reject Non-IP') .withTitle('Sukka\'s Ruleset - Reject Non-IP')
.withDescription([ .appendDescription(SHARED_DESCRIPTION, '')
...SHARED_DESCRIPTION, .appendDescription(
'',
'The ruleset supports AD blocking, tracking protection, privacy protection, anti-phishing, anti-mining', 'The ruleset supports AD blocking, tracking protection, privacy protection, anti-phishing, anti-mining',
'', '',
'The file contains wildcard domains from data source mentioned in /domainset/reject file' 'The file contains wildcard domains from data source mentioned in /domainset/reject file'
]); );
const rejectIPOutput = new RulesetOutput(span, 'reject', 'ip') const rejectIPOutput = new RulesetOutput(span, 'reject', 'ip')
.withTitle('Sukka\'s Ruleset - Anti Bogus Domain') .withTitle('Sukka\'s Ruleset - Anti Bogus Domain')
.withDescription([ .appendDescription(
...SHARED_DESCRIPTION, SHARED_DESCRIPTION,
'', '',
'This file contains known addresses that are hijacking NXDOMAIN results returned by DNS servers, and botnet controller IPs.' 'This file contains known addresses that are hijacking NXDOMAIN results returned by DNS servers, and botnet controller IPs.'
]) )
.appendDataSource('https://github.com/felixonmars/dnsmasq-china-list') .appendDataSource('https://github.com/felixonmars/dnsmasq-china-list')
.appendDataSource('https://github.com/curbengh/botnet-filter') .appendDataSource('https://github.com/curbengh/botnet-filter')
.bulkAddIPASN(AUGUST_ASN) .bulkAddIPASN(AUGUST_ASN)

View File

@ -48,11 +48,11 @@ const getSpeedtestHostsGroupsPromise = $$fetch('https://speedtest-net-servers.cd
export const buildSpeedtestDomainSet = task(require.main === module, __filename)( export const buildSpeedtestDomainSet = task(require.main === module, __filename)(
async (span) => new DomainsetOutput(span, 'speedtest') async (span) => new DomainsetOutput(span, 'speedtest')
.withTitle('Sukka\'s Ruleset - Speedtest Domains') .withTitle('Sukka\'s Ruleset - Speedtest Domains')
.withDescription([ .appendDescription(
...SHARED_DESCRIPTION, SHARED_DESCRIPTION,
'', '',
'This file contains common speedtest endpoints.' 'This file contains common speedtest endpoints.'
]) )
.addFromDomainset(readFileIntoProcessedArray(path.resolve(SOURCE_DIR, 'domainset/speedtest.conf'))) .addFromDomainset(readFileIntoProcessedArray(path.resolve(SOURCE_DIR, 'domainset/speedtest.conf')))
.addFromDomainset(readFileIntoProcessedArray(path.resolve(OUTPUT_SURGE_DIR, 'domainset/speedtest.conf'))) .addFromDomainset(readFileIntoProcessedArray(path.resolve(OUTPUT_SURGE_DIR, 'domainset/speedtest.conf')))
.bulkAddDomain(await span.traceChildPromise('get speedtest hosts groups', getSpeedtestHostsGroupsPromise)) .bulkAddDomain(await span.traceChildPromise('get speedtest hosts groups', getSpeedtestHostsGroupsPromise))

View File

@ -15,21 +15,17 @@ function createRulesetForStreamService(
// Domains // Domains
new RulesetOutput(span, fileId, 'non_ip') new RulesetOutput(span, fileId, 'non_ip')
.withTitle(`Sukka's Ruleset - Stream Services: ${title}`) .withTitle(`Sukka's Ruleset - Stream Services: ${title}`)
.withDescription([ .appendDescription(SHARED_DESCRIPTION)
...SHARED_DESCRIPTION, .appendDescription('')
'', .appendDescription(streamServices.map((i) => `- ${i.name}`))
...streamServices.map((i) => `- ${i.name}`)
])
.addFromRuleset(streamServices.flatMap((i) => i.rules)) .addFromRuleset(streamServices.flatMap((i) => i.rules))
.write(), .write(),
// IP // IP
new RulesetOutput(span, fileId, 'ip') new RulesetOutput(span, fileId, 'ip')
.withTitle(`Sukka's Ruleset - Stream Services IPs: ${title}`) .withTitle(`Sukka's Ruleset - Stream Services IPs: ${title}`)
.withDescription([ .appendDescription(SHARED_DESCRIPTION)
...SHARED_DESCRIPTION, .appendDescription('')
'', .appendDescription(streamServices.map((i) => `- ${i.name}`))
...streamServices.map((i) => `- ${i.name}`)
])
.bulkAddCIDR4NoResolve(streamServices.flatMap(i => i.ip?.v4 ?? [])) .bulkAddCIDR4NoResolve(streamServices.flatMap(i => i.ip?.v4 ?? []))
.bulkAddCIDR6NoResolve(streamServices.flatMap(i => i.ip?.v6 ?? [])) .bulkAddCIDR6NoResolve(streamServices.flatMap(i => i.ip?.v6 ?? []))
.write() .write()

View File

@ -9,6 +9,7 @@ import { merge as mergeCidr } from 'fast-cidr-tools';
import { createRetrieKeywordFilter as createKeywordFilter } from 'foxts/retrie'; import { createRetrieKeywordFilter as createKeywordFilter } from 'foxts/retrie';
import path from 'node:path'; import path from 'node:path';
import { SurgeMitmSgmodule } from '../writing-strategy/surge'; import { SurgeMitmSgmodule } from '../writing-strategy/surge';
import { appendArrayInPlace } from 'foxts/append-array-in-place';
/** /**
* Holds the universal rule data (domain, ip, url-regex, etc. etc.) * Holds the universal rule data (domain, ip, url-regex, etc. etc.)
@ -86,6 +87,21 @@ export class FileOutput {
return this; return this;
} }
appendDescription(description: string | string[], ...rest: string[]) {
this.description ??= [];
if (typeof description === 'string') {
this.description.push(description);
} else {
appendArrayInPlace(this.description, description);
}
if (rest.length) {
appendArrayInPlace(this.description, rest);
}
return this;
}
protected date = new Date(); protected date = new Date();
withDate(date: Date) { withDate(date: Date) {
this.date = date; this.date = date;