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.

399 lines
11 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);
}
});
// 执行查询
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
};