From 85a3e2ee545ef4da01e4ec52c17845cbb0ab9dc2 Mon Sep 17 00:00:00 2001 From: xream Date: Fri, 3 Jan 2025 23:37:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=87=E4=BB=B6=E6=94=AF=E6=8C=81=20?= =?UTF-8?q?Mihomo=20=E9=85=8D=E7=BD=AE,=20=E6=94=AF=E6=8C=81=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E8=A6=86=E5=86=99;=20target=20=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E9=80=82=E9=85=8D=E5=A4=A7=E5=B0=8F=E5=86=99=E5=92=8C=E5=88=AB?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/package.json | 2 +- .../src/core/proxy-utils/processors/index.js | 92 ++++++++++++++++++- .../core/proxy-utils/producers/clashmeta.js | 2 +- .../src/core/proxy-utils/producers/index.js | 17 ++++ backend/src/restful/preview.js | 2 +- backend/src/restful/sync.js | 7 +- 6 files changed, 115 insertions(+), 7 deletions(-) diff --git a/backend/package.json b/backend/package.json index 182b79502..934d2ec56 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "sub-store", - "version": "2.16.2", + "version": "2.16.3", "description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.", "main": "src/main.js", "scripts": { diff --git a/backend/src/core/proxy-utils/processors/index.js b/backend/src/core/proxy-utils/processors/index.js index 5c59223cd..f024594a5 100644 --- a/backend/src/core/proxy-utils/processors/index.js +++ b/backend/src/core/proxy-utils/processors/index.js @@ -10,6 +10,7 @@ import { hex_md5 } from '@/vendor/md5'; import { ProxyUtils } from '@/core/proxy-utils'; import { produceArtifact } from '@/restful/sync'; import { SETTINGS_KEY } from '@/constants'; +import YAML from '@/utils/yaml'; import env from '@/utils/env'; import { @@ -21,6 +22,46 @@ import { getRmainingDays, } from '@/utils/flow'; +function isObject(item) { + return item && typeof item === 'object' && !Array.isArray(item); +} +function trimWrap(str) { + if (str.startsWith('<') && str.endsWith('>')) { + return str.slice(1, -1); + } + return str; +} +function deepMerge(target, _other) { + const other = typeof _other === 'string' ? JSON.parse(_other) : _other; + for (const key in other) { + if (isObject(other[key])) { + if (key.endsWith('!')) { + const k = trimWrap(key.slice(0, -1)); + target[k] = other[key]; + } else { + const k = trimWrap(key); + if (!target[k]) Object.assign(target, { [k]: {} }); + deepMerge(target[k], other[k]); + } + } else if (Array.isArray(other[key])) { + if (key.startsWith('+')) { + const k = trimWrap(key.slice(1)); + if (!target[k]) Object.assign(target, { [k]: [] }); + target[k] = [...other[key], ...target[k]]; + } else if (key.endsWith('+')) { + const k = trimWrap(key.slice(0, -1)); + if (!target[k]) Object.assign(target, { [k]: [] }); + target[k] = [...target[k], ...other[key]]; + } else { + const k = trimWrap(key); + Object.assign(target, { [k]: other[key] }); + } + } else { + Object.assign(target, { [key]: other[key] }); + } + } + return target; +} /** The rule "(name CONTAINS "🇨🇳") AND (port IN [80, 443])" can be expressed as follows: { @@ -321,6 +362,33 @@ function ScriptOperator(script, targetPlatform, $arguments, source, $options) { name: 'Script Operator', func: async (proxies) => { let output = proxies; + if (output?.$file?.type === 'mihomoProfile') { + try { + let patch = YAML.safeLoad(script); + if (typeof patch !== 'object') patch = {}; + output.$content = ProxyUtils.yaml.safeDump( + deepMerge( + { + proxies: await produceArtifact({ + type: + output?.$file?.sourceType || + 'collection', + name: output?.$file?.sourceName, + platform: 'mihomo', + produceType: 'internal', + produceOpts: { + 'delete-underscore-fields': true, + }, + }), + }, + patch, + ), + ); + return output; + } catch (e) { + // console.log(e); + } + } await (async function () { const operator = createDynamicFunction( 'operator', @@ -339,9 +407,27 @@ function ScriptOperator(script, targetPlatform, $arguments, source, $options) { 'operator', `async function operator(input = []) { if (input && (input.$files || input.$content)) { - let { $content, $files, $options } = input - ${script} - return { $content, $files, $options } + let { $content, $files, $options, $file } = input + if($file.type === 'mihomoProfile') { + ${script} + if(typeof main === 'function') { + const config = { + proxies: await produceArtifact({ + type: $file.sourceType || 'collection', + name: $file.sourceName, + platform: 'mihomo', + produceType: 'internal', + produceOpts: { + 'delete-underscore-fields': true + } + }), + } + $content = ProxyUtils.yaml.safeDump(await main(config)) + } + } else { + ${script} + } + return { $content, $files, $options, $file } } else { let proxies = input let list = [] diff --git a/backend/src/core/proxy-utils/producers/clashmeta.js b/backend/src/core/proxy-utils/producers/clashmeta.js index 3afe121fb..838fbe6c7 100644 --- a/backend/src/core/proxy-utils/producers/clashmeta.js +++ b/backend/src/core/proxy-utils/producers/clashmeta.js @@ -180,7 +180,7 @@ export default function ClashMeta_Producer() { delete proxy.id; delete proxy.resolved; delete proxy['no-resolve']; - if (type !== 'internal') { + if (type !== 'internal' || opts['delete-underscore-fields']) { for (const key in proxy) { if (proxy[key] == null || /^_/i.test(key)) { delete proxy[key]; diff --git a/backend/src/core/proxy-utils/producers/index.js b/backend/src/core/proxy-utils/producers/index.js index add3b2e62..2915a7757 100644 --- a/backend/src/core/proxy-utils/producers/index.js +++ b/backend/src/core/proxy-utils/producers/index.js @@ -20,20 +20,37 @@ function JSON_Producer() { } export default { + qx: QX_Producer(), QX: QX_Producer(), QuantumultX: QX_Producer(), + surge: Surge_Producer(), Surge: Surge_Producer(), SurgeMac: SurgeMac_Producer(), Loon: Loon_Producer(), Clash: Clash_Producer(), + meta: ClashMeta_Producer(), + clashmeta: ClashMeta_Producer(), + 'clash.meta': ClashMeta_Producer(), + 'Clash.Meta': ClashMeta_Producer(), ClashMeta: ClashMeta_Producer(), + mihomo: ClashMeta_Producer(), + Mihomo: ClashMeta_Producer(), + uri: URI_Producer(), URI: URI_Producer(), + v2: V2Ray_Producer(), + v2ray: V2Ray_Producer(), V2Ray: V2Ray_Producer(), + json: JSON_Producer(), JSON: JSON_Producer(), + stash: Stash_Producer(), Stash: Stash_Producer(), + shadowrocket: Shadowrocket_Producer(), Shadowrocket: Shadowrocket_Producer(), ShadowRocket: Shadowrocket_Producer(), + surfboard: Surfboard_Producer(), Surfboard: Surfboard_Producer(), + singbox: singbox_Producer(), 'sing-box': singbox_Producer(), + egern: Egern_Producer(), Egern: Egern_Producer(), }; diff --git a/backend/src/restful/preview.js b/backend/src/restful/preview.js index 20c0a6354..daabd1fac 100644 --- a/backend/src/restful/preview.js +++ b/backend/src/restful/preview.js @@ -67,7 +67,7 @@ async function previewFile(req, res) { const processed = Array.isArray(file.process) && file.process.length > 0 ? await ProxyUtils.process( - { $files: files, $content: filesContent }, + { $files: files, $content: filesContent, $file: file }, file.process, ) : { $content: filesContent, $files: files }; diff --git a/backend/src/restful/sync.js b/backend/src/restful/sync.js index ea09b1254..d209091f6 100644 --- a/backend/src/restful/sync.js +++ b/backend/src/restful/sync.js @@ -512,7 +512,12 @@ async function produceArtifact({ const processed = Array.isArray(file.process) && file.process.length > 0 ? await ProxyUtils.process( - { $files: files, $content: filesContent, $options }, + { + $files: files, + $content: filesContent, + $options, + $file: file, + }, file.process, ) : { $content: filesContent, $files: files, $options };