You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
9.6 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

const sqlite3 = require("sqlite3").verbose();
const path = require("path");
const { app } = require("electron");
const { spawn, exec } = require("child_process");
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ù<EFBFBD><C3B9><EFBFBD>
const processes = {
LiveTalkingProcess: null,
gptsovitsProcess: null,
chatProcess: null
};
// <20><>ȡ<EFBFBD><C8A1><EFBFBD>ݿ<EFBFBD>·<EFBFBD><C2B7>
function getDatabasePath() {
if (process.env.NODE_ENV === "development") {
const dbPath = path.join(__dirname, "..", "..", "live_chat.db");
return dbPath;
} else {
const exePath = app.getPath("exe");
// <20><>ȡwin-unpacked<65>ļ<EFBFBD><C4BC><EFBFBD>·<EFBFBD><C2B7>
const winUnpackedDir = path.dirname(exePath);
// <20><>ȡwin-unpacked<65><64><EFBFBD>ϼ<EFBFBD>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD>win-unpackedͬ<64><CDAC><EFBFBD><EFBFBD>Ŀ¼<C4BF><C2BC>
const parentDir = path.dirname(winUnpackedDir);
// <20><><EFBFBD><EFBFBD>live_chat.db<64><62><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
const dbPath = path.join(parentDir, "live_chat.db");
console.log("dbPath", dbPath);
return dbPath;
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
function updateConfig(tableName, key, value) {
return new Promise((resolve, reject) => {
const db = new sqlite3.Database(getDatabasePath(), err => {
if (err) {
console.error("<22><><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>Ӵ<EFBFBD><D3B4><EFBFBD>:", err.message);
return reject(err);
}
});
// <20>ȳ<EFBFBD><C8B3>Ը<EFBFBD><D4B8>£<EFBFBD><C2A3><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ0<CEAA><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>¼
db.run(
`UPDATE ${tableName} SET value = ? WHERE key = ?`,
[value, key],
function (err) {
if (err) {
db.close();
return reject(err);
}
// <20><><EFBFBD>û<EFBFBD><C3BB>ƥ<EFBFBD><C6A5>ļ<EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>
if (this.changes === 0) {
db.run(
`INSERT INTO ${tableName} (key, value) VALUES (?, ?)`,
[key, value],
function (err) {
db.close();
if (err) return reject(err);
resolve({
success: true,
action: "insert",
changes: this.changes
});
}
);
} else {
db.close();
resolve({ success: true, action: "update", changes: this.changes });
}
}
);
});
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ֵ
function getConfigValue(tableName, key) {
return new Promise((resolve, reject) => {
const db = new sqlite3.Database(getDatabasePath(), err => {
if (err) {
return reject(err);
}
});
db.get(
`SELECT value FROM ${tableName} WHERE key = ?`,
[key],
(err, row) => {
db.close();
if (err) return reject(err);
resolve(row ? row.value : null);
}
);
});
}
function getAllSystemMessages() {
return new Promise((resolve, reject) => {
// 连接数据库
const db = new sqlite3.Database(getDatabasePath(), err => {
if (err) {
console.error("数据库连接错误:", err.message);
return reject(err);
}
console.log("成功连接到数据库");
});
// 执行查询
const sql = "SELECT message FROM system_message";
db.all(sql, [], (err, rows) => {
// 关闭数据库连接
db.close(closeErr => {
if (closeErr) {
console.error("关闭数据库错误:", closeErr.message);
return reject(closeErr);
}
});
if (err) {
console.error("查询错误:", err.message);
return reject(err);
}
// 提取所有message字段
const messages = rows.map(row => row.message);
resolve(messages);
});
});
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3>Ϣ
const bulkInsertSystemMessages = messages => {
return new Promise((resolve, reject) => {
if (!Array.isArray(messages) || messages.length === 0) {
reject(new Error("<22><><EFBFBD><EFBFBD><E1B9A9>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>"));
return;
}
try {
const db = new sqlite3.Database(getDatabasePath(), err => {
if (err) {
reject(err);
return;
}
// ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
db.run("BEGIN TRANSACTION", err => {
if (err) {
reject(err);
db.close();
return;
}
const stmt = db.prepare(
"INSERT INTO system_message (message) VALUES (?)"
);
let completed = 0;
let errorOccurred = null;
messages.forEach(message => {
stmt.run(message, function (err) {
if (err && !errorOccurred) {
errorOccurred = err;
}
completed++;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (completed === messages.length) {
stmt.finalize();
if (errorOccurred) {
db.run("ROLLBACK", () => {
reject(errorOccurred);
db.close();
});
} else {
db.run("COMMIT", err => {
if (err) {
reject(err);
} else {
resolve({
success: true,
count: messages.length
});
}
db.close();
});
}
}
});
});
});
});
} catch (error) {
reject(error);
}
});
};
// <20><><EFBFBD>ϵͳ<CFB5><CDB3>Ϣ<EFBFBD><CFA2>
const clearSystemMessages = () => {
return new Promise((resolve, reject) => {
const db = new sqlite3.Database(getDatabasePath(), err => {
if (err) {
reject(err);
return;
}
// ʹ<><CAB9>TRUNCATE-like<6B><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ձ<EFBFBD><D5B1><EFBFBD>ͬʱ<CDAC><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID
db.run("DELETE FROM system_message", err => {
if (err) {
reject(err);
db.close();
return;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SQLite<74>ض<EFBFBD><D8B6><EFBFBD>
db.run(
"DELETE FROM sqlite_sequence WHERE name = 'system_message'",
err => {
if (err) {
reject(err);
} else {
resolve({ success: true });
}
db.close();
}
);
});
});
});
};
function getProcessExePath(fileName, exeName) {
let exePath;
let exeFolder;
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (process.env.NODE_ENV === "development") {
// process.cwd() ͨ<><CDA8>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>Ŀ¼
const projectRoot = process.cwd();
const parentDir = path.dirname(projectRoot);
exePath = path.join(parentDir, fileName, exeName);
exeFolder = path.join(parentDir, fileName);
} else {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><>win-unpackedͬ<64><CDAC>Ŀ¼<C4BF>µ<EFBFBD>LiveTalking<6E>ļ<EFBFBD><C4BC><EFBFBD>
exePath = app.getPath("exe");
// <20><>ȡwin-unpacked<65>ļ<EFBFBD><C4BC><EFBFBD>·<EFBFBD><C2B7>
const winUnpackedDir = path.dirname(exePath);
// <20><>ȡwin-unpacked<65><64><EFBFBD>ϼ<EFBFBD>Ŀ¼
const parentDir = path.dirname(winUnpackedDir);
exePath = path.join(parentDir, fileName, exeName);
exeFolder = path.join(parentDir, fileName);
}
console.log("exePath", exePath);
console.log("exeFolder", exeFolder);
// <20><>׼<EFBFBD><D7BC>·<EFBFBD><C2B7><EFBFBD><EFBFBD>ʽ
return { exePath, exeFolder };
}
/**
* <20><><EFBFBD><EFBFBD>LiveTalking.exe
*/
async function startProcess(fileName, exeName) {
return new Promise(async (resolve, reject) => {
const processKey = `${fileName}Process`;
if (processes[processKey]) {
reject(`${fileName} is already running`);
return;
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
const obj = getProcessExePath(fileName, exeName);
try {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ͨ<EFBFBD><CDA8>wmic<69><63>ȡ<EFBFBD><C8A1>ϸ<EFBFBD><CFB8>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>Windows<77><73>
// const newProcess = spawn("cmd.exe", ["/c", obj.exePath], {
// // ֱ<><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>bat<61><74><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>start<72><74><EFBFBD><EFBFBD>
// cwd: obj.exeFolder,
// windowsVerbatimArguments: true,
// windowsHide: false,
// detached: false // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBA3AC><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD>
// });
const newProcess = spawn(
"cmd.exe",
["/c", "start", '""', `"${obj.exePath}"`],
{
cwd: obj.exeFolder,
windowsVerbatimArguments: true,
windowsHide: false,
detached: true
}
);
// <20><>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>ID<49><44><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>PID<49><44>
processes[processKey] = {
process: newProcess,
pid: newProcess.pid // <20><><EFBFBD><EFBFBD>PID<49><44><EFBFBD>ں<EFBFBD><DABA><EFBFBD><EFBFBD><EFBFBD>ֹ
};
newProcess.on("error", err => {
processes[processKey] = null;
reject(`<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>: ${err.message}`);
});
console.log(`spawned with PID ${newProcess.pid}`);
resolve(`${fileName} <20><><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD> (PID: ${newProcess.pid})`);
} catch (err) {
reject(`<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>쳣: ${err.message}`);
}
});
}
// ֹͣ<CDA3><D6B9><EFBFBD>н<EFBFBD><D0BD><EFBFBD>
async function stopAllProcesses() {
try {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD>ɿն<C9BF><D5B6><EFBFBD>
for (const key in processes) {
if (processes[key]) {
delete processes[key];
}
}
const projectRoot = process.cwd();
const parentDir = path.dirname(projectRoot);
const exPath = path.join(parentDir, "kill-live.bat");
const child = spawn("cmd.exe", ["/c", "start", '""', `"${exPath}"`], {
cwd: parentDir,
windowsVerbatimArguments: true,
windowsHide: false,
detached: true
});
child.unref();
} catch (err) {
console.error(err);
}
}
module.exports = {
updateConfig,
getConfigValue,
bulkInsertSystemMessages,
clearSystemMessages,
startProcess,
stopAllProcesses,
getAllSystemMessages
};