|
|
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);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 执行查询
|
|
|
const sql = "SELECT * FROM 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);
|
|
|
}
|
|
|
resolve(rows);
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
function updateMessageById(id, data) {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
const db = new sqlite3.Database(getDatabasePath(), err => {
|
|
|
if (err) {
|
|
|
return reject(err);
|
|
|
}
|
|
|
});
|
|
|
debugger;
|
|
|
// 解构data中的所有字段(根据实际表结构调整字段名)
|
|
|
const { message, status } = data;
|
|
|
|
|
|
// 构建更新字段字符串(排除ID,避免更新主键)
|
|
|
const fields = [];
|
|
|
const params = [];
|
|
|
|
|
|
// 动态处理所有字段(确保与表结构一致)
|
|
|
if (message !== undefined) {
|
|
|
fields.push("message = ?");
|
|
|
params.push(message);
|
|
|
}
|
|
|
if (status !== undefined) {
|
|
|
fields.push("status = ?");
|
|
|
params.push(status);
|
|
|
}
|
|
|
// 构建SQL语句(UPDATE message SET 字段1=?, 字段2=? WHERE id=?)
|
|
|
const sql = `UPDATE message SET ${fields.join(", ")} WHERE id = ?`;
|
|
|
params.push(id); // 最后添加WHERE条件的ID参数
|
|
|
|
|
|
// 执行更新
|
|
|
db.run(sql, params, function (err) {
|
|
|
if (err) {
|
|
|
console.error("更新message表失败:", err.message);
|
|
|
reject({ code: 1, msg: `更新失败:${err.message}` });
|
|
|
} else {
|
|
|
if (this.changes > 0) {
|
|
|
resolve({
|
|
|
code: 0,
|
|
|
msg: `成功更新ID为${id}的记录`,
|
|
|
affectedRows: this.changes
|
|
|
});
|
|
|
} else {
|
|
|
resolve({ code: 2, msg: `未找到ID为${id}的记录`, affectedRows: 0 });
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
// <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);
|
|
|
}
|
|
|
}
|
|
|
async function stopChatProcesses() {
|
|
|
try {
|
|
|
delete processes["chatProcess"];
|
|
|
const projectRoot = process.cwd();
|
|
|
const parentDir = path.dirname(projectRoot);
|
|
|
const exPath = path.join(parentDir, "kill-chat.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,
|
|
|
stopChatProcesses,
|
|
|
getAllSystemMessages,
|
|
|
updateMessageById
|
|
|
};
|