🏗️ refactor proxy handling to replace stcpModel with visitorsModel and enhance configuration structure in ServerService
This commit is contained in:
parent
f0d8c20f4d
commit
20f1fe8318
@ -1,337 +0,0 @@
|
||||
// import { app, dialog, ipcMain, shell } from "electron";
|
||||
// import { clearConfig, getConfig, saveConfig } from "../storage/config";
|
||||
// import { clearVersion, listVersion } from "../storage/version";
|
||||
// import { genIniConfig, genTomlConfig, stopFrpcProcess } from "./frpc";
|
||||
// import { clearProxy, insertProxy, listProxy } from "../storage/proxy";
|
||||
// import path from "path";
|
||||
// import fs from "fs";
|
||||
// import { logDebug, logError, logInfo, LogModule, logWarn } from "../utils/log";
|
||||
//
|
||||
// const toml = require("@iarna/toml");
|
||||
// const { v4: uuidv4 } = require("uuid");
|
||||
//
|
||||
// export const initConfigApi = win => {
|
||||
// ipcMain.on("config.saveConfig", async (event, args) => {
|
||||
// logInfo(LogModule.APP, "Attempting to save configuration.");
|
||||
// saveConfig(args, (err, numberOfUpdated, upsert) => {
|
||||
// if (!err) {
|
||||
// const start = args.systemSelfStart || false;
|
||||
// logDebug(LogModule.APP, "Startup status set to: " + start);
|
||||
// app.setLoginItemSettings({
|
||||
// openAtLogin: start, //win
|
||||
// openAsHidden: start //macOs
|
||||
// });
|
||||
// logInfo(LogModule.APP, "Configuration saved successfully.");
|
||||
// } else {
|
||||
// logError(LogModule.APP, `Error saving configuration: ${err}`);
|
||||
// }
|
||||
// event.reply("Config.saveConfig.hook", {
|
||||
// err: err,
|
||||
// numberOfUpdated: numberOfUpdated,
|
||||
// upsert: upsert
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// ipcMain.on("config.getConfig", async (event, args) => {
|
||||
// logInfo(LogModule.APP, "Requesting configuration.");
|
||||
// getConfig((err, doc) => {
|
||||
// if (err) {
|
||||
// logError(LogModule.APP, `Error retrieving configuration: ${err}`);
|
||||
// }
|
||||
// event.reply("Config.getConfig.hook", {
|
||||
// err: err,
|
||||
// data: doc
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// ipcMain.on("config.versions", event => {
|
||||
// logInfo(LogModule.APP, "Requesting version information.");
|
||||
// listVersion((err, doc) => {
|
||||
// if (err) {
|
||||
// logError(LogModule.APP, `Error retrieving version information: ${err}`);
|
||||
// }
|
||||
// event.reply("Config.versions.hook", {
|
||||
// err: err,
|
||||
// data: doc
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// ipcMain.on("config.hasConfig", event => {
|
||||
// logInfo(LogModule.APP, "Checking if configuration exists.");
|
||||
// getConfig((err, doc) => {
|
||||
// if (err) {
|
||||
// logError(LogModule.APP, `Error checking configuration: ${err}`);
|
||||
// }
|
||||
// event.reply("Config.getConfig.hook", {
|
||||
// err: err,
|
||||
// data: doc
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// ipcMain.on("config.exportConfig", async (event, args) => {
|
||||
// logInfo(LogModule.APP, "Attempting to export configuration.");
|
||||
// const result = await dialog.showOpenDialog({
|
||||
// properties: ["openDirectory"]
|
||||
// });
|
||||
// const outputDirectory = result.filePaths[0];
|
||||
// if (!outputDirectory) {
|
||||
// logWarn(LogModule.APP, "Export canceled by user.");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// `Exporting configuration to directory ${outputDirectory} with type: ${args}`
|
||||
// );
|
||||
// getConfig((err1, config) => {
|
||||
// if (!err1 && config) {
|
||||
// listProxy((err2, proxys) => {
|
||||
// if (!err2) {
|
||||
// let configContent = "";
|
||||
// if (args === "ini") {
|
||||
// configContent = genIniConfig(config, proxys);
|
||||
// } else if (args === "toml") {
|
||||
// configContent = genTomlConfig(config, proxys);
|
||||
// }
|
||||
// const configPath = path.join(
|
||||
// outputDirectory,
|
||||
// `frpc-desktop.${args}`
|
||||
// );
|
||||
// fs.writeFile(
|
||||
// configPath, // 配置文件目录
|
||||
// configContent, // 配置文件内容
|
||||
// { flag: "w" },
|
||||
// err => {
|
||||
// if (err) {
|
||||
// logError(
|
||||
// LogModule.APP,
|
||||
// `Error writing configuration file: ${err}`
|
||||
// );
|
||||
// event.reply("config.exportConfig.hook", {
|
||||
// data: "导出错误",
|
||||
// err: err
|
||||
// });
|
||||
// } else {
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// "Configuration exported successfully."
|
||||
// );
|
||||
// event.reply("Config.exportConfig.hook", {
|
||||
// data: {
|
||||
// configPath: configPath
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// } else {
|
||||
// logError(LogModule.APP, `Error listing proxies: ${err2}`);
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// logError(LogModule.APP, `Error retrieving configuration: ${err1}`);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// const parseTomlConfig = (tomlPath: string) => {
|
||||
// logInfo(LogModule.APP, `Parsing TOML configuration from ${tomlPath}`);
|
||||
// const importConfigPath = tomlPath;
|
||||
// const tomlData = fs.readFileSync(importConfigPath, "utf-8");
|
||||
// logInfo(LogModule.APP, "Configuration content read successfully.");
|
||||
// const sourceConfig = toml.parse(tomlData);
|
||||
// // 解析config
|
||||
// const targetConfig: FrpConfig = {
|
||||
// currentVersion: null,
|
||||
// serverAddr: sourceConfig.serverAddr || "",
|
||||
// serverPort: sourceConfig.serverPort || "",
|
||||
// authMethod: sourceConfig?.user
|
||||
// ? "multiuser"
|
||||
// : sourceConfig?.auth?.method || "",
|
||||
// authToken: sourceConfig?.auth?.token || "",
|
||||
// transportHeartbeatInterval:
|
||||
// sourceConfig?.transport?.heartbeatInterval || 30,
|
||||
// transportHeartbeatTimeout:
|
||||
// sourceConfig?.transport?.heartbeatTimeout || 90,
|
||||
// tlsConfigEnable: sourceConfig?.transport?.tls?.enable || false,
|
||||
// tlsConfigCertFile: sourceConfig?.transport?.tls?.certFile || "",
|
||||
// tlsConfigKeyFile: sourceConfig?.transport?.tls?.keyFile || "",
|
||||
// tlsConfigServerName: sourceConfig?.transport?.tls?.serverName || "",
|
||||
// tlsConfigTrustedCaFile: sourceConfig?.transport?.tls?.trustedCaFile || "",
|
||||
// logLevel: sourceConfig?.log?.level || "info",
|
||||
// logMaxDays: sourceConfig?.log?.maxDays || 3,
|
||||
// proxyConfigProxyUrl: sourceConfig?.transport?.proxyURL || "",
|
||||
// proxyConfigEnable: Boolean(sourceConfig?.transport?.proxyURL) || false,
|
||||
// user: sourceConfig?.user || "",
|
||||
// metaToken: sourceConfig?.metadatas?.token || "",
|
||||
// systemSelfStart: false,
|
||||
// systemStartupConnect: false,
|
||||
// systemSilentStartup: false,
|
||||
// webEnable: true,
|
||||
// webPort: sourceConfig?.webServer?.port || 57400,
|
||||
// transportProtocol: sourceConfig?.transport?.protocol || "tcp",
|
||||
// transportDialServerTimeout:
|
||||
// sourceConfig?.transport?.dialServerTimeout || 10,
|
||||
// transportDialServerKeepalive:
|
||||
// sourceConfig?.transport?.dialServerKeepalive || 70,
|
||||
// transportPoolCount: sourceConfig?.transport?.poolCount || 0,
|
||||
// transportTcpMux: sourceConfig?.transport?.tcpMux || true,
|
||||
// transportTcpMuxKeepaliveInterval:
|
||||
// sourceConfig?.transport?.tcpMuxKeepaliveInterval || 7200
|
||||
// };
|
||||
// let frpcProxys = [];
|
||||
// // 解析proxy
|
||||
// if (sourceConfig?.proxies && sourceConfig.proxies.length > 0) {
|
||||
// const frpcProxys1 = sourceConfig.proxies.map(m => {
|
||||
// const rm: Proxy = {
|
||||
// _id: uuidv4(),
|
||||
// name: m?.name,
|
||||
// type: m?.type,
|
||||
// localIp: m?.localIP || "",
|
||||
// localPort: m?.localPort || null,
|
||||
// remotePort: m?.remotePort || null,
|
||||
// customDomains: m?.customDomains || [],
|
||||
// subdomain: m.subdomain || "",
|
||||
// basicAuth: m.basicAuth || false,
|
||||
// httpUser: m.httpUser || "",
|
||||
// httpPassword: m.httpPassword || "",
|
||||
// // 以下为stcp参数
|
||||
// visitorsModel: "visitorsProvider",
|
||||
// serverName: "",
|
||||
// secretKey: m?.secretKey || "",
|
||||
// bindAddr: "",
|
||||
// bindPort: null,
|
||||
// status: m?.status || true,
|
||||
// fallbackTo: m?.fallbackTo,
|
||||
// fallbackTimeoutMs: m?.fallbackTimeoutMs || 500,
|
||||
// keepTunnelOpen: m?.keepTunnelOpen || false,
|
||||
// https2http: m?.https2http || false,
|
||||
// https2httpCaFile: m?.https2httpCaFile || "",
|
||||
// https2httpKeyFile: m?.https2httpKeyFile || ""
|
||||
// };
|
||||
// return rm;
|
||||
// });
|
||||
// frpcProxys = [...frpcProxys, ...frpcProxys1];
|
||||
// logInfo(LogModule.APP, "Parsed proxies from configuration.");
|
||||
// }
|
||||
// // 解析stcp的访问者
|
||||
// if (sourceConfig?.visitors && sourceConfig.visitors.length > 0) {
|
||||
// const frpcProxys2 = sourceConfig.visitors.map(m => {
|
||||
// const rm: Proxy = {
|
||||
// _id: uuidv4(),
|
||||
// name: m?.name,
|
||||
// type: m?.type,
|
||||
// localIp: "",
|
||||
// localPort: null,
|
||||
// remotePort: null,
|
||||
// customDomains: [],
|
||||
// subdomain: m.subdomain || "",
|
||||
// basicAuth: m.basicAuth || false,
|
||||
// httpUser: m.httpUser || "",
|
||||
// httpPassword: m.httpPassword || "",
|
||||
// // 以下为stcp参数
|
||||
// visitorsModel: "visitors",
|
||||
// serverName: m?.serverName,
|
||||
// secretKey: m?.secretKey || "",
|
||||
// bindAddr: m?.bindAddr,
|
||||
// bindPort: m?.bindPort,
|
||||
// status: m?.status || true,
|
||||
// fallbackTo: m?.fallbackTo,
|
||||
// fallbackTimeoutMs: m?.fallbackTimeoutMs || 500,
|
||||
// keepTunnelOpen: m?.keepTunnelOpen || false,
|
||||
// https2http: m?.https2http || false,
|
||||
// https2httpCaFile: m?.https2httpCaFile || "",
|
||||
// https2httpKeyFile: m?.https2httpKeyFile || ""
|
||||
// };
|
||||
// return rm;
|
||||
// });
|
||||
// frpcProxys = [...frpcProxys, ...frpcProxys2];
|
||||
// logInfo(LogModule.APP, "Parsed visitors from configuration.");
|
||||
// }
|
||||
// if (targetConfig) {
|
||||
// clearConfig(() => {
|
||||
// logInfo(LogModule.APP, "Clearing existing configuration.");
|
||||
// saveConfig(targetConfig);
|
||||
// logInfo(LogModule.APP, "New configuration saved.");
|
||||
// });
|
||||
// }
|
||||
// if (frpcProxys && frpcProxys.length > 0) {
|
||||
// clearProxy(() => {
|
||||
// frpcProxys.forEach(f => {
|
||||
// insertProxy(f, err => {
|
||||
// if (err) {
|
||||
// logError(LogModule.APP, `Error inserting proxy: ${err}`);
|
||||
// } else {
|
||||
// logInfo(LogModule.APP, `Inserted proxy: ${JSON.stringify(f)}`);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// ipcMain.on("config.importConfig", async (event, args) => {
|
||||
// logInfo(LogModule.APP, "Attempting to import configuration.");
|
||||
// const result = await dialog.showOpenDialog(win, {
|
||||
// properties: ["openFile"],
|
||||
// filters: [
|
||||
// { name: "FrpcConfig Files", extensions: ["toml", "ini"] } // 允许选择的文件类型
|
||||
// ]
|
||||
// });
|
||||
// if (result.canceled) {
|
||||
// logWarn(LogModule.APP, "Import canceled by user.");
|
||||
// return;
|
||||
// } else {
|
||||
// const filePath = result.filePaths[0];
|
||||
// const fileExtension = path.extname(filePath); // 获取文件后缀名
|
||||
// logWarn(
|
||||
// LogModule.APP,
|
||||
// `Importing file ${filePath} with extension ${fileExtension}`
|
||||
// );
|
||||
// if (fileExtension === ".toml") {
|
||||
// parseTomlConfig(filePath);
|
||||
// event.reply("Config.importConfig.hook", {
|
||||
// success: true
|
||||
// });
|
||||
// } else {
|
||||
// logError(
|
||||
// LogModule.APP,
|
||||
// `Import failed, unsupported file format: ${fileExtension}`
|
||||
// );
|
||||
// event.reply("Config.importConfig.hook", {
|
||||
// success: false,
|
||||
// data: `导入失败,暂不支持 ${fileExtension} 格式文件`
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// ipcMain.on("config.clearAll", async (event, args) => {
|
||||
// logInfo(LogModule.APP, "Clearing all configurations.");
|
||||
// stopFrpcProcess(() => {
|
||||
// clearConfig();
|
||||
// clearProxy();
|
||||
// clearVersion();
|
||||
// event.reply("Config.clearAll.hook", {});
|
||||
// logInfo(LogModule.APP, "All configurations cleared.");
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// ipcMain.on("config.openDataFolder", async (event, args) => {
|
||||
// const userDataPath = app.getPath("userData");
|
||||
// logInfo(LogModule.APP, "Attempting to open data folder.");
|
||||
// shell.openPath(userDataPath).then(errorMessage => {
|
||||
// if (errorMessage) {
|
||||
// logError(LogModule.APP, `Failed to open data folder: ${errorMessage}`);
|
||||
// event.reply("Config.openDataFolder.hook", false);
|
||||
// } else {
|
||||
// logInfo(LogModule.APP, "Data folder opened successfully.");
|
||||
// event.reply("Config.openDataFolder.hook", true);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// };
|
@ -1,21 +0,0 @@
|
||||
// import {dialog, ipcMain} from "electron";
|
||||
// import { logInfo, logError, LogModule } from "../utils/log";
|
||||
//
|
||||
// export const initFileApi = () => {
|
||||
// ipcMain.handle("file.selectFile", async (event, args) => {
|
||||
// logInfo(LogModule.APP, `Attempting to open file dialog with filters: ${JSON.stringify(args)}`);
|
||||
// try {
|
||||
// const result = dialog.showOpenDialogSync({
|
||||
// properties: ['openFile'],
|
||||
// filters: [
|
||||
// { name: 'Text Files', extensions: args },
|
||||
// ]
|
||||
// });
|
||||
// logInfo(LogModule.APP, `File dialog result: ${JSON.stringify(result)}`);
|
||||
// return result;
|
||||
// } catch (error) {
|
||||
// logError(LogModule.APP, `Error opening file dialog: ${error.message}`);
|
||||
// return null;
|
||||
// }
|
||||
// });
|
||||
// }
|
@ -1,722 +0,0 @@
|
||||
// import { app, ipcMain, Notification } from "electron";
|
||||
// import { getConfig } from "../storage/config";
|
||||
// import { listProxy } from "../storage/proxy";
|
||||
// import { getVersionById } from "../storage/version";
|
||||
// import treeKill from "tree-kill";
|
||||
// import { logInfo, logError, LogModule, logDebug, logWarn } from "../utils/log";
|
||||
//
|
||||
// const fs = require("fs");
|
||||
// const path = require("path");
|
||||
// const { exec, spawn } = require("child_process");
|
||||
//
|
||||
// export let frpcProcess = null;
|
||||
// const runningCmd = {
|
||||
// commandPath: null,
|
||||
// configPath: null
|
||||
// };
|
||||
// let frpcStatusListener = null;
|
||||
//
|
||||
// const getFrpcVersionWorkerPath = (
|
||||
// versionId: number,
|
||||
// callback: (workerPath: string) => void
|
||||
// ) => {
|
||||
// getVersionById(versionId, (err2, version) => {
|
||||
// if (!err2) {
|
||||
// if (version) {
|
||||
// callback(version["frpcVersionPath"]);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
//
|
||||
// const isRangePort = (m: Proxy) => {
|
||||
// return (
|
||||
// (m.type === "tcp" || m.type === "udp") &&
|
||||
// (String(m.localPort).indexOf("-") !== -1 ||
|
||||
// String(m.localPort).indexOf(",") !== -1)
|
||||
// );
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 生成toml配置文件
|
||||
// * @param config
|
||||
// * @param proxys
|
||||
// */
|
||||
// export const genTomlConfig = (config: FrpConfig, proxys: Proxy[]) => {
|
||||
// const proxyToml = proxys.map(m => {
|
||||
// const rangePort = isRangePort(m);
|
||||
// config.tlsConfigKeyFile = config.tlsConfigKeyFile.replace(/\\/g, "\\\\");
|
||||
// config.tlsConfigCertFile = config.tlsConfigCertFile.replace(/\\/g, "\\\\");
|
||||
// config.tlsConfigTrustedCaFile = config.tlsConfigTrustedCaFile.replace(
|
||||
// /\\/g,
|
||||
// "\\\\"
|
||||
// );
|
||||
// let toml = `${
|
||||
// rangePort
|
||||
// ? `{{- range $_, $v := parseNumberRangePair "${m.localPort}" "${m.remotePort}" }}`
|
||||
// : ""
|
||||
// }
|
||||
// [[${
|
||||
// (m.type === "stcp" || m.type === "xtcp" || m.type === "sudp") &&
|
||||
// m.visitorsModel === "visitors"
|
||||
// ? "visitors"
|
||||
// : "proxies"
|
||||
// }]]
|
||||
// ${rangePort ? "" : `name = "${m.name}"`}
|
||||
// type = "${m.type}"\n`;
|
||||
//
|
||||
// switch (m.type) {
|
||||
// case "tcp":
|
||||
// case "udp":
|
||||
// if (rangePort) {
|
||||
// toml += `name = "${m.name}-{{ $v.First }}"
|
||||
// localPort = {{ $v.First }}
|
||||
// remotePort = {{ $v.Second }}\n`;
|
||||
// } else {
|
||||
// toml += `localIP = "${m.localIp}"
|
||||
// localPort = ${m.localPort}
|
||||
// remotePort = ${m.remotePort}\n`;
|
||||
// }
|
||||
// break;
|
||||
// case "http":
|
||||
// case "https":
|
||||
// const customDomains = m.customDomains.filter(f1 => f1 !== "");
|
||||
// if (customDomains && customDomains.length > 0) {
|
||||
// toml += `customDomains=[${m.customDomains.map(m => `"${m}"`)}]\n`;
|
||||
// }
|
||||
// if (m.subdomain) {
|
||||
// toml += `subdomain="${m.subdomain}"\n`;
|
||||
// }
|
||||
// if (m.basicAuth) {
|
||||
// toml += `httpUser = "${m.httpUser}"
|
||||
// httpPassword = "${m.httpPassword}"\n`;
|
||||
// }
|
||||
// if (m.https2http) {
|
||||
// toml += `[proxies.plugin]
|
||||
// type = "https2http"
|
||||
// localAddr = "${m.localIp}:${m.localPort}"
|
||||
//
|
||||
// crtPath = "${m.https2httpCaFile}"
|
||||
// keyPath = "${m.https2httpKeyFile}"\n`;
|
||||
// } else {
|
||||
// toml += `localIP = "${m.localIp}"
|
||||
// localPort = ${m.localPort}\n`;
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
// case "xtcp":
|
||||
// if (m.visitorsModel === "visitors") {
|
||||
// toml += `keepTunnelOpen = ${m.keepTunnelOpen}\n`;
|
||||
// }
|
||||
// case "stcp":
|
||||
// case "sudp":
|
||||
// if (m.visitorsModel === "visitors") {
|
||||
// // 访问者
|
||||
// toml += `serverName = "${m.serverName}"
|
||||
// bindAddr = "${m.bindAddr}"
|
||||
// bindPort = ${m.bindPort}\n`;
|
||||
// if (m.fallbackTo) {
|
||||
// toml += `fallbackTo = "${m.fallbackTo}"
|
||||
// fallbackTimeoutMs = ${m.fallbackTimeoutMs || 500}\n`;
|
||||
// }
|
||||
// } else if (m.visitorsModel === "visitorsProvider") {
|
||||
// // 被访问者
|
||||
// toml += `localIP = "${m.localIp}"
|
||||
// localPort = ${m.localPort}\n`;
|
||||
// }
|
||||
//
|
||||
// toml += `secretKey="${m.secretKey}"\n`;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// if (rangePort) {
|
||||
// toml += `{{- end }}\n`;
|
||||
// }
|
||||
// return toml;
|
||||
// });
|
||||
// const toml = `serverAddr = "${config.serverAddr}"
|
||||
// serverPort = ${config.serverPort}
|
||||
// ${
|
||||
// config.authMethod === "token"
|
||||
// ? `auth.method = "token"
|
||||
// auth.token = "${config.authToken}"`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.authMethod === "multiuser"
|
||||
// ? `user = "${config.user}"
|
||||
// metadatas.token = "${config.metaToken}"`
|
||||
// : ""
|
||||
// }
|
||||
// log.to = "frpc.log"
|
||||
// log.level = "${config.logLevel}"
|
||||
// log.maxDays = ${config.logMaxDays}
|
||||
// webServer.addr = "127.0.0.1"
|
||||
// webServer.port = ${config.webPort}
|
||||
// ${
|
||||
// config.transportProtocol
|
||||
// ? `transport.protocol = "${config.transportProtocol}"`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.transportPoolCount
|
||||
// ? `transport.poolCount = ${config.transportPoolCount}`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.transportDialServerTimeout
|
||||
// ? `transport.dialServerTimeout = ${config.transportDialServerTimeout}`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.transportDialServerKeepalive
|
||||
// ? `transport.dialServerKeepalive = ${config.transportDialServerKeepalive}`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.transportHeartbeatInterval
|
||||
// ? `transport.heartbeatInterval = ${config.transportHeartbeatInterval}`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.transportHeartbeatTimeout
|
||||
// ? `transport.heartbeatTimeout = ${config.transportHeartbeatTimeout}`
|
||||
// : ""
|
||||
// }
|
||||
// ${config.transportTcpMux ? `transport.tcpMux = ${config.transportTcpMux}` : ""}
|
||||
// ${
|
||||
// config.transportTcpMux && config.transportTcpMuxKeepaliveInterval
|
||||
// ? `transport.tcpMuxKeepaliveInterval = ${config.transportTcpMuxKeepaliveInterval}`
|
||||
// : ""
|
||||
// }
|
||||
// transport.tls.enable = ${config.tlsConfigEnable}
|
||||
// ${
|
||||
// config.tlsConfigEnable && config.tlsConfigCertFile
|
||||
// ? `transport.tls.certFile = "${config.tlsConfigCertFile}"`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.tlsConfigEnable && config.tlsConfigKeyFile
|
||||
// ? `transport.tls.keyFile = "${config.tlsConfigKeyFile}"`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.tlsConfigEnable && config.tlsConfigTrustedCaFile
|
||||
// ? `transport.tls.trustedCaFile = "${config.tlsConfigTrustedCaFile}"`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.tlsConfigEnable && config.tlsConfigServerName
|
||||
// ? `transport.tls.serverName = "${config.tlsConfigServerName}"`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.proxyConfigEnable
|
||||
// ? `transport.proxyURL = "${config.proxyConfigProxyUrl}"`
|
||||
// : ""
|
||||
// }
|
||||
// ${proxyToml.join("")}`;
|
||||
// return toml;
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 生成ini配置
|
||||
// * @param config
|
||||
// * @param proxys
|
||||
// */
|
||||
// export const genIniConfig = (config: FrpConfig, proxys: Proxy[]) => {
|
||||
// const proxyIni = proxys.map(m => {
|
||||
// const rangePort = isRangePort(m);
|
||||
// let ini = `[${rangePort ? "range:" : ""}${m.name}]
|
||||
// type = "${m.type}"
|
||||
// `;
|
||||
// switch (m.type) {
|
||||
// case "tcp":
|
||||
// case "udp":
|
||||
// ini += `
|
||||
// local_ip = "${m.localIp}"
|
||||
// local_port = ${m.localPort}
|
||||
// remote_port = ${m.remotePort}\n`;
|
||||
// break;
|
||||
// case "http":
|
||||
// ini += `
|
||||
// local_ip = "${m.localIp}"
|
||||
// local_port = ${m.localPort}
|
||||
// custom_domains=[${m.customDomains.map(m => `${m}`)}]
|
||||
// subdomain="${m.subdomain}"\n`;
|
||||
// if (m.basicAuth) {
|
||||
// ini += `
|
||||
// httpUser = "${m.httpUser}"
|
||||
// httpPassword = "${m.httpPassword}"\n`;
|
||||
// }
|
||||
// break;
|
||||
// case "https":
|
||||
// ini += `
|
||||
// custom_domains=[${m.customDomains.map(m => `${m}`)}]
|
||||
// subdomain="${m.subdomain}"\n`;
|
||||
// if (m.basicAuth) {
|
||||
// ini += `
|
||||
// httpUser = "${m.httpUser}"
|
||||
// httpPassword = "${m.httpPassword}"\n`;
|
||||
// }
|
||||
// if (m.https2http) {
|
||||
// ini += `
|
||||
// plugin = https2http
|
||||
// plugin_local_addr = ${m.localIp}:${m.localPort}
|
||||
// plugin_crt_path = ${m.https2httpCaFile}
|
||||
// plugin_key_path = ${m.https2httpKeyFile}\n`;
|
||||
// } else {
|
||||
// ini += `
|
||||
// local_ip = "${m.localIp}"
|
||||
// local_port = ${m.localPort}\n`;
|
||||
// }
|
||||
// break;
|
||||
// case "xtcp":
|
||||
// if (m.visitorsModel === "visitors") {
|
||||
// ini += `keep_tunnel_open = ${m.keepTunnelOpen}\n`;
|
||||
// }
|
||||
// case "stcp":
|
||||
// case "sudp":
|
||||
// if (m.visitorsModel === "visitors") {
|
||||
// // 访问者
|
||||
// ini += `
|
||||
// role = visitor
|
||||
// server_name = "${m.serverName}"
|
||||
// bind_addr = "${m.bindAddr}"
|
||||
// bind_port = ${m.bindPort}\n`;
|
||||
// if (m.fallbackTo) {
|
||||
// ini += `
|
||||
// fallback_to = ${m.fallbackTo}
|
||||
// fallback_timeout_ms = ${m.fallbackTimeoutMs || 500}\n`;
|
||||
// }
|
||||
// } else if (m.visitorsModel === "visitorsProvider") {
|
||||
// // 被访问者
|
||||
// ini += `
|
||||
// local_ip = "${m.localIp}"
|
||||
// local_port = ${m.localPort}\n`;
|
||||
// }
|
||||
// ini += `
|
||||
// sk="${m.secretKey}"\n`;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// return ini;
|
||||
// });
|
||||
// const ini = `
|
||||
// [common]
|
||||
// server_addr = ${config.serverAddr}
|
||||
// server_port = ${config.serverPort}
|
||||
// ${
|
||||
// config.authMethod === "token"
|
||||
// ? `
|
||||
// authentication_method = ${config.authMethod}
|
||||
// token = ${config.authToken}\n`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.authMethod === "multiuser"
|
||||
// ? `
|
||||
// user = ${config.user}
|
||||
// meta_token = ${config.metaToken}\n`
|
||||
// : ""
|
||||
// }
|
||||
//
|
||||
// ${config.transportProtocol ? `protocol = ${config.transportProtocol}` : ""}
|
||||
// ${config.transportPoolCount ? `pool_count = ${config.transportPoolCount}` : ""}
|
||||
// ${
|
||||
// config.transportDialServerTimeout
|
||||
// ? `dial_server_timeout = ${config.transportDialServerTimeout}`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.transportDialServerKeepalive
|
||||
// ? `dial_server_keepalive = ${config.transportDialServerKeepalive}`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.transportHeartbeatInterval
|
||||
// ? `
|
||||
// heartbeat_interval = ${config.transportHeartbeatInterval}
|
||||
// `
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.transportHeartbeatTimeout
|
||||
// ? `
|
||||
// heartbeat_timeout = ${config.transportHeartbeatTimeout}
|
||||
// `
|
||||
// : ""
|
||||
// }
|
||||
// ${config.transportTcpMux ? `transport.tcp_mux = ${config.transportTcpMux}` : ""}
|
||||
// ${
|
||||
// config.transportTcpMux && config.transportTcpMuxKeepaliveInterval
|
||||
// ? `tcp_mux_keepalive_interval = ${config.transportTcpMuxKeepaliveInterval}`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.tlsConfigEnable && config.tlsConfigCertFile
|
||||
// ? `
|
||||
// tls_cert_file = ${config.tlsConfigCertFile}\n`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.tlsConfigEnable && config.tlsConfigKeyFile
|
||||
// ? `
|
||||
// tls_key_file = ${config.tlsConfigKeyFile}\n`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.tlsConfigEnable && config.tlsConfigTrustedCaFile
|
||||
// ? `
|
||||
// tls_trusted_ca_file = ${config.tlsConfigTrustedCaFile}\n`
|
||||
// : ""
|
||||
// }
|
||||
// ${
|
||||
// config.tlsConfigEnable && config.tlsConfigServerName
|
||||
// ? `
|
||||
// tls_server_name = ${config.tlsConfigServerName}\n`
|
||||
// : ""
|
||||
// }
|
||||
//
|
||||
// ${
|
||||
// config.proxyConfigEnable
|
||||
// ? `
|
||||
// http_proxy = "${config.proxyConfigProxyUrl}"\n`
|
||||
// : ""
|
||||
// }
|
||||
//
|
||||
// log_file = "frpc.log"
|
||||
// log_level = ${config.logLevel}
|
||||
// log_max_days = ${config.logMaxDays}
|
||||
// admin_addr = 127.0.0.1
|
||||
// admin_port = ${config.webPort}
|
||||
// tls_enable = ${config.tlsConfigEnable}
|
||||
//
|
||||
//
|
||||
// ${proxyIni.join("")}
|
||||
// `;
|
||||
// return ini;
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 生成配置文件
|
||||
// */
|
||||
// export const generateConfig = (
|
||||
// config: FrpConfig,
|
||||
// callback: (configPath: string) => void
|
||||
// ) => {
|
||||
// listProxy((err3, proxys) => {
|
||||
// if (err3) {
|
||||
// logError(LogModule.FRP_CLIENT, `Failed to list proxies: ${err3.message}`);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// const { currentVersion } = config;
|
||||
// let filename = null;
|
||||
// let configContent = "";
|
||||
// const filtered = proxys
|
||||
// .map(m => {
|
||||
// if (m.status == null || m.status == undefined) {
|
||||
// m.status = true;
|
||||
// }
|
||||
// return m;
|
||||
// })
|
||||
// .filter(f => f.status);
|
||||
//
|
||||
// if (currentVersion < 124395282) {
|
||||
// // 版本小于v0.52.0
|
||||
// filename = "frp.ini";
|
||||
// configContent = genIniConfig(config, filtered);
|
||||
// logInfo(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Using INI format for configuration: ${filename}`
|
||||
// );
|
||||
// } else {
|
||||
// filename = "frp.toml";
|
||||
// configContent = genTomlConfig(config, filtered);
|
||||
// logInfo(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Using TOML format for configuration: ${filename}`
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// const configPath = path.join(app.getPath("userData"), filename);
|
||||
// logInfo(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Writing configuration to file: ${configPath}`
|
||||
// );
|
||||
//
|
||||
// fs.writeFile(
|
||||
// configPath, // 配置文件目录
|
||||
// configContent, // 配置文件内容
|
||||
// { flag: "w" },
|
||||
// err => {
|
||||
// if (err) {
|
||||
// logError(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Failed to write configuration file: ${err.message}`
|
||||
// );
|
||||
// } else {
|
||||
// logInfo(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Configuration file written successfully: ${filename}`
|
||||
// );
|
||||
// callback(filename);
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 启动frpc子进程
|
||||
// * @param cwd
|
||||
// * @param commandPath
|
||||
// * @param configPath
|
||||
// */
|
||||
// const startFrpcProcess = (commandPath: string, configPath: string) => {
|
||||
// logInfo(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Starting frpc process. Directory: ${app.getPath(
|
||||
// "userData"
|
||||
// )}, Command: ${commandPath}`
|
||||
// );
|
||||
//
|
||||
// const command = `${commandPath} -c ${configPath}`;
|
||||
// frpcProcess = spawn(command, {
|
||||
// cwd: app.getPath("userData"),
|
||||
// shell: true
|
||||
// });
|
||||
// runningCmd.commandPath = commandPath;
|
||||
// runningCmd.configPath = configPath;
|
||||
//
|
||||
// frpcProcess.stdout.on("data", data => {
|
||||
// logDebug(LogModule.FRP_CLIENT, `Frpc process output: ${data}`);
|
||||
// });
|
||||
//
|
||||
// frpcProcess.stdout.on("error", data => {
|
||||
// logError(LogModule.FRP_CLIENT, `Frpc process error: ${data}`);
|
||||
// stopFrpcProcess(() => {});
|
||||
// });
|
||||
//
|
||||
// frpcStatusListener = setInterval(() => {
|
||||
// const status = frpcProcessStatus();
|
||||
// logDebug(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Monitoring frpc process status: ${status}, Listener ID: ${frpcStatusListener}`
|
||||
// );
|
||||
// if (!status) {
|
||||
// new Notification({
|
||||
// title: "Frpc Desktop",
|
||||
// body: "Connection lost, please check the logs for details."
|
||||
// }).show();
|
||||
// logError(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// "Frpc process status check failed. Connection lost."
|
||||
// );
|
||||
// clearInterval(frpcStatusListener);
|
||||
// }
|
||||
// }, 3000);
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 重载frpc配置
|
||||
// */
|
||||
// export const reloadFrpcProcess = () => {
|
||||
// if (frpcProcess && !frpcProcess.killed) {
|
||||
// logDebug(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// "Attempting to reload frpc process configuration."
|
||||
// );
|
||||
// getConfig((err1, config) => {
|
||||
// if (!err1) {
|
||||
// if (config) {
|
||||
// generateConfig(config, configPath => {
|
||||
// const command = `${runningCmd.commandPath} reload -c ${configPath}`;
|
||||
// logInfo(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Reloading configuration: ${command}`
|
||||
// );
|
||||
// exec(
|
||||
// command,
|
||||
// {
|
||||
// cwd: app.getPath("userData"),
|
||||
// shell: true
|
||||
// },
|
||||
// (error, stdout, stderr) => {
|
||||
// if (error) {
|
||||
// logError(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Error reloading configuration: ${error.message}`
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
// logDebug(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Configuration reload output: ${stdout}`
|
||||
// );
|
||||
// if (stderr) {
|
||||
// logWarn(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Configuration reload warnings: ${stderr}`
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
// } else {
|
||||
// logWarn(LogModule.FRP_CLIENT, "No configuration found to reload.");
|
||||
// }
|
||||
// } else {
|
||||
// logError(LogModule.FRP_CLIENT, `Error getting configuration: ${err1}`);
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// logDebug(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// "frpc process is not running or has been killed."
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 停止frpc子进程
|
||||
// */
|
||||
// export const stopFrpcProcess = (callback?: () => void) => {
|
||||
// if (frpcProcess) {
|
||||
// treeKill(frpcProcess.pid, (error: Error) => {
|
||||
// if (error) {
|
||||
// logError(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Failed to stop frpc process with pid: ${frpcProcess.pid}. Error: ${error.message}`
|
||||
// );
|
||||
// callback();
|
||||
// } else {
|
||||
// logInfo(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Successfully stopped frpc process with pid: ${frpcProcess.pid}.`
|
||||
// );
|
||||
// frpcProcess = null;
|
||||
// clearInterval(frpcStatusListener);
|
||||
// callback();
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// logWarn(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// "Attempted to stop frpc process, but no process is running."
|
||||
// );
|
||||
// logWarn(LogModule.FRP_CLIENT, "No frpc process to stop.");
|
||||
// callback();
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 获取frpc子进程状态
|
||||
// */
|
||||
// export const frpcProcessStatus = () => {
|
||||
// if (!frpcProcess) {
|
||||
// logDebug(LogModule.FRP_CLIENT, "frpc process is not running.");
|
||||
// return false;
|
||||
// }
|
||||
// try {
|
||||
// // 发送信号给进程,如果进程存在,会正常返回
|
||||
// process.kill(frpcProcess.pid, 0);
|
||||
// logDebug(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `frpc process is running with pid: ${frpcProcess.pid}`
|
||||
// );
|
||||
// return true;
|
||||
// } catch (error) {
|
||||
// // 进程不存在,抛出异常
|
||||
// logError(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `frpc process not found. Error: ${error.message}`
|
||||
// );
|
||||
// return false;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 启动frpc流程
|
||||
// * @param config
|
||||
// */
|
||||
// export const startFrpWorkerProcess = async (config: FrpConfig) => {
|
||||
// logInfo(LogModule.FRP_CLIENT, "Starting frpc worker process...");
|
||||
// getFrpcVersionWorkerPath(config.currentVersion, (frpcVersionPath: string) => {
|
||||
// if (frpcVersionPath) {
|
||||
// logInfo(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// `Found frpc version path: ${frpcVersionPath}`
|
||||
// );
|
||||
// generateConfig(config, configPath => {
|
||||
// const platform = process.platform;
|
||||
// if (platform === "win32") {
|
||||
// logInfo(LogModule.FRP_CLIENT, "Starting frpc on Windows.");
|
||||
// startFrpcProcess(path.join(frpcVersionPath, "frpc.exe"), configPath);
|
||||
// } else {
|
||||
// logInfo(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// "Starting frpc on non-Windows platform."
|
||||
// );
|
||||
// startFrpcProcess(path.join(frpcVersionPath, "frpc"), configPath);
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// logError(LogModule.FRP_CLIENT, "frpc version path not found.");
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
//
|
||||
// export const initFrpcApi = () => {
|
||||
// ipcMain.handle("frpc.running", async (event, args) => {
|
||||
// logDebug(LogModule.FRP_CLIENT, "Checking if frpc process is running...");
|
||||
// return frpcProcessStatus();
|
||||
// });
|
||||
//
|
||||
// ipcMain.on("frpc.start", async (event, args) => {
|
||||
// logInfo(LogModule.FRP_CLIENT, "Received request to start frpc process.");
|
||||
// getConfig((err1, config) => {
|
||||
// if (!err1) {
|
||||
// if (!config) {
|
||||
// logWarn(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// "Configuration not found. Prompting user to set configuration."
|
||||
// );
|
||||
// event.reply(
|
||||
// "Home.frpc.start.error.hook",
|
||||
// "请先前往设置页面,修改配置后再启动"
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
// if (!config.currentVersion) {
|
||||
// logWarn(
|
||||
// LogModule.FRP_CLIENT,
|
||||
// "Current version not set in configuration. Prompting user."
|
||||
// );
|
||||
// event.reply(
|
||||
// "Home.frpc.start.error.hook",
|
||||
// "请先前往设置页面,修改配置后再启动"
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
// startFrpWorkerProcess(config);
|
||||
// } else {
|
||||
// logError(LogModule.FRP_CLIENT, `Error getting configuration: ${err1}`);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// ipcMain.on("frpc.stop", () => {
|
||||
// logInfo(LogModule.FRP_CLIENT, "Received request to stop frpc process.");
|
||||
// if (frpcProcess && !frpcProcess.killed) {
|
||||
// stopFrpcProcess(() => {});
|
||||
// } else {
|
||||
// logWarn(LogModule.FRP_CLIENT, "No frpc process to stop.");
|
||||
// }
|
||||
// });
|
||||
// };
|
@ -1,590 +0,0 @@
|
||||
// import { app, BrowserWindow, dialog, ipcMain, net } from "electron";
|
||||
// import {
|
||||
// deleteVersionById,
|
||||
// getVersionById,
|
||||
// insertVersion,
|
||||
// listVersion
|
||||
// } from "../storage/version";
|
||||
// import frpReleasesJson from "../json/frp-releases.json";
|
||||
// import frpChecksums from "../json/frp_all_sha256_checksums.json";
|
||||
// import { logDebug, logError, logInfo, LogModule, logWarn } from "../utils/log";
|
||||
// // import { calculateFileChecksum, formatBytes } from "../utils/FileUtils";
|
||||
//
|
||||
// const fs = require("fs");
|
||||
// const path = require("path");
|
||||
// const zlib = require("zlib");
|
||||
// const { download } = require("electron-dl");
|
||||
// const AdmZip = require("adm-zip");
|
||||
//
|
||||
// const versionRelation = {
|
||||
// win32_x64: ["window", "amd64"],
|
||||
// win32_arm64: ["window", "arm64"],
|
||||
// win32_ia32: ["window", "386"],
|
||||
// darwin_arm64: ["darwin", "arm64"],
|
||||
// darwin_x64: ["darwin", "amd64"],
|
||||
// darwin_amd64: ["darwin", "amd64"],
|
||||
// linux_x64: ["linux", "amd64"],
|
||||
// linux_arm64: ["linux", "arm64"]
|
||||
// };
|
||||
// const platform = process.platform;
|
||||
// const arch = process.arch;
|
||||
// let currArch = `${platform}_${arch}`;
|
||||
// const frpArch = versionRelation[currArch];
|
||||
//
|
||||
// const unTarGZ = (tarGzPath: string, targetPath: string) => {
|
||||
// const tar = require("tar");
|
||||
// const unzip = zlib.createGunzip();
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// `Starting to extract tar.gz: ${tarGzPath} to ${targetPath}`
|
||||
// );
|
||||
//
|
||||
// const readStream = fs.createReadStream(tarGzPath);
|
||||
// if (!fs.existsSync(unzip)) {
|
||||
// fs.mkdirSync(targetPath, { recursive: true, mode: 0o777 });
|
||||
// logInfo(LogModule.APP, `Created target directory: ${targetPath}`);
|
||||
// }
|
||||
//
|
||||
// readStream.on("error", err => {
|
||||
// logError(LogModule.APP, `Error reading tar.gz file: ${err.message}`);
|
||||
// });
|
||||
//
|
||||
// readStream
|
||||
// .pipe(unzip)
|
||||
// .on("error", err => {
|
||||
// logError(LogModule.APP, `Error during gunzip: ${err.message}`);
|
||||
// })
|
||||
// .pipe(
|
||||
// tar
|
||||
// .extract({
|
||||
// cwd: targetPath,
|
||||
// filter: filePath => path.basename(filePath) === "frpc"
|
||||
// })
|
||||
// .on("error", err => {
|
||||
// logError(LogModule.APP, `Error extracting tar file: ${err.message}`);
|
||||
// })
|
||||
// )
|
||||
// .on("finish", () => {
|
||||
// const frpcPath = path.join("frp", path.basename(tarGzPath, ".tar.gz"));
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// `Extraction completed. Extracted directory: ${frpcPath}`
|
||||
// );
|
||||
// });
|
||||
// return path.join("frp", path.basename(tarGzPath, ".tar.gz"));
|
||||
// };
|
||||
//
|
||||
// const unZip = (zipPath: string, targetPath: string) => {
|
||||
// if (!fs.existsSync(path.join(targetPath, path.basename(zipPath, ".zip")))) {
|
||||
// fs.mkdirSync(path.join(targetPath, path.basename(zipPath, ".zip")), {
|
||||
// recursive: true
|
||||
// });
|
||||
// logInfo(LogModule.APP, `Created target directory: ${targetPath}`);
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// `Created directory for zip extraction: ${path.basename(zipPath, ".zip")}`
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// logDebug(
|
||||
// LogModule.APP,
|
||||
// `Starting to unzip: ${zipPath} to target directory: ${targetPath}`
|
||||
// );
|
||||
// logInfo(LogModule.APP, `Starting to extract zip file: ${zipPath}`);
|
||||
//
|
||||
// const zip = new AdmZip(zipPath);
|
||||
// try {
|
||||
// zip.extractAllTo(targetPath, true); // 第二个参数为 true,表示覆盖已存在的文件
|
||||
// const frpcPath = path.join("frp", path.basename(zipPath, ".zip"));
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// `Extraction completed. Extracted directory: ${frpcPath}`
|
||||
// );
|
||||
// logDebug(
|
||||
// LogModule.APP,
|
||||
// `Unzip completed. Extracted directory: ${frpcPath}`
|
||||
// );
|
||||
// return frpcPath;
|
||||
// } catch (error) {
|
||||
// logError(LogModule.APP, `Error extracting zip file: ${error.message}`);
|
||||
// }
|
||||
//
|
||||
// return null;
|
||||
// };
|
||||
//
|
||||
// export const initGitHubApi = win => {
|
||||
// // 版本
|
||||
// let versions: FrpVersion[] = [];
|
||||
//
|
||||
// const getVersionByGithubVersionId = versionId => {
|
||||
// logDebug(LogModule.APP, `Attempting to get version with ID: ${versionId}`);
|
||||
// const version = versions.find(f => f.id === versionId);
|
||||
// if (version) {
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// `Version details ID:${version.id}, Name:${version.name}, Published At:${version.published_at}`
|
||||
// );
|
||||
// } else {
|
||||
// logWarn(LogModule.APP, `No version found for ID: ${versionId}`);
|
||||
// }
|
||||
// return version;
|
||||
// };
|
||||
//
|
||||
// const getVersionByAssetName = (assetName: string) => {
|
||||
// logDebug(
|
||||
// LogModule.APP,
|
||||
// `Attempting to get version with asset name: ${assetName}`
|
||||
// );
|
||||
// const version = versions.find(f =>
|
||||
// f.assets.some(asset => asset.name === assetName)
|
||||
// );
|
||||
// if (version) {
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// `Version details ID:${version.id}, Name:${version.name}, Published At:${version.published_at}`
|
||||
// );
|
||||
// } else {
|
||||
// logWarn(LogModule.APP, `No version found for asset name: ${assetName}`);
|
||||
// }
|
||||
// return version;
|
||||
// };
|
||||
//
|
||||
// const getAdaptiveAsset = versionId => {
|
||||
// const { assets } = getVersionByGithubVersionId(versionId);
|
||||
// if (!assets || assets.length === 0) {
|
||||
// logWarn(LogModule.GITHUB, `No assets found for version ID: ${versionId}`);
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// const asset = assets.find(f => {
|
||||
// const a = frpArch;
|
||||
// if (a) {
|
||||
// const flag = a.every(item => f.name.includes(item));
|
||||
// if (flag) {
|
||||
// logInfo(
|
||||
// LogModule.GITHUB,
|
||||
// `Found matching asset: ${f.name} for version ID: ${versionId}`
|
||||
// );
|
||||
// }
|
||||
// return flag;
|
||||
// }
|
||||
// logWarn(
|
||||
// LogModule.GITHUB,
|
||||
// `No architecture match found for asset: ${f.name}`
|
||||
// );
|
||||
// return false;
|
||||
// });
|
||||
//
|
||||
// if (!asset) {
|
||||
// logError(
|
||||
// LogModule.GITHUB,
|
||||
// `No adaptive asset found for version ID: ${versionId}`
|
||||
// );
|
||||
// }
|
||||
// return asset;
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * handle github api release json
|
||||
// * @param githubReleaseJsonStr jsonStr
|
||||
// * @returns versions
|
||||
// */
|
||||
// const handleApiResponse = (githubReleaseJsonStr: string) => {
|
||||
// const downloadPath = path.join(app.getPath("userData"), "download");
|
||||
// const frpPath = path.join(app.getPath("userData"), "frp");
|
||||
// logInfo(LogModule.GITHUB, "Parsing GitHub release JSON response.");
|
||||
//
|
||||
// versions = JSON.parse(githubReleaseJsonStr);
|
||||
// if (versions) {
|
||||
// logInfo(
|
||||
// LogModule.GITHUB,
|
||||
// "Successfully parsed versions from GitHub response."
|
||||
// );
|
||||
//
|
||||
// const returnVersionsData = versions
|
||||
// .filter(f => getAdaptiveAsset(f.id))
|
||||
// .map(m => {
|
||||
// const asset = getAdaptiveAsset(m.id);
|
||||
// const download_count = m.assets.reduce(
|
||||
// (sum, item) => sum + item.download_count,
|
||||
// 0
|
||||
// );
|
||||
// if (asset) {
|
||||
// const absPath = path.join(
|
||||
// frpPath,
|
||||
// asset.name.replace(/(\.tar\.gz|\.zip)$/, "")
|
||||
// );
|
||||
// m.absPath = absPath;
|
||||
// m.download_completed = fs.existsSync(absPath);
|
||||
// m.download_count = download_count;
|
||||
// m.size = formatBytes(asset.size);
|
||||
// logInfo(
|
||||
// LogModule.GITHUB,
|
||||
// `Asset found: ${asset.name}, download count: ${download_count}`
|
||||
// );
|
||||
// } else {
|
||||
// logWarn(LogModule.GITHUB, `No asset found for version ID: ${m.id}`);
|
||||
// }
|
||||
// return m;
|
||||
// });
|
||||
// logDebug(
|
||||
// LogModule.GITHUB,
|
||||
// `Retrieved FRP versions: ${JSON.stringify(returnVersionsData)}`
|
||||
// );
|
||||
// return returnVersionsData;
|
||||
// } else {
|
||||
// logError(
|
||||
// LogModule.GITHUB,
|
||||
// "Failed to parse versions: No versions found in response."
|
||||
// );
|
||||
// return [];
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * conventMirrorUrl
|
||||
// * @param mirror mirror
|
||||
// * @returns mirrorUrl
|
||||
// */
|
||||
// const conventMirrorUrl = (mirror: string) => {
|
||||
// switch (mirror) {
|
||||
// case "github":
|
||||
// return {
|
||||
// api: "https://api.github.com",
|
||||
// asset: "https://github.com"
|
||||
// };
|
||||
// default:
|
||||
// return {
|
||||
// api: "https://api.github.com",
|
||||
// asset: "https://github.com"
|
||||
// };
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 获取github上的frp所有版本
|
||||
// */
|
||||
// ipcMain.on("github.getFrpVersions", async (event, mirror: string) => {
|
||||
// const { api } = conventMirrorUrl(mirror);
|
||||
// const mirrorUrl = api;
|
||||
// logInfo(LogModule.GITHUB, `Requesting mirror URL: ${mirrorUrl}`);
|
||||
// const request = net.request({
|
||||
// method: "get",
|
||||
// url: `${mirrorUrl}/repos/fatedier/frp/releases?page=1&per_page=1000`
|
||||
// });
|
||||
//
|
||||
// let githubReleaseJsonStr = null;
|
||||
// request.on("response", response => {
|
||||
// logInfo(
|
||||
// LogModule.GITHUB,
|
||||
// `Received response with status code: ${response.statusCode}`
|
||||
// );
|
||||
// let responseData: Buffer = Buffer.alloc(0);
|
||||
// response.on("data", (data: Buffer) => {
|
||||
// responseData = Buffer.concat([responseData, data]);
|
||||
// });
|
||||
// response.on("end", () => {
|
||||
// if (response.statusCode === 200) {
|
||||
// githubReleaseJsonStr = responseData.toString();
|
||||
// logInfo(
|
||||
// LogModule.GITHUB,
|
||||
// "Successfully retrieved GitHub release data."
|
||||
// );
|
||||
// } else {
|
||||
// logWarn(
|
||||
// LogModule.GITHUB,
|
||||
// "Failed to retrieve data, using local JSON instead. Status code: " +
|
||||
// response.statusCode
|
||||
// );
|
||||
// githubReleaseJsonStr = JSON.stringify(frpReleasesJson);
|
||||
// }
|
||||
// const versions = handleApiResponse(githubReleaseJsonStr);
|
||||
// event.reply("Download.frpVersionHook", versions);
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// request.on("error", jerror => {
|
||||
// logError(
|
||||
// LogModule.GITHUB,
|
||||
// "Error occurred while requesting GitHub releases: " + error
|
||||
// );
|
||||
// githubReleaseJsonStr = JSON.stringify(frpReleasesJson);
|
||||
// const versions = handleApiResponse(githubReleaseJsonStr);
|
||||
// event.reply("Download.frpVersionHook", versions);
|
||||
// });
|
||||
//
|
||||
// request.end();
|
||||
// });
|
||||
//
|
||||
// const decompressFrp = (frpFilename: string, compressedFilePath: string) => {
|
||||
// const targetPath = path.resolve(path.join(app.getPath("userData"), "frp"));
|
||||
// const ext = path.extname(frpFilename);
|
||||
// let frpcVersionPath = "";
|
||||
// try {
|
||||
// if (ext === ".zip") {
|
||||
// unZip(
|
||||
// // path.join(
|
||||
// // path.join(app.getPath("userData"), "download"),
|
||||
// // `${frpFilename}`
|
||||
// // ),
|
||||
// compressedFilePath,
|
||||
// targetPath
|
||||
// );
|
||||
// logInfo(LogModule.APP, `Unzipped file to path: ${frpcVersionPath}`);
|
||||
// frpcVersionPath = path.join("frp", path.basename(frpFilename, ".zip"));
|
||||
// } else if (ext === ".gz" && frpFilename.includes(".tar.gz")) {
|
||||
// unTarGZ(
|
||||
// // path.join(
|
||||
// // path.join(app.getPath("userData"), "download"),
|
||||
// // `${frpFilename}`
|
||||
// // ),
|
||||
// compressedFilePath,
|
||||
// targetPath
|
||||
// );
|
||||
// frpcVersionPath = path.join(
|
||||
// "frp",
|
||||
// path.basename(frpFilename, ".tar.gz")
|
||||
// );
|
||||
// logInfo(LogModule.APP, `Untarred file to path: ${frpcVersionPath}`);
|
||||
// }
|
||||
// } catch (error) {
|
||||
// logError(LogModule.APP, `Error during extraction: ${error.message}`);
|
||||
// }
|
||||
//
|
||||
// return frpcVersionPath;
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 下载请求
|
||||
// */
|
||||
// ipcMain.on("github.download", async (event, args) => {
|
||||
// const { versionId, mirror } = args;
|
||||
// const version = getVersionByGithubVersionId(versionId);
|
||||
// const asset = getAdaptiveAsset(versionId);
|
||||
// const { browser_download_url } = asset;
|
||||
//
|
||||
// let url = browser_download_url.replace(
|
||||
// "https://github.com",
|
||||
// conventMirrorUrl(mirror).asset
|
||||
// );
|
||||
//
|
||||
// logDebug(
|
||||
// LogModule.GITHUB,
|
||||
// `Starting download for versionId: ${versionId}, mirror: ${mirror}, download URL: ${url}`
|
||||
// );
|
||||
//
|
||||
// await download(BrowserWindow.getFocusedWindow(), url, {
|
||||
// filename: `${asset.name}`,
|
||||
// directory: path.join(app.getPath("userData"), "download"),
|
||||
// onProgress: progress => {
|
||||
// event.reply("Download.frpVersionDownloadOnProgress", {
|
||||
// id: versionId,
|
||||
// progress: progress
|
||||
// });
|
||||
// logDebug(
|
||||
// LogModule.GITHUB,
|
||||
// `Download progress for versionId: ${versionId} is ${
|
||||
// progress.percent * 100
|
||||
// }%`
|
||||
// );
|
||||
// },
|
||||
// onCompleted: () => {
|
||||
// logInfo(
|
||||
// LogModule.GITHUB,
|
||||
// `Download completed for versionId: ${versionId}, asset: ${asset.name}`
|
||||
// );
|
||||
//
|
||||
// const frpcVersionPath = decompressFrp(
|
||||
// asset.name,
|
||||
// path.join(
|
||||
// path.join(app.getPath("userData"), "download"),
|
||||
// `${asset.name}`
|
||||
// )
|
||||
// );
|
||||
// version["frpcVersionPath"] = frpcVersionPath;
|
||||
// insertVersion(version, (err, document) => {
|
||||
// if (!err) {
|
||||
// listVersion((err, doc) => {
|
||||
// event.reply("Config.versions.hook", { err, data: doc });
|
||||
// event.reply("Download.frpVersionDownloadOnCompleted", versionId);
|
||||
// version.download_completed = true;
|
||||
// logInfo(
|
||||
// LogModule.GITHUB,
|
||||
// `Version ${versionId} has been inserted successfully.`
|
||||
// );
|
||||
// });
|
||||
// } else {
|
||||
// logError(LogModule.GITHUB, `Error inserting version: ${err}`);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// /**
|
||||
// * 删除下载
|
||||
// */
|
||||
// ipcMain.on("github.deleteVersion", async (event, args) => {
|
||||
// const { absPath, id } = args;
|
||||
// logDebug(
|
||||
// LogModule.GITHUB,
|
||||
// `Attempting to delete version with ID: ${id} and path: ${absPath}`
|
||||
// );
|
||||
// if (fs.existsSync(absPath)) {
|
||||
// // if (process.platform === 'darwin') {
|
||||
// // fs.unlinkSync(absPath.replace(/ /g, '\\ '));
|
||||
// // }else{
|
||||
// // fs.unlinkSync(absPath);
|
||||
// // }
|
||||
// fs.rmSync(absPath, { recursive: true, force: true });
|
||||
// deleteVersionById(id, () => {
|
||||
// logInfo(
|
||||
// LogModule.GITHUB,
|
||||
// `Successfully deleted version with ID: ${id}`
|
||||
// );
|
||||
// });
|
||||
// } else {
|
||||
// logWarn(
|
||||
// LogModule.GITHUB,
|
||||
// `Version with ID: ${id} not found at path: ${absPath}`
|
||||
// );
|
||||
// }
|
||||
// listVersion((err, doc) => {
|
||||
// if (err) {
|
||||
// logError(LogModule.GITHUB, `Error listing versions: ${err}`);
|
||||
// } else {
|
||||
// event.reply("Config.versions.hook", { err, data: doc });
|
||||
// event.reply("Download.deleteVersion.hook", {
|
||||
// err: null,
|
||||
// data: "删除成功"
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// /**
|
||||
// * 获取最后版本
|
||||
// */
|
||||
// ipcMain.on("github.getFrpcDesktopLastVersions", async event => {
|
||||
// logInfo(LogModule.GITHUB, "Requesting the latest version from GitHub.");
|
||||
// const request = net.request({
|
||||
// method: "get",
|
||||
// url: "https://api.github.com/repos/luckjiawei/frpc-desktop/releases/latest"
|
||||
// });
|
||||
// request.on("response", response => {
|
||||
// let responseData: Buffer = Buffer.alloc(0);
|
||||
// response.on("data", (data: Buffer) => {
|
||||
// responseData = Buffer.concat([responseData, data]);
|
||||
// });
|
||||
// response.on("end", () => {
|
||||
// try {
|
||||
// versions = JSON.parse(responseData.toString());
|
||||
// logInfo(
|
||||
// LogModule.GITHUB,
|
||||
// "Successfully retrieved the latest version."
|
||||
// );
|
||||
// event.reply("github.getFrpcDesktopLastVersionsHook", versions);
|
||||
// } catch (error) {
|
||||
// logError(
|
||||
// LogModule.GITHUB,
|
||||
// `Error parsing response data: ${error.message}`
|
||||
// );
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// request.on("error", error => {
|
||||
// logError(LogModule.GITHUB, `Request error: ${error.message}`);
|
||||
// });
|
||||
// request.end();
|
||||
// });
|
||||
//
|
||||
// ipcMain.on(
|
||||
// "download.importFrpFile",
|
||||
// async (event, filePath: string, targetPath: string) => {
|
||||
// const result = await dialog.showOpenDialog(win, {
|
||||
// properties: ["openFile"],
|
||||
// filters: [
|
||||
// { name: "Frp 文件", extensions: ["tar.gz", "zip"] } // 允许选择的文件类型,分开后缀以确保可以选择
|
||||
// ]
|
||||
// });
|
||||
// if (result.canceled) {
|
||||
// logWarn(LogModule.APP, "Import canceled by user.");
|
||||
// logWarn(LogModule.GITHUB, "User canceled the file import operation.");
|
||||
// return;
|
||||
// } else {
|
||||
// const filePath = result.filePaths[0];
|
||||
// // const fileExtension = path.extname(filePath);
|
||||
// logInfo(LogModule.APP, `User selected file: ${filePath}`);
|
||||
// const checksum = calculateFileChecksum(filePath);
|
||||
// logInfo(LogModule.APP, `Calculated checksum for the file: ${checksum}`);
|
||||
// const frpName = frpChecksums[checksum];
|
||||
// if (frpName) {
|
||||
// logInfo(LogModule.APP, `FRP file name found: ${frpName}`);
|
||||
// if (frpArch.every(item => frpName.includes(item))) {
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// `Architecture matches for FRP file: ${frpName}`
|
||||
// );
|
||||
// const version = getVersionByAssetName(frpName);
|
||||
// getVersionById(version.id, (err, existingVersion) => {
|
||||
// if (!err && existingVersion) {
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// `Version already exists: ${JSON.stringify(existingVersion)}`
|
||||
// );
|
||||
// event.reply("Download.importFrpFile.hook", {
|
||||
// success: false,
|
||||
// data: `导入失败,版本已存在`
|
||||
// });
|
||||
// return; // 终止后续执行
|
||||
// }
|
||||
//
|
||||
// const frpcVersionPath = decompressFrp(frpName, filePath);
|
||||
// logInfo(
|
||||
// LogModule.APP,
|
||||
// `Successfully decompressed FRP file: ${frpName} to path: ${frpcVersionPath}`
|
||||
// );
|
||||
// version["frpcVersionPath"] = frpcVersionPath;
|
||||
// insertVersion(version, (err, document) => {
|
||||
// if (!err) {
|
||||
// listVersion((err, doc) => {
|
||||
// event.reply("Config.versions.hook", { err, data: doc });
|
||||
// version.download_completed = true;
|
||||
// event.reply("Download.importFrpFile.hook", {
|
||||
// success: true,
|
||||
// data: `导入成功`
|
||||
// });
|
||||
// });
|
||||
// } else {
|
||||
// logError(LogModule.APP, `Error inserting version: ${err}`);
|
||||
// event.reply("Download.importFrpFile.hook", {
|
||||
// success: true,
|
||||
// data: `导入失败,未知错误`
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// } else {
|
||||
// logWarn(
|
||||
// LogModule.APP,
|
||||
// `Architecture does not match for FRP file: ${frpName}`
|
||||
// );
|
||||
// event.reply("Download.importFrpFile.hook", {
|
||||
// success: false,
|
||||
// data: `导入失败,所选 frp 架构与操作系统不符`
|
||||
// });
|
||||
// }
|
||||
// } else {
|
||||
// logWarn(
|
||||
// LogModule.APP,
|
||||
// `No matching FRP file name found for checksum: ${checksum}`
|
||||
// );
|
||||
// event.reply("Download.importFrpFile.hook", {
|
||||
// success: false,
|
||||
// data: `导入失败,无法识别文件`
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// };
|
@ -1,81 +0,0 @@
|
||||
// import {app, dialog, autoUpdater, BrowserWindow} from "electron";
|
||||
//
|
||||
// const log = require('electron-log');
|
||||
//
|
||||
//
|
||||
// export const initUpdaterApi = (win: BrowserWindow) => {
|
||||
// //更新测试打开
|
||||
// Object.defineProperty(app, 'isPackaged', {
|
||||
// get() {
|
||||
// return true;
|
||||
// }
|
||||
// });
|
||||
// const server = 'https://hazel-git-master-uiluck.vercel.app'
|
||||
// let packageName = null
|
||||
// const platform = process.platform;
|
||||
// const arch = process.arch;
|
||||
// switch (platform) {
|
||||
// case "darwin":
|
||||
// if (arch == "arm64") {
|
||||
// packageName = "darwin_arm64";
|
||||
// } else {
|
||||
// packageName = "darwin";
|
||||
// }
|
||||
// break;
|
||||
// case "win32":
|
||||
// packageName = "exe";
|
||||
// break;
|
||||
// case "linux":
|
||||
// packageName = "AppImage";
|
||||
// if (arch == "arm64") {
|
||||
// packageName = "AppImage_arm64";
|
||||
// } else {
|
||||
// packageName = "AppImage";
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// const url = `${server}/update/${packageName}/${app.getVersion()}`
|
||||
// log.info(`开启自动更新 ${url}`);
|
||||
// autoUpdater.setFeedURL({url: url})
|
||||
//
|
||||
// autoUpdater.on('checking-for-update', () => {
|
||||
// log.info("正在检查更新")
|
||||
// })
|
||||
//
|
||||
// autoUpdater.on('update-available', (event, info) => {
|
||||
// log.info(`发现新版本`)
|
||||
// })
|
||||
//
|
||||
// autoUpdater.on('update-not-available', () => {
|
||||
// log.info('没有可用的更新')
|
||||
//
|
||||
// })
|
||||
//
|
||||
// autoUpdater.on('error', (err) => {
|
||||
// log.error(`更新错误:${err.message}`)
|
||||
//
|
||||
// })
|
||||
//
|
||||
// autoUpdater.on('update-downloaded', () => {
|
||||
// dialog.showMessageBox({
|
||||
// type: 'info',
|
||||
// title: '应用更新',
|
||||
// message: '发现新版本,是否更新?',
|
||||
// buttons: ['是', '否']
|
||||
// }).then((buttonIndex) => {
|
||||
// if (buttonIndex.response == 0) { //选择是,则退出程序,安装新版本
|
||||
// autoUpdater.quitAndInstall()
|
||||
// app.quit()
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
//
|
||||
// // setInterval(() => {
|
||||
// // log.initialize("定时检查更新")
|
||||
// // // autoUpdater.checkForUpdates();
|
||||
// // }, 60000)
|
||||
// autoUpdater.checkForUpdates();
|
||||
// log.info("手动检查更新一次")
|
||||
//
|
||||
//
|
||||
// }
|
Loading…
Reference in New Issue
Block a user