Feat: implement Clash Meta mrs format

This commit is contained in:
SukkaW
2024-08-06 19:10:29 +08:00
parent 03f1a0058e
commit 50ca0c5e9e
9 changed files with 114 additions and 10 deletions

View 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);
}
};

View File

@@ -151,8 +151,10 @@ const MARK = 'this_ruleset_is_made_by_sukkaw.ruleset.skk.moe';
export const createRuleset = (
parentSpan: Span,
title: string, description: string[] | readonly string[], date: Date, content: string[],
type: ('ruleset' | 'domainset' | string & {}), surgePath: string, clashPath: string
) => parentSpan.traceChild(`create ruleset: ${path.basename(surgePath, path.extname(surgePath))}`).traceAsyncFn((childSpan) => {
type: ('ruleset' | 'domainset' | string & {}),
surgePath: string, clashPath: string,
clashMrsPath?: string
) => parentSpan.traceChild(`create ruleset: ${path.basename(surgePath, path.extname(surgePath))}`).traceAsyncFn(async (childSpan) => {
const surgeContent = withBannerArray(
title, description, date,
sortRuleSet(type === 'domainset'
@@ -174,8 +176,19 @@ export const createRuleset = (
return withBannerArray(title, description, date, _clashContent);
});
return Promise.all([
await Promise.all([
compareAndWriteFile(childSpan, surgeContent, surgePath),
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
// );
// });
// }
// }
});