mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-12 17:20:35 +08:00
Feat: implement Clash Meta mrs format
This commit is contained in:
parent
03f1a0058e
commit
50ca0c5e9e
@ -53,7 +53,8 @@ export const buildAppleCdn = task(require.main === module, __filename)(async (sp
|
|||||||
domainset,
|
domainset,
|
||||||
'domainset',
|
'domainset',
|
||||||
path.resolve(__dirname, '../List/domainset/apple_cdn.conf'),
|
path.resolve(__dirname, '../List/domainset/apple_cdn.conf'),
|
||||||
path.resolve(__dirname, '../Clash/domainset/apple_cdn.txt')
|
path.resolve(__dirname, '../Clash/domainset/apple_cdn.txt'),
|
||||||
|
path.resolve(__dirname, '../Clash/clash_mrs_domain/apple_cdn.mrs')
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -78,7 +78,8 @@ export const buildCdnDownloadConf = task(require.main === module, __filename)(as
|
|||||||
sortDomains(domainDeduper(cdnDomainsList)),
|
sortDomains(domainDeduper(cdnDomainsList)),
|
||||||
'domainset',
|
'domainset',
|
||||||
path.resolve(__dirname, '../List/domainset/cdn.conf'),
|
path.resolve(__dirname, '../List/domainset/cdn.conf'),
|
||||||
path.resolve(__dirname, '../Clash/domainset/cdn.txt')
|
path.resolve(__dirname, '../Clash/domainset/cdn.txt'),
|
||||||
|
path.resolve(__dirname, '../Clash/clash_mrs_domain/cdn.mrs')
|
||||||
),
|
),
|
||||||
createRuleset(
|
createRuleset(
|
||||||
span,
|
span,
|
||||||
@ -92,7 +93,8 @@ export const buildCdnDownloadConf = task(require.main === module, __filename)(as
|
|||||||
sortDomains(domainDeduper(downloadDomainSet)),
|
sortDomains(domainDeduper(downloadDomainSet)),
|
||||||
'domainset',
|
'domainset',
|
||||||
path.resolve(__dirname, '../List/domainset/download.conf'),
|
path.resolve(__dirname, '../List/domainset/download.conf'),
|
||||||
path.resolve(__dirname, '../Clash/domainset/download.txt')
|
path.resolve(__dirname, '../Clash/domainset/download.txt'),
|
||||||
|
path.resolve(__dirname, '../Clash/clash_mrs_domain/download.mrs')
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -127,6 +127,8 @@ function transformDomainset(parentSpan: Span, sourcePath: string, relativePath:
|
|||||||
description = SHARED_DESCRIPTION;
|
description = SHARED_DESCRIPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clashFileBasename = relativePath.slice(0, -path.extname(relativePath).length);
|
||||||
|
|
||||||
return createRuleset(
|
return createRuleset(
|
||||||
span,
|
span,
|
||||||
title,
|
title,
|
||||||
@ -135,7 +137,7 @@ function transformDomainset(parentSpan: Span, sourcePath: string, relativePath:
|
|||||||
deduped,
|
deduped,
|
||||||
'domainset',
|
'domainset',
|
||||||
path.resolve(outputSurgeDir, relativePath),
|
path.resolve(outputSurgeDir, relativePath),
|
||||||
path.resolve(outputClashDir, `${relativePath.slice(0, -path.extname(relativePath).length)}.txt`)
|
path.resolve(outputClashDir, `${clashFileBasename}.txt`)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@ -191,7 +191,8 @@ export const buildRejectDomainSet = task(require.main === module, __filename)(as
|
|||||||
span.traceChildSync('sort reject domainset (base)', () => sortDomains(dudupedDominArray, domainArrayMainDomainMap, domainArraySubdomainMap)),
|
span.traceChildSync('sort reject domainset (base)', () => sortDomains(dudupedDominArray, domainArrayMainDomainMap, domainArraySubdomainMap)),
|
||||||
'domainset',
|
'domainset',
|
||||||
path.resolve(__dirname, '../List/domainset/reject.conf'),
|
path.resolve(__dirname, '../List/domainset/reject.conf'),
|
||||||
path.resolve(__dirname, '../Clash/domainset/reject.txt')
|
path.resolve(__dirname, '../Clash/domainset/reject.txt'),
|
||||||
|
path.resolve(__dirname, '../Clash/clash_mrs_domain/reject.mrs')
|
||||||
),
|
),
|
||||||
createRuleset(
|
createRuleset(
|
||||||
span,
|
span,
|
||||||
@ -211,7 +212,8 @@ export const buildRejectDomainSet = task(require.main === module, __filename)(as
|
|||||||
span.traceChildSync('sort reject domainset (extra)', () => sortDomains(dudupedDominArrayExtra, domainArrayMainDomainMap, domainArraySubdomainMap)),
|
span.traceChildSync('sort reject domainset (extra)', () => sortDomains(dudupedDominArrayExtra, domainArrayMainDomainMap, domainArraySubdomainMap)),
|
||||||
'domainset',
|
'domainset',
|
||||||
path.resolve(__dirname, '../List/domainset/reject_extra.conf'),
|
path.resolve(__dirname, '../List/domainset/reject_extra.conf'),
|
||||||
path.resolve(__dirname, '../Clash/domainset/reject_extra.txt')
|
path.resolve(__dirname, '../Clash/domainset/reject_extra.txt'),
|
||||||
|
path.resolve(__dirname, '../Clash/clash_mrs_domain/reject_extra.mrs')
|
||||||
),
|
),
|
||||||
compareAndWriteFile(
|
compareAndWriteFile(
|
||||||
span,
|
span,
|
||||||
|
|||||||
@ -251,6 +251,7 @@ export const buildSpeedtestDomainSet = task(require.main === module, __filename)
|
|||||||
deduped,
|
deduped,
|
||||||
'domainset',
|
'domainset',
|
||||||
path.resolve(__dirname, '../List/domainset/speedtest.conf'),
|
path.resolve(__dirname, '../List/domainset/speedtest.conf'),
|
||||||
path.resolve(__dirname, '../Clash/domainset/speedtest.txt')
|
path.resolve(__dirname, '../Clash/domainset/speedtest.txt'),
|
||||||
|
path.resolve(__dirname, '../Clash/clash_mrs_domain/speedtest.mrs')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
57
Build/lib/convert-clash-meta-mrs.ts
Normal file
57
Build/lib/convert-clash-meta-mrs.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
|
import fsp from 'fs/promises';
|
||||||
|
import { Readable } from 'stream';
|
||||||
|
import { pipeline } from 'stream/promises';
|
||||||
|
import zlib from 'zlib';
|
||||||
|
import { async as ezspawn } from '@jsdevtools/ez-spawn';
|
||||||
|
|
||||||
|
const mihomoBinaryDir = path.join(__dirname, '../../node_modules/.cache/mihomo');
|
||||||
|
const mihomoBinaryPath = path.join(mihomoBinaryDir, 'mihomo');
|
||||||
|
|
||||||
|
const mihomoBinaryUrl: Partial<Record<NodeJS.Platform, Partial<Record<NodeJS.Architecture, string>>>> = {
|
||||||
|
linux: {
|
||||||
|
x64: 'https://github.com/MetaCubeX/mihomo/releases/download/v1.18.7/mihomo-linux-amd64-compatible-v1.18.7.gz'
|
||||||
|
},
|
||||||
|
darwin: {
|
||||||
|
x64: 'https://github.com/MetaCubeX/mihomo/releases/download/v1.18.7/mihomo-darwin-amd64-v1.18.7.gz',
|
||||||
|
arm64: 'https://github.com/MetaCubeX/mihomo/releases/download/v1.18.7/mihomo-darwin-arm64-v1.18.7.gz'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ensureMihomoBinary = async () => {
|
||||||
|
await fsp.mkdir(mihomoBinaryDir, { recursive: true });
|
||||||
|
if (!fs.existsSync(mihomoBinaryPath)) {
|
||||||
|
const writeStream = fs.createWriteStream(mihomoBinaryPath);
|
||||||
|
|
||||||
|
const downloadUrl = mihomoBinaryUrl[process.platform]?.[process.arch];
|
||||||
|
if (!downloadUrl) {
|
||||||
|
throw new Error(`Unsupported platform: ${process.platform} ${process.arch}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await fetch(downloadUrl);
|
||||||
|
|
||||||
|
if (!res.ok || !res.body) {
|
||||||
|
throw new Error(`Failed to download mihomo binary: ${res.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const gunzip = zlib.createGunzip();
|
||||||
|
|
||||||
|
await pipeline(
|
||||||
|
Readable.fromWeb(res.body),
|
||||||
|
gunzip,
|
||||||
|
writeStream
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await fsp.chmod(mihomoBinaryPath, 0o755);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const convertClashMetaMrs = async (type: 'domain', format: 'text', input: string, output: string) => {
|
||||||
|
await ensureMihomoBinary();
|
||||||
|
|
||||||
|
const { stderr } = await ezspawn(mihomoBinaryPath, ['convert-ruleset', type, format, input, output]);
|
||||||
|
|
||||||
|
if (stderr) {
|
||||||
|
throw new Error(stderr);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -151,8 +151,10 @@ const MARK = 'this_ruleset_is_made_by_sukkaw.ruleset.skk.moe';
|
|||||||
export const createRuleset = (
|
export const createRuleset = (
|
||||||
parentSpan: Span,
|
parentSpan: Span,
|
||||||
title: string, description: string[] | readonly string[], date: Date, content: string[],
|
title: string, description: string[] | readonly string[], date: Date, content: string[],
|
||||||
type: ('ruleset' | 'domainset' | string & {}), surgePath: string, clashPath: string
|
type: ('ruleset' | 'domainset' | string & {}),
|
||||||
) => parentSpan.traceChild(`create ruleset: ${path.basename(surgePath, path.extname(surgePath))}`).traceAsyncFn((childSpan) => {
|
surgePath: string, clashPath: string,
|
||||||
|
clashMrsPath?: string
|
||||||
|
) => parentSpan.traceChild(`create ruleset: ${path.basename(surgePath, path.extname(surgePath))}`).traceAsyncFn(async (childSpan) => {
|
||||||
const surgeContent = withBannerArray(
|
const surgeContent = withBannerArray(
|
||||||
title, description, date,
|
title, description, date,
|
||||||
sortRuleSet(type === 'domainset'
|
sortRuleSet(type === 'domainset'
|
||||||
@ -174,8 +176,19 @@ export const createRuleset = (
|
|||||||
return withBannerArray(title, description, date, _clashContent);
|
return withBannerArray(title, description, date, _clashContent);
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all([
|
await Promise.all([
|
||||||
compareAndWriteFile(childSpan, surgeContent, surgePath),
|
compareAndWriteFile(childSpan, surgeContent, surgePath),
|
||||||
compareAndWriteFile(childSpan, clashContent, clashPath)
|
compareAndWriteFile(childSpan, clashContent, clashPath)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// if (clashMrsPath) {
|
||||||
|
// if (type === 'domainset') {
|
||||||
|
// await childSpan.traceChildAsync('clash meta mrs domain ' + clashMrsPath, async () => {
|
||||||
|
// await fs.promises.mkdir(path.dirname(clashMrsPath), { recursive: true });
|
||||||
|
// await convertClashMetaMrs(
|
||||||
|
// 'domain', 'text', clashPath, clashMrsPath
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
});
|
});
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cliqz/adblocker": "^1.31.1",
|
"@cliqz/adblocker": "^1.31.1",
|
||||||
|
"@jsdevtools/ez-spawn": "^3.0.4",
|
||||||
"async-retry": "^1.3.3",
|
"async-retry": "^1.3.3",
|
||||||
"async-sema": "^3.1.1",
|
"async-sema": "^3.1.1",
|
||||||
"better-sqlite3": "^11.1.2",
|
"better-sqlite3": "^11.1.2",
|
||||||
|
|||||||
25
pnpm-lock.yaml
generated
25
pnpm-lock.yaml
generated
@ -14,6 +14,9 @@ importers:
|
|||||||
'@cliqz/adblocker':
|
'@cliqz/adblocker':
|
||||||
specifier: ^1.31.1
|
specifier: ^1.31.1
|
||||||
version: 1.31.1
|
version: 1.31.1
|
||||||
|
'@jsdevtools/ez-spawn':
|
||||||
|
specifier: ^3.0.4
|
||||||
|
version: 3.0.4
|
||||||
async-retry:
|
async-retry:
|
||||||
specifier: ^1.3.3
|
specifier: ^1.3.3
|
||||||
version: 1.3.3
|
version: 1.3.3
|
||||||
@ -188,6 +191,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==}
|
resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==}
|
||||||
engines: {node: '>=18.18'}
|
engines: {node: '>=18.18'}
|
||||||
|
|
||||||
|
'@jsdevtools/ez-spawn@3.0.4':
|
||||||
|
resolution: {integrity: sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
'@napi-rs/wasm-runtime@0.2.4':
|
'@napi-rs/wasm-runtime@0.2.4':
|
||||||
resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==}
|
resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==}
|
||||||
|
|
||||||
@ -615,6 +622,9 @@ packages:
|
|||||||
buffer@5.7.1:
|
buffer@5.7.1:
|
||||||
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
||||||
|
|
||||||
|
call-me-maybe@1.0.2:
|
||||||
|
resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==}
|
||||||
|
|
||||||
callsites@3.1.0:
|
callsites@3.1.0:
|
||||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -1363,6 +1373,10 @@ packages:
|
|||||||
streamx@2.18.0:
|
streamx@2.18.0:
|
||||||
resolution: {integrity: sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==}
|
resolution: {integrity: sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==}
|
||||||
|
|
||||||
|
string-argv@0.3.2:
|
||||||
|
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
|
||||||
|
engines: {node: '>=0.6.19'}
|
||||||
|
|
||||||
string-similarity@4.0.4:
|
string-similarity@4.0.4:
|
||||||
resolution: {integrity: sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==}
|
resolution: {integrity: sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==}
|
||||||
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
|
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
|
||||||
@ -1634,6 +1648,13 @@ snapshots:
|
|||||||
|
|
||||||
'@humanwhocodes/retry@0.3.0': {}
|
'@humanwhocodes/retry@0.3.0': {}
|
||||||
|
|
||||||
|
'@jsdevtools/ez-spawn@3.0.4':
|
||||||
|
dependencies:
|
||||||
|
call-me-maybe: 1.0.2
|
||||||
|
cross-spawn: 7.0.3
|
||||||
|
string-argv: 0.3.2
|
||||||
|
type-detect: 4.0.8
|
||||||
|
|
||||||
'@napi-rs/wasm-runtime@0.2.4':
|
'@napi-rs/wasm-runtime@0.2.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@emnapi/core': 1.2.0
|
'@emnapi/core': 1.2.0
|
||||||
@ -2076,6 +2097,8 @@ snapshots:
|
|||||||
base64-js: 1.5.1
|
base64-js: 1.5.1
|
||||||
ieee754: 1.2.1
|
ieee754: 1.2.1
|
||||||
|
|
||||||
|
call-me-maybe@1.0.2: {}
|
||||||
|
|
||||||
callsites@3.1.0: {}
|
callsites@3.1.0: {}
|
||||||
|
|
||||||
camelcase@6.3.0: {}
|
camelcase@6.3.0: {}
|
||||||
@ -2884,6 +2907,8 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
bare-events: 2.4.2
|
bare-events: 2.4.2
|
||||||
|
|
||||||
|
string-argv@0.3.2: {}
|
||||||
|
|
||||||
string-similarity@4.0.4: {}
|
string-similarity@4.0.4: {}
|
||||||
|
|
||||||
string-width@4.2.3:
|
string-width@4.2.3:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user