diff --git a/backend/package.json b/backend/package.json index 4f03d36..8b8c305 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "sub-store", - "version": "2.14.373", + "version": "2.14.374", "description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.", "main": "src/main.js", "scripts": { diff --git a/backend/src/core/proxy-utils/index.js b/backend/src/core/proxy-utils/index.js index 15213e7..de8e5c3 100644 --- a/backend/src/core/proxy-utils/index.js +++ b/backend/src/core/proxy-utils/index.js @@ -244,21 +244,10 @@ function produce(proxies, targetPlatform, type, opts = {}) { $.log(`Producing proxies for target: ${targetPlatform}`); if (typeof producer.type === 'undefined' || producer.type === 'SINGLE') { - let localPort = 10000; let list = proxies .map((proxy) => { try { - let line = producer.produce(proxy, type, opts); - if ( - line.length > 0 && - line.includes('__SubStoreLocalPort__') - ) { - line = line.replace( - /__SubStoreLocalPort__/g, - localPort++, - ); - } - return line; + return producer.produce(proxy, type, opts); } catch (err) { $.error( `Cannot produce proxy: ${JSON.stringify( diff --git a/backend/src/core/proxy-utils/producers/clash.js b/backend/src/core/proxy-utils/producers/clash.js index 7311f6f..e172f6b 100644 --- a/backend/src/core/proxy-utils/producers/clash.js +++ b/backend/src/core/proxy-utils/producers/clash.js @@ -163,9 +163,11 @@ export default function Clash_Producer() { delete proxy.id; delete proxy.resolved; delete proxy['no-resolve']; - for (const key in proxy) { - if (proxy[key] == null || /^_/i.test(key)) { - delete proxy[key]; + if (type !== 'internal') { + for (const key in proxy) { + if (proxy[key] == null || /^_/i.test(key)) { + delete proxy[key]; + } } } if ( diff --git a/backend/src/core/proxy-utils/producers/clashmeta.js b/backend/src/core/proxy-utils/producers/clashmeta.js index 0a0a649..1e0dac8 100644 --- a/backend/src/core/proxy-utils/producers/clashmeta.js +++ b/backend/src/core/proxy-utils/producers/clashmeta.js @@ -178,9 +178,11 @@ export default function ClashMeta_Producer() { delete proxy.id; delete proxy.resolved; delete proxy['no-resolve']; - for (const key in proxy) { - if (proxy[key] == null || /^_/i.test(key)) { - delete proxy[key]; + if (type !== 'internal') { + for (const key in proxy) { + if (proxy[key] == null || /^_/i.test(key)) { + delete proxy[key]; + } } } if ( diff --git a/backend/src/core/proxy-utils/producers/shadowrocket.js b/backend/src/core/proxy-utils/producers/shadowrocket.js index f0e1c60..a47fa2d 100644 --- a/backend/src/core/proxy-utils/producers/shadowrocket.js +++ b/backend/src/core/proxy-utils/producers/shadowrocket.js @@ -181,9 +181,11 @@ export default function ShadowRocket_Producer() { delete proxy.id; delete proxy.resolved; delete proxy['no-resolve']; - for (const key in proxy) { - if (proxy[key] == null || /^_/i.test(key)) { - delete proxy[key]; + if (type !== 'internal') { + for (const key in proxy) { + if (proxy[key] == null || /^_/i.test(key)) { + delete proxy[key]; + } } } if ( diff --git a/backend/src/core/proxy-utils/producers/stash.js b/backend/src/core/proxy-utils/producers/stash.js index 0ebabd0..8d38563 100644 --- a/backend/src/core/proxy-utils/producers/stash.js +++ b/backend/src/core/proxy-utils/producers/stash.js @@ -272,9 +272,11 @@ export default function Stash_Producer() { delete proxy.id; delete proxy.resolved; delete proxy['no-resolve']; - for (const key in proxy) { - if (proxy[key] == null || /^_/i.test(key)) { - delete proxy[key]; + if (type !== 'internal') { + for (const key in proxy) { + if (proxy[key] == null || /^_/i.test(key)) { + delete proxy[key]; + } } } if ( diff --git a/backend/src/core/proxy-utils/producers/surgemac.js b/backend/src/core/proxy-utils/producers/surgemac.js index 83e0c8e..b52b5a4 100644 --- a/backend/src/core/proxy-utils/producers/surgemac.js +++ b/backend/src/core/proxy-utils/producers/surgemac.js @@ -1,5 +1,7 @@ +import { Base64 } from 'js-base64'; import { Result, isPresent } from './utils'; import Surge_Producer from './surge'; +import ClashMeta_Producer from './clashmeta'; import { isIPv4, isIPv6 } from '@/utils'; import $ from '@/core/app'; @@ -8,14 +10,22 @@ const targetPlatform = 'SurgeMac'; const surge_Producer = Surge_Producer(); export default function SurgeMac_Producer() { - const produce = (proxy) => { + const produce = (proxy, type, opts = {}) => { switch (proxy.type) { case 'external': return external(proxy); - case 'ssr': - return shadowsocksr(proxy); - default: - return surge_Producer.produce(proxy); + // case 'ssr': + // return shadowsocksr(proxy); + default: { + try { + return surge_Producer.produce(proxy, type, opts); + } catch (e) { + $.log( + `${proxy.name} is not supported on ${targetPlatform}, try to use Mihomo(SurgeMac - External Proxy Program) instead`, + ); + return mihomo(proxy, type, opts); + } + } } }; return { produce }; @@ -60,6 +70,7 @@ function external(proxy) { return result.toString(); } +// eslint-disable-next-line no-unused-vars function shadowsocksr(proxy) { const external_proxy = { ...proxy, @@ -101,6 +112,65 @@ function shadowsocksr(proxy) { return external(external_proxy); } +// eslint-disable-next-line no-unused-vars +function mihomo(proxy, type, opts) { + const clashProxy = ClashMeta_Producer().produce([proxy], 'internal')?.[0]; + if (clashProxy) { + const localPort = opts?.localPort || proxy._localPort || 65535; + const ipv6 = ['ipv4', 'v4-only'].includes(proxy['ip-version']) + ? false + : true; + const external_proxy = { + name: proxy.name, + type: 'external', + exec: proxy._exec || '/usr/local/bin/mihomo', + 'local-port': localPort, + args: [ + '-config', + Base64.encode( + JSON.stringify({ + 'mixed-port': localPort, + ipv6, + mode: 'global', + dns: { + enable: true, + ipv6, + nameserver: [ + 'https://223.6.6.6/dns-query', + 'https://120.53.53.53/dns-query', + ], + }, + proxies: [ + { + ...clashProxy, + name: 'proxy', + }, + ], + 'proxy-groups': [ + { + name: 'GLOBAL', + type: 'select', + proxies: ['proxy'], + }, + ], + }), + ), + ], + addresses: [], + }; + + // https://manual.nssurge.com/policy/external-proxy.html + if (isIP(proxy.server)) { + external_proxy.addresses.push(proxy.server); + } else { + $.log( + `Platform ${targetPlatform}, proxy type ${proxy.type}: addresses should be an IP address, but got ${proxy.server}`, + ); + } + opts.localPort = localPort - 1; + return external(external_proxy); + } +} function isIP(ip) { return isIPv4(ip) || isIPv6(ip);