mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-13 01:30:37 +08:00
Refactor: refine writing strategy
This commit is contained in:
parent
3926fb3484
commit
2035f5ea96
@ -8,7 +8,7 @@ import { fastStringArrayJoin } from 'foxts/fast-string-array-join';
|
|||||||
import { readFileByLine } from '../fetch-text-by-line';
|
import { readFileByLine } from '../fetch-text-by-line';
|
||||||
import { asyncWriteToStream } from 'foxts/async-write-to-stream';
|
import { asyncWriteToStream } from 'foxts/async-write-to-stream';
|
||||||
import type { BaseWriteStrategy } from '../writing-strategy/base';
|
import type { BaseWriteStrategy } from '../writing-strategy/base';
|
||||||
import { merge } from 'fast-cidr-tools';
|
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';
|
||||||
@ -369,10 +369,10 @@ export class FileOutput {
|
|||||||
let ipcidr6NoResolve: string[] | null = null;
|
let ipcidr6NoResolve: string[] | null = null;
|
||||||
|
|
||||||
if (this.ipcidr.size) {
|
if (this.ipcidr.size) {
|
||||||
ipcidr = merge(Array.from(this.ipcidr), true);
|
ipcidr = mergeCidr(Array.from(this.ipcidr), true);
|
||||||
}
|
}
|
||||||
if (this.ipcidrNoResolve.size) {
|
if (this.ipcidrNoResolve.size) {
|
||||||
ipcidrNoResolve = merge(Array.from(this.ipcidrNoResolve), true);
|
ipcidrNoResolve = mergeCidr(Array.from(this.ipcidrNoResolve), true);
|
||||||
}
|
}
|
||||||
if (this.ipcidr6.size) {
|
if (this.ipcidr6.size) {
|
||||||
ipcidr6 = Array.from(this.ipcidr6);
|
ipcidr6 = Array.from(this.ipcidr6);
|
||||||
@ -433,9 +433,12 @@ export class FileOutput {
|
|||||||
this.title,
|
this.title,
|
||||||
this.description,
|
this.description,
|
||||||
this.date,
|
this.date,
|
||||||
|
path.join(
|
||||||
|
strategy.outputDir,
|
||||||
strategy.type
|
strategy.type
|
||||||
? path.join(strategy.type, basename)
|
? path.join(strategy.type, basename)
|
||||||
: basename
|
: basename
|
||||||
|
)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,12 +7,10 @@ import { SurgeDomainSet } from '../writing-strategy/surge';
|
|||||||
import { FileOutput } from './base';
|
import { FileOutput } from './base';
|
||||||
|
|
||||||
export class DomainsetOutput extends FileOutput {
|
export class DomainsetOutput extends FileOutput {
|
||||||
protected type = 'domainset' as const;
|
|
||||||
|
|
||||||
strategies: Array<false | BaseWriteStrategy> = [
|
strategies: Array<false | BaseWriteStrategy> = [
|
||||||
new SurgeDomainSet(),
|
new SurgeDomainSet(),
|
||||||
new ClashDomainSet(),
|
new ClashDomainSet(),
|
||||||
new SingboxSource(this.type)
|
new SingboxSource('domainset')
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,16 +6,15 @@ import { SurgeRuleSet } from '../writing-strategy/surge';
|
|||||||
import { FileOutput } from './base';
|
import { FileOutput } from './base';
|
||||||
|
|
||||||
export class IPListOutput extends FileOutput {
|
export class IPListOutput extends FileOutput {
|
||||||
protected type = 'ip' as const;
|
|
||||||
strategies: Array<false | BaseWriteStrategy>;
|
strategies: Array<false | BaseWriteStrategy>;
|
||||||
|
|
||||||
constructor(span: Span, id: string, private readonly clashUseRule = true) {
|
constructor(span: Span, id: string, private readonly clashUseRule = true) {
|
||||||
super(span, id);
|
super(span, id);
|
||||||
|
|
||||||
this.strategies = [
|
this.strategies = [
|
||||||
new SurgeRuleSet(this.type),
|
new SurgeRuleSet('ip'),
|
||||||
this.clashUseRule ? new ClashClassicRuleSet(this.type) : new ClashIPSet(),
|
this.clashUseRule ? new ClashClassicRuleSet('ip') : new ClashIPSet(),
|
||||||
new SingboxSource(this.type)
|
new SingboxSource('ip')
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,13 +5,13 @@ import { SurgeRuleSet } from '../writing-strategy/surge';
|
|||||||
import { FileOutput } from './base';
|
import { FileOutput } from './base';
|
||||||
|
|
||||||
export class RulesetOutput extends FileOutput {
|
export class RulesetOutput extends FileOutput {
|
||||||
constructor(span: Span, id: string, protected type: 'non_ip' | 'ip' | (string & {})) {
|
constructor(span: Span, id: string, type: 'non_ip' | 'ip') {
|
||||||
super(span, id);
|
super(span, id);
|
||||||
|
|
||||||
this.strategies = [
|
this.strategies = [
|
||||||
new SurgeRuleSet(this.type),
|
new SurgeRuleSet(type),
|
||||||
new ClashClassicRuleSet(this.type),
|
new ClashClassicRuleSet(type),
|
||||||
new SingboxSource(this.type)
|
new SingboxSource(type)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -20,13 +20,13 @@ export class SurgeOnlyRulesetOutput extends FileOutput {
|
|||||||
constructor(
|
constructor(
|
||||||
span: Span,
|
span: Span,
|
||||||
id: string,
|
id: string,
|
||||||
protected type: 'non_ip' | 'ip' | (string & {}),
|
type: 'non_ip' | 'ip' | (string & {}),
|
||||||
overrideOutputDir?: string
|
overrideOutputDir?: string
|
||||||
) {
|
) {
|
||||||
super(span, id);
|
super(span, id);
|
||||||
|
|
||||||
this.strategies = [
|
this.strategies = [
|
||||||
new SurgeRuleSet(this.type, overrideOutputDir)
|
new SurgeRuleSet(type, overrideOutputDir)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,12 +35,12 @@ export class ClashOnlyRulesetOutput extends FileOutput {
|
|||||||
constructor(
|
constructor(
|
||||||
span: Span,
|
span: Span,
|
||||||
id: string,
|
id: string,
|
||||||
protected type: 'non_ip' | 'ip' | (string & {})
|
type: 'non_ip' | 'ip'
|
||||||
) {
|
) {
|
||||||
super(span, id);
|
super(span, id);
|
||||||
|
|
||||||
this.strategies = [
|
this.strategies = [
|
||||||
new ClashClassicRuleSet(this.type)
|
new ClashClassicRuleSet(type)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,13 @@
|
|||||||
import path from 'node:path';
|
|
||||||
import type { Span } from '../../trace';
|
import type { Span } from '../../trace';
|
||||||
import { compareAndWriteFile } from '../create-file';
|
import { compareAndWriteFile } from '../create-file';
|
||||||
|
|
||||||
export abstract class BaseWriteStrategy {
|
export abstract class BaseWriteStrategy {
|
||||||
// abstract readonly type: 'domainset' | 'non_ip' | 'ip' | (string & {});
|
|
||||||
public overwriteFilename: string | null = null;
|
public overwriteFilename: string | null = null;
|
||||||
public abstract readonly type: 'domainset' | 'non_ip' | 'ip' | (string & {});
|
public abstract readonly type: 'domainset' | 'non_ip' | 'ip' | (string & {});
|
||||||
|
|
||||||
abstract readonly fileExtension: 'conf' | 'txt' | 'json' | (string & {});
|
abstract readonly fileExtension: 'conf' | 'txt' | 'json' | (string & {});
|
||||||
|
|
||||||
constructor(protected outputDir: string) {}
|
constructor(public readonly outputDir: string) {}
|
||||||
|
|
||||||
protected abstract result: string[] | null;
|
protected abstract result: string[] | null;
|
||||||
|
|
||||||
@ -51,14 +49,14 @@ export abstract class BaseWriteStrategy {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
abstract withPadding(title: string, description: string[] | readonly string[], date: Date, content: string[]): string[];
|
protected abstract withPadding(title: string, description: string[] | readonly string[], date: Date, content: string[]): string[];
|
||||||
|
|
||||||
output(
|
public output(
|
||||||
span: Span,
|
span: Span,
|
||||||
title: string,
|
title: string,
|
||||||
description: string[] | readonly string[],
|
description: string[] | readonly string[],
|
||||||
date: Date,
|
date: Date,
|
||||||
relativePath: string
|
filePath: string
|
||||||
): void | Promise<void> {
|
): void | Promise<void> {
|
||||||
if (!this.result) {
|
if (!this.result) {
|
||||||
return;
|
return;
|
||||||
@ -71,11 +69,11 @@ export abstract class BaseWriteStrategy {
|
|||||||
date,
|
date,
|
||||||
this.result
|
this.result
|
||||||
),
|
),
|
||||||
path.join(this.outputDir, relativePath)
|
filePath
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
get content() {
|
public get content() {
|
||||||
return this.result;
|
return this.result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export class ClashDomainSet extends BaseWriteStrategy {
|
|||||||
|
|
||||||
protected result: string[] = ['this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
|
protected result: string[] = ['this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
|
||||||
|
|
||||||
constructor(protected outputDir = OUTPUT_CLASH_DIR) {
|
constructor(public readonly outputDir = OUTPUT_CLASH_DIR) {
|
||||||
super(outputDir);
|
super(outputDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ export class ClashIPSet extends BaseWriteStrategy {
|
|||||||
|
|
||||||
protected result: string[] = [];
|
protected result: string[] = [];
|
||||||
|
|
||||||
constructor(protected outputDir = OUTPUT_CLASH_DIR) {
|
constructor(public readonly outputDir = OUTPUT_CLASH_DIR) {
|
||||||
super(outputDir);
|
super(outputDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ export class ClashClassicRuleSet extends BaseWriteStrategy {
|
|||||||
|
|
||||||
protected result: string[] = ['DOMAIN,this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
|
protected result: string[] = ['DOMAIN,this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
|
||||||
|
|
||||||
constructor(public readonly type: string, protected outputDir = OUTPUT_CLASH_DIR) {
|
constructor(public readonly type: 'ip' | 'non_ip' /* | (string & {}) */, public readonly outputDir = OUTPUT_CLASH_DIR) {
|
||||||
super(outputDir);
|
super(outputDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,11 @@ export class SingboxSource extends BaseWriteStrategy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(public type: string, protected outputDir = OUTPUT_SINGBOX_DIR) {
|
constructor(
|
||||||
|
/** Since sing-box only have one format that does not reflect type, we need to specify it */
|
||||||
|
public type: 'domainset' | 'non_ip' | 'ip' /* | (string & {}) */,
|
||||||
|
public readonly outputDir = OUTPUT_SINGBOX_DIR
|
||||||
|
) {
|
||||||
super(outputDir);
|
super(outputDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,11 @@ export class SurgeRuleSet extends BaseWriteStrategy {
|
|||||||
|
|
||||||
protected result: string[] = ['DOMAIN,this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
|
protected result: string[] = ['DOMAIN,this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
|
||||||
|
|
||||||
constructor(public readonly type: string, outputDir = OUTPUT_SURGE_DIR) {
|
constructor(
|
||||||
|
/** Surge RULE-SET can be both ip or non_ip, so this needs to be specified */
|
||||||
|
public readonly type: 'ip' | 'non_ip' | (string & {}),
|
||||||
|
public readonly outputDir = OUTPUT_SURGE_DIR
|
||||||
|
) {
|
||||||
super(outputDir);
|
super(outputDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +134,7 @@ export class SurgeRuleSet extends BaseWriteStrategy {
|
|||||||
export class SurgeMitmSgmodule extends BaseWriteStrategy {
|
export class SurgeMitmSgmodule extends BaseWriteStrategy {
|
||||||
// readonly type = 'domainset';
|
// readonly type = 'domainset';
|
||||||
readonly fileExtension = 'sgmodule';
|
readonly fileExtension = 'sgmodule';
|
||||||
type = '';
|
readonly type = '';
|
||||||
|
|
||||||
private rules = new Set<string>();
|
private rules = new Set<string>();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user