2025-02-18 17:52:09 +08:00
|
|
|
import BaseService from "./BaseService";
|
2025-02-25 11:57:54 +08:00
|
|
|
import ServerRepository from "../repository/ServerRepository";
|
2025-02-23 21:07:44 +08:00
|
|
|
import fs from "fs";
|
|
|
|
import PathUtils from "../utils/PathUtils";
|
2025-02-25 11:57:54 +08:00
|
|
|
import ProxyRepository from "../repository/ProxyRepository";
|
2025-02-25 17:09:14 +08:00
|
|
|
import { BrowserWindow, dialog } from "electron";
|
|
|
|
import BeanFactory from "../core/BeanFactory";
|
|
|
|
import path from "path";
|
|
|
|
import GlobalConstant from "../core/GlobalConstant";
|
|
|
|
import TOML from "smol-toml";
|
|
|
|
|
2025-02-24 14:35:11 +08:00
|
|
|
class ServerService extends BaseService<OpenSourceFrpcDesktopServer> {
|
2025-02-25 11:57:54 +08:00
|
|
|
private readonly _serverDao: ServerRepository;
|
|
|
|
private readonly _proxyDao: ProxyRepository;
|
2025-02-25 17:09:14 +08:00
|
|
|
// private readonly _systemService: SystemService;
|
2025-02-23 21:07:44 +08:00
|
|
|
private readonly _serverId: string = "1";
|
|
|
|
|
2025-02-25 17:09:14 +08:00
|
|
|
constructor(
|
|
|
|
serverDao: ServerRepository,
|
2025-02-26 12:31:57 +08:00
|
|
|
proxyDao: ProxyRepository
|
2025-02-25 17:09:14 +08:00
|
|
|
// systemService: SystemService
|
|
|
|
) {
|
2025-02-21 18:30:13 +08:00
|
|
|
super();
|
|
|
|
this._serverDao = serverDao;
|
2025-02-23 21:07:44 +08:00
|
|
|
this._proxyDao = proxyDao;
|
2025-02-25 17:09:14 +08:00
|
|
|
// this._systemService = systemService;
|
2025-02-18 17:52:09 +08:00
|
|
|
}
|
|
|
|
|
2025-02-23 02:11:17 +08:00
|
|
|
async saveServerConfig(
|
2025-02-24 14:35:11 +08:00
|
|
|
frpcServer: OpenSourceFrpcDesktopServer
|
|
|
|
): Promise<OpenSourceFrpcDesktopServer> {
|
2025-02-23 21:07:44 +08:00
|
|
|
frpcServer._id = this._serverId;
|
|
|
|
return await this._serverDao.updateById(this._serverId, frpcServer);
|
2025-02-21 18:30:13 +08:00
|
|
|
}
|
|
|
|
|
2025-02-24 14:35:11 +08:00
|
|
|
async getServerConfig(): Promise<OpenSourceFrpcDesktopServer> {
|
2025-02-23 21:07:44 +08:00
|
|
|
return await this._serverDao.findById(this._serverId);
|
2025-02-21 18:30:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
hasServerConfig(): Promise<boolean> {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this._serverDao
|
2025-02-23 21:07:44 +08:00
|
|
|
.exists(this._serverId)
|
2025-02-21 18:30:13 +08:00
|
|
|
.then(r => {
|
|
|
|
resolve(r);
|
|
|
|
})
|
|
|
|
.catch(err => reject(err));
|
|
|
|
});
|
|
|
|
}
|
2025-02-23 21:07:44 +08:00
|
|
|
|
2025-02-26 15:58:48 +08:00
|
|
|
private isRagePort(proxy: FrpcProxy) {
|
|
|
|
return (
|
|
|
|
["tcp", "udp"].indexOf(proxy.type) >= 0 &&
|
|
|
|
(String(proxy.localPort).indexOf("-") !== -1 ||
|
|
|
|
String(proxy.localPort).indexOf(",") !== -1)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private isVisitors(proxy: FrpcProxy) {
|
|
|
|
return (
|
|
|
|
["stcp", "sudp", "xtcp"].indexOf(proxy.type) >= 0 &&
|
|
|
|
proxy.visitorsModel === "visitors"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private isEnableProxy(proxy: FrpcProxy) {
|
|
|
|
return proxy.status === 1;
|
|
|
|
}
|
|
|
|
|
2025-02-24 16:38:39 +08:00
|
|
|
async genTomlConfig(outputPath: string) {
|
|
|
|
if (!outputPath) {
|
|
|
|
return;
|
|
|
|
}
|
2025-02-23 21:07:44 +08:00
|
|
|
const server = await this.getServerConfig();
|
|
|
|
const proxies = await this._proxyDao.findAll();
|
2025-02-26 15:58:48 +08:00
|
|
|
|
|
|
|
const enabledRangePortProxies = proxies
|
|
|
|
.filter(f => this.isEnableProxy(f))
|
|
|
|
.filter(f => !this.isVisitors(f))
|
|
|
|
.filter(f => this.isRagePort(f))
|
|
|
|
.map(proxy => {
|
|
|
|
return `
|
|
|
|
{{- range $_, $v := parseNumberRangePair "${proxy.localPort}" "${proxy.remotePort}" }}
|
|
|
|
[[proxies]]
|
|
|
|
|
|
|
|
type = "${proxy.type}"
|
|
|
|
name = "${proxy.name}-{{ $v.First }}"
|
|
|
|
localPort = {{ $v.First }}
|
|
|
|
remotePort = {{ $v.Second }}
|
|
|
|
{{- end }}
|
|
|
|
`;
|
|
|
|
});
|
|
|
|
|
2025-02-23 21:07:44 +08:00
|
|
|
const enabledProxies = proxies
|
2025-02-26 15:58:48 +08:00
|
|
|
.filter(f => this.isEnableProxy(f))
|
|
|
|
.filter(f => !this.isVisitors(f))
|
|
|
|
.filter(f => !this.isRagePort(f))
|
2025-02-23 21:07:44 +08:00
|
|
|
.map(proxy => {
|
2025-02-26 14:56:10 +08:00
|
|
|
if (proxy.type === "tcp" || proxy.type === "udp") {
|
2025-02-26 15:58:48 +08:00
|
|
|
const localPort = parseInt(proxy.localPort);
|
|
|
|
const remotePort = parseInt(proxy.remotePort);
|
2025-02-26 14:56:10 +08:00
|
|
|
return {
|
|
|
|
name: proxy.name,
|
|
|
|
type: proxy.type,
|
|
|
|
localIP: proxy.localIP,
|
2025-02-26 15:58:48 +08:00
|
|
|
localPort: localPort,
|
|
|
|
remotePort: remotePort
|
2025-02-26 14:56:10 +08:00
|
|
|
};
|
|
|
|
} else if (proxy.type === "http" || proxy.type === "https") {
|
2025-02-26 16:45:18 +08:00
|
|
|
return {
|
|
|
|
name: proxy.name,
|
|
|
|
type: proxy.type,
|
|
|
|
localIP: proxy.localIP,
|
|
|
|
localPort: parseInt(proxy.localPort),
|
|
|
|
customDomains: proxy.customDomains,
|
|
|
|
subdomain: proxy.subdomain,
|
|
|
|
...(proxy.basicAuth
|
|
|
|
? { httpUser: proxy.httpUser, httpPassword: proxy.httpPassword }
|
|
|
|
: {})
|
|
|
|
};
|
2025-02-26 14:56:10 +08:00
|
|
|
} else if (
|
|
|
|
proxy.type === "stcp" ||
|
|
|
|
proxy.type === "xtcp" ||
|
|
|
|
proxy.type === "sudp"
|
|
|
|
) {
|
|
|
|
return {
|
|
|
|
name: proxy.name,
|
|
|
|
type: proxy.type,
|
|
|
|
localIP: proxy.localIP,
|
|
|
|
localPort: parseInt(proxy.localPort),
|
|
|
|
secretKey: proxy.secretKey
|
|
|
|
};
|
2025-02-26 12:31:57 +08:00
|
|
|
}
|
2025-02-23 21:07:44 +08:00
|
|
|
});
|
2025-02-26 14:56:10 +08:00
|
|
|
|
|
|
|
const enableVisitors = proxies
|
2025-02-26 15:58:48 +08:00
|
|
|
.filter(f => this.isEnableProxy(f))
|
|
|
|
.filter(f => this.isVisitors(f))
|
2025-02-26 14:56:10 +08:00
|
|
|
.map(proxy => {
|
2025-02-26 15:58:48 +08:00
|
|
|
if (proxy.type === "xtcp") {
|
|
|
|
return {
|
|
|
|
name: proxy.name,
|
|
|
|
type: proxy.type,
|
|
|
|
// serverUser: proxy.serverUser,
|
|
|
|
serverName: proxy.serverName,
|
|
|
|
secretKey: proxy.secretKey,
|
|
|
|
bindAddr: proxy.bindAddr,
|
|
|
|
bindPort: proxy.bindPort,
|
|
|
|
keepTunnelOpen: proxy.keepTunnelOpen,
|
|
|
|
fallbackTo: proxy.fallbackTo,
|
|
|
|
fallbackTimeoutMs: proxy.fallbackTimeoutMs
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
name: proxy.name,
|
|
|
|
type: proxy.type,
|
|
|
|
serverName: proxy.serverName,
|
|
|
|
secretKey: proxy.secretKey,
|
|
|
|
bindAddr: proxy.bindAddr,
|
|
|
|
bindPort: proxy.bindPort
|
|
|
|
};
|
|
|
|
}
|
2025-02-26 14:56:10 +08:00
|
|
|
});
|
|
|
|
|
2025-02-23 21:07:44 +08:00
|
|
|
const { frpcVersion, _id, system, ...commonConfig } = server;
|
|
|
|
const frpcConfig = { ...commonConfig };
|
|
|
|
frpcConfig.log.to = PathUtils.getFrpcLogFilePath();
|
2025-02-26 14:56:10 +08:00
|
|
|
frpcConfig.loginFailExit = GlobalConstant.FRPC_LOGIN_FAIL_EXIT;
|
|
|
|
frpcConfig.webServer.addr = GlobalConstant.LOCAL_IP;
|
2025-02-26 15:58:48 +08:00
|
|
|
|
|
|
|
let toml = TOML.stringify({
|
2025-02-26 14:56:10 +08:00
|
|
|
...frpcConfig,
|
2025-02-26 15:58:48 +08:00
|
|
|
...(enabledProxies.length > 0 ? { proxies: enabledProxies } : {}),
|
|
|
|
...(enableVisitors.length > 0 ? { visitors: enableVisitors } : {})
|
|
|
|
});
|
|
|
|
|
|
|
|
enabledRangePortProxies.forEach(f => {
|
|
|
|
toml += `
|
|
|
|
${f}`;
|
2025-02-26 14:56:10 +08:00
|
|
|
});
|
2025-02-24 16:38:39 +08:00
|
|
|
|
2025-02-26 14:56:10 +08:00
|
|
|
fs.writeFileSync(outputPath, toml, { flag: "w" });
|
2025-02-23 21:07:44 +08:00
|
|
|
}
|
2025-02-25 17:09:14 +08:00
|
|
|
|
|
|
|
async importTomlConfig() {
|
|
|
|
const win: BrowserWindow = BeanFactory.getBean("win");
|
|
|
|
const result = await dialog.showOpenDialog(win, {
|
|
|
|
properties: ["openFile"],
|
2025-02-26 12:31:57 +08:00
|
|
|
filters: [{ name: "Frpc Toml ConfigFile", extensions: ["toml"] }]
|
2025-02-25 17:09:14 +08:00
|
|
|
});
|
|
|
|
if (result.canceled) {
|
2025-02-26 12:31:57 +08:00
|
|
|
} else {
|
2025-02-25 17:09:14 +08:00
|
|
|
const filePath = result.filePaths[0];
|
|
|
|
const fileExtension = path.extname(filePath);
|
|
|
|
if (fileExtension === GlobalConstant.TOML_EXT) {
|
|
|
|
const tomlData = fs.readFileSync(filePath, "utf-8");
|
|
|
|
const sourceConfig = TOML.parse(tomlData);
|
|
|
|
} else {
|
|
|
|
throw new Error(`导入失败,暂不支持 ${fileExtension} 格式文件`);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2025-02-18 17:52:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export default ServerService;
|