From 710780456ac825b2b8bc549b01740a466205df83 Mon Sep 17 00:00:00 2001 From: pompurin404 Date: Tue, 15 Oct 2024 13:50:19 +0800 Subject: [PATCH] set proxy for Sub-Store and support control whether allow LAN connections to Sub-Store --- changelog.md | 7 +- src/main/resolve/server.ts | 45 ++- src/main/utils/init.ts | 9 +- src/main/utils/ipc.ts | 17 +- .../components/settings/substore-config.tsx | 295 ++++++++++-------- src/renderer/src/pages/mihomo.tsx | 8 +- src/renderer/src/utils/ipc.ts | 16 +- src/shared/types.d.ts | 1 + 8 files changed, 249 insertions(+), 149 deletions(-) diff --git a/changelog.md b/changelog.md index 62b65c1..a9b3c41 100644 --- a/changelog.md +++ b/changelog.md @@ -1,8 +1,9 @@ ### New Features -- 支持多个订阅切换分别保存选择的节点 -- 支持在对话框直接拖动窗口 +- Sub-Store 请求默认经过内核代理 +- 允许控制是否允许局域网连接 Sub-Store +- 全局模式时自动置顶 GLOBAL 代理组 ### Bug Fixes -- 修复订阅显示样式错误 +- 修复下拉菜单组件样式异常 diff --git a/src/main/resolve/server.ts b/src/main/resolve/server.ts index d1597d3..7cdaa71 100644 --- a/src/main/resolve/server.ts +++ b/src/main/resolve/server.ts @@ -11,6 +11,8 @@ import express from 'express' export let pacPort: number export let subStorePort: number export let subStoreFrontendPort: number +let subStoreFrontendServer: http.Server +let subStoreBackendWorker: Worker const defaultPacScript = ` function FindProxyForURL(url, host) { @@ -56,28 +58,42 @@ export async function startPacServer(): Promise { server.unref() } -export async function startSubStoreServer(): Promise { +export async function startSubStoreFrontendServer(): Promise { + const { useSubStore = true, subStoreHost = '127.0.0.1' } = await getAppConfig() + if (!useSubStore) return + await stopSubStoreFrontendServer() + subStoreFrontendPort = await findAvailablePort(14122) + const app = express() + app.use(express.static(path.join(resourcesFilesDir(), 'sub-store-frontend'))) + subStoreFrontendServer = app.listen(subStoreFrontendPort, subStoreHost) +} + +export async function stopSubStoreFrontendServer(): Promise { + if (subStoreFrontendServer) { + subStoreFrontendServer.close() + } +} + +export async function startSubStoreBackendServer(): Promise { const { useSubStore = true, useCustomSubStore = false, + subStoreHost = '127.0.0.1', subStoreBackendSyncCron = '', subStoreBackendDownloadCron = '', subStoreBackendUploadCron = '' } = await getAppConfig() + const { 'mixed-port': port = 7890 } = await getControledMihomoConfig() if (!useSubStore) return - if (!subStoreFrontendPort) { - subStoreFrontendPort = await findAvailablePort(14122) - const app = express() - app.use(express.static(path.join(resourcesFilesDir(), 'sub-store-frontend'))) - app.listen(subStoreFrontendPort) - } - if (!useCustomSubStore && !subStorePort) { + if (!useCustomSubStore) { + await stopSubStoreBackendServer() subStorePort = await findAvailablePort(38324) const icon = nativeImage.createFromPath(subStoreIcon) icon.toDataURL() - new Worker(path.join(resourcesFilesDir(), 'sub-store.bundle.js'), { + subStoreBackendWorker = new Worker(path.join(resourcesFilesDir(), 'sub-store.bundle.js'), { env: { SUB_STORE_BACKEND_API_PORT: subStorePort.toString(), + SUB_STORE_BACKEND_API_HOST: subStoreHost, SUB_STORE_DATA_BASE_PATH: subStoreDir(), SUB_STORE_BACKEND_CUSTOM_ICON: icon.toDataURL(), SUB_STORE_BACKEND_CUSTOM_NAME: 'Mihomo Party', @@ -85,8 +101,17 @@ export async function startSubStoreServer(): Promise { SUB_STORE_BACKEND_DOWNLOAD_CRON: subStoreBackendDownloadCron, SUB_STORE_BACKEND_UPLOAD_CRON: subStoreBackendUploadCron, SUB_STORE_MMDB_COUNTRY_PATH: path.join(mihomoWorkDir(), 'country.mmdb'), - SUB_STORE_MMDB_ASN_PATH: path.join(mihomoWorkDir(), 'ASN.mmdb') + SUB_STORE_MMDB_ASN_PATH: path.join(mihomoWorkDir(), 'ASN.mmdb'), + HTTP_PROXY: `http://127.0.0.1:${port}`, + HTTPS_PROXY: `http://127.0.0.1:${port}`, + ALL_PROXY: `http://127.0.0.1:${port}` } }) } } + +export async function stopSubStoreBackendServer(): Promise { + if (subStoreBackendWorker) { + subStoreBackendWorker.terminate() + } +} diff --git a/src/main/utils/init.ts b/src/main/utils/init.ts index f1bc548..632d16e 100644 --- a/src/main/utils/init.ts +++ b/src/main/utils/init.ts @@ -25,7 +25,11 @@ import yaml from 'yaml' import { mkdir, writeFile, copyFile, rm, readdir } from 'fs/promises' import { existsSync } from 'fs' import path from 'path' -import { startPacServer, startSubStoreServer } from '../resolve/server' +import { + startPacServer, + startSubStoreBackendServer, + startSubStoreFrontendServer +} from '../resolve/server' import { triggerSysProxy } from '../sys/sysproxy' import { getAppConfig, @@ -231,7 +235,8 @@ export async function init(): Promise { await initFiles() await cleanup() await startPacServer() - await startSubStoreServer() + await startSubStoreFrontendServer() + await startSubStoreBackendServer() const { sysProxy } = await getAppConfig() try { await triggerSysProxy(sysProxy.enable) diff --git a/src/main/utils/ipc.ts b/src/main/utils/ipc.ts index dc81812..b5a382b 100644 --- a/src/main/utils/ipc.ts +++ b/src/main/utils/ipc.ts @@ -43,7 +43,14 @@ import { setOverride, updateOverrideItem } from '../config' -import { startSubStoreServer, subStoreFrontendPort, subStorePort } from '../resolve/server' +import { + startSubStoreFrontendServer, + startSubStoreBackendServer, + stopSubStoreFrontendServer, + stopSubStoreBackendServer, + subStoreFrontendPort, + subStorePort +} from '../resolve/server' import { isEncryptionAvailable, manualGrantCorePermition, @@ -190,7 +197,13 @@ export function registerIpcMainHandlers(): void { ipcMain.handle('registerShortcut', (_e, oldShortcut, newShortcut, action) => ipcErrorWrapper(registerShortcut)(oldShortcut, newShortcut, action) ) - ipcMain.handle('startSubStoreServer', () => ipcErrorWrapper(startSubStoreServer)()) + ipcMain.handle('startSubStoreFrontendServer', () => + ipcErrorWrapper(startSubStoreFrontendServer)() + ) + ipcMain.handle('stopSubStoreFrontendServer', () => ipcErrorWrapper(stopSubStoreFrontendServer)()) + ipcMain.handle('startSubStoreBackendServer', () => ipcErrorWrapper(startSubStoreBackendServer)()) + ipcMain.handle('stopSubStoreBackendServer', () => ipcErrorWrapper(stopSubStoreBackendServer)()) + ipcMain.handle('subStorePort', () => subStorePort) ipcMain.handle('subStoreFrontendPort', () => subStoreFrontendPort) ipcMain.handle('subStoreSubs', () => ipcErrorWrapper(subStoreSubs)()) diff --git a/src/renderer/src/components/settings/substore-config.tsx b/src/renderer/src/components/settings/substore-config.tsx index b43c8d5..0045797 100644 --- a/src/renderer/src/components/settings/substore-config.tsx +++ b/src/renderer/src/components/settings/substore-config.tsx @@ -2,7 +2,12 @@ import React, { useState } from 'react' import SettingCard from '@renderer/components/base/base-setting-card' import SettingItem from '@renderer/components/base/base-setting-item' import { Button, Input, Switch } from '@nextui-org/react' -import { startSubStoreServer } from '@renderer/utils/ipc' +import { + startSubStoreFrontendServer, + startSubStoreBackendServer, + stopSubStoreFrontendServer, + stopSubStoreBackendServer +} from '@renderer/utils/ipc' import { useAppConfig } from '@renderer/hooks/use-app-config' import debounce from '@renderer/utils/debounce' import { isValidCron } from 'cron-validator' @@ -12,6 +17,7 @@ const SubStoreConfig: React.FC = () => { const { useSubStore = true, useCustomSubStore = false, + subStoreHost = '127.0.0.1', customSubStoreUrl, subStoreBackendSyncCron, subStoreBackendDownloadCron, @@ -31,14 +37,20 @@ const SubStoreConfig: React.FC = () => { useState(subStoreBackendUploadCron) return ( - + { try { await patchAppConfig({ useSubStore: v }) - if (v) await startSubStoreServer() + if (v) { + await startSubStoreFrontendServer() + await startSubStoreBackendServer() + } else { + await stopSubStoreFrontendServer() + await stopSubStoreBackendServer() + } } catch (e) { alert(e) } @@ -46,138 +58,163 @@ const SubStoreConfig: React.FC = () => { /> {useSubStore && ( - - { - try { - await patchAppConfig({ useCustomSubStore: v }) - if (!v) await startSubStoreServer() - } catch (e) { - alert(e) - } - }} - /> - - )} - {useCustomSubStore ? ( - - { - setCustomSubStoreUrlValue(v) - setCustomSubStoreUrl(v) - }} - /> - - ) : ( <> - -
- {subStoreBackendSyncCronValue !== subStoreBackendSyncCron && ( - - )} + + { + try { + if (v) { + await patchAppConfig({ subStoreHost: '0.0.0.0' }) + } else { + await patchAppConfig({ subStoreHost: '127.0.0.1' }) + } + await startSubStoreFrontendServer() + await startSubStoreBackendServer() + } catch (e) { + alert(e) + } + }} + /> + + + { + try { + await patchAppConfig({ useCustomSubStore: v }) + if (v) { + await stopSubStoreBackendServer() + } else { + await startSubStoreBackendServer() + } + } catch (e) { + alert(e) + } + }} + /> + + {useCustomSubStore ? ( + { - setSubStoreBackendSyncCronValue(v) + setCustomSubStoreUrlValue(v) + setCustomSubStoreUrl(v) }} /> -
-
- -
- {subStoreBackendDownloadCronValue !== subStoreBackendDownloadCron && ( - - )} - { - setSubStoreBackendDownloadCronValue(v) - }} - /> -
-
- -
- {subStoreBackendUploadCronValue !== subStoreBackendUploadCron && ( - - )} - { - setSubStoreBackendUploadCronValue(v) - }} - /> -
-
+
+ ) : ( + <> + +
+ {subStoreBackendSyncCronValue !== subStoreBackendSyncCron && ( + + )} + { + setSubStoreBackendSyncCronValue(v) + }} + /> +
+
+ +
+ {subStoreBackendDownloadCronValue !== subStoreBackendDownloadCron && ( + + )} + { + setSubStoreBackendDownloadCronValue(v) + }} + /> +
+
+ +
+ {subStoreBackendUploadCronValue !== subStoreBackendUploadCron && ( + + )} + { + setSubStoreBackendUploadCronValue(v) + }} + /> +
+
+ + )} )}
diff --git a/src/renderer/src/pages/mihomo.tsx b/src/renderer/src/pages/mihomo.tsx index a0fffec..55b5004 100644 --- a/src/renderer/src/pages/mihomo.tsx +++ b/src/renderer/src/pages/mihomo.tsx @@ -8,7 +8,12 @@ import { platform } from '@renderer/utils/init' import { FaNetworkWired } from 'react-icons/fa' import { IoMdCloudDownload } from 'react-icons/io' import PubSub from 'pubsub-js' -import { mihomoUpgrade, restartCore, triggerSysProxy } from '@renderer/utils/ipc' +import { + mihomoUpgrade, + restartCore, + startSubStoreBackendServer, + triggerSysProxy +} from '@renderer/utils/ipc' import React, { useState } from 'react' import InterfaceModal from '@renderer/components/mihomo/interface-modal' import { MdDeleteForever } from 'react-icons/md' @@ -129,6 +134,7 @@ const Mihomo: React.FC = () => { className="mr-2" onPress={async () => { await onChangeNeedRestart({ 'mixed-port': mixedPortInput }) + await startSubStoreBackendServer() if (sysProxy?.enable) { triggerSysProxy(true) } diff --git a/src/renderer/src/utils/ipc.ts b/src/renderer/src/utils/ipc.ts index 9903bde..90aa6fc 100644 --- a/src/renderer/src/utils/ipc.ts +++ b/src/renderer/src/utils/ipc.ts @@ -307,8 +307,20 @@ export async function getGistUrl(): Promise { return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('getGistUrl')) } -export async function startSubStoreServer(): Promise { - return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('startSubStoreServer')) +export async function startSubStoreFrontendServer(): Promise { + return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('startSubStoreFrontendServer')) +} + +export async function stopSubStoreFrontendServer(): Promise { + return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('stopSubStoreFrontendServer')) +} + +export async function startSubStoreBackendServer(): Promise { + return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('startSubStoreBackendServer')) +} + +export async function stopSubStoreBackendServer(): Promise { + return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('stopSubStoreBackendServer')) } export async function subStorePort(): Promise { diff --git a/src/shared/types.d.ts b/src/shared/types.d.ts index c9a9d9f..c617a1f 100644 --- a/src/shared/types.d.ts +++ b/src/shared/types.d.ts @@ -231,6 +231,7 @@ interface IAppConfig { tunCardStatus?: CardStatus githubToken?: string useSubStore: boolean + subStoreHost?: string subStoreBackendSyncCron?: string subStoreBackendDownloadCron?: string subStoreBackendUploadCron?: string