const sqlite3 = require("sqlite3").verbose(); const path = require("path"); const { app } = require("electron"); const { spawn, exec } = require("child_process"); // �������ù��� const processes = { LiveTalkingProcess: null, gptsovitsProcess: null, chatProcess: null }; // ��ȡ���ݿ�·�� function getDatabasePath() { if (process.env.NODE_ENV === "development") { const dbPath = path.join(__dirname, "..", "..", "live_chat.db"); return dbPath; } else { const exePath = app.getPath("exe"); // ��ȡwin-unpacked�ļ���·�� const winUnpackedDir = path.dirname(exePath); // ��ȡwin-unpacked���ϼ�Ŀ¼����win-unpackedͬ����Ŀ¼�� const parentDir = path.dirname(winUnpackedDir); // ����live_chat.db������·�� const dbPath = path.join(parentDir, "live_chat.db"); console.log("dbPath", dbPath); return dbPath; } } // ��������ֵ function updateConfig(tableName, key, value) { return new Promise((resolve, reject) => { const db = new sqlite3.Database(getDatabasePath(), err => { if (err) { console.error("���ݿ����Ӵ���:", err.message); return reject(err); } }); // �ȳ��Ը��£����Ӱ������Ϊ0������¼�¼ db.run( `UPDATE ${tableName} SET value = ? WHERE key = ?`, [value, key], function (err) { if (err) { db.close(); return reject(err); } // ���û��ƥ��ļ�¼����� 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 }); } } ); }); } // ��ȡ����ֵ 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 }); } } }); }); } // ��������ϵͳ��Ϣ const bulkInsertSystemMessages = messages => { return new Promise((resolve, reject) => { if (!Array.isArray(messages) || messages.length === 0) { reject(new Error("���ṩ��Ч����Ϣ����")); return; } try { const db = new sqlite3.Database(getDatabasePath(), err => { if (err) { reject(err); return; } // ʹ����������������룬������� 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++; // ������Ϣ��������� 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); } }); }; // ���ϵͳ��Ϣ�� const clearSystemMessages = () => { return new Promise((resolve, reject) => { const db = new sqlite3.Database(getDatabasePath(), err => { if (err) { reject(err); return; } // ʹ��TRUNCATE-like������ձ���ͬʱ��������ID db.run("DELETE FROM system_message", err => { if (err) { reject(err); db.close(); return; } // ����������������SQLite�ض��� 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; // �ж��Ƿ�Ϊ�������� if (process.env.NODE_ENV === "development") { // process.cwd() ͨ��ָ����Ŀ��Ŀ¼ const projectRoot = process.cwd(); const parentDir = path.dirname(projectRoot); exePath = path.join(parentDir, fileName, exeName); exeFolder = path.join(parentDir, fileName); } else { // ��������: ��win-unpackedͬ��Ŀ¼�µ�LiveTalking�ļ��� exePath = app.getPath("exe"); // ��ȡwin-unpacked�ļ���·�� const winUnpackedDir = path.dirname(exePath); // ��ȡwin-unpacked���ϼ�Ŀ¼ const parentDir = path.dirname(winUnpackedDir); exePath = path.join(parentDir, fileName, exeName); exeFolder = path.join(parentDir, fileName); } console.log("exePath", exePath); console.log("exeFolder", exeFolder); // ��׼��·����ʽ return { exePath, exeFolder }; } /** * ����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; } // ��ȡ����·�� const obj = getProcessExePath(fileName, exeName); try { // ��������ʱ��ͨ��wmic��ȡ��ϸ��Ϣ����Windows�� // const newProcess = spawn("cmd.exe", ["/c", obj.exePath], { // // ֱ������bat����ʹ��start���� // cwd: obj.exeFolder, // windowsVerbatimArguments: true, // windowsHide: false, // detached: false // �����룬���ڸ����ӽ��� // }); const newProcess = spawn( "cmd.exe", ["/c", "start", '""', `"${obj.exePath}"`], { cwd: obj.exeFolder, windowsVerbatimArguments: true, windowsHide: false, detached: true } ); // ��¼����ID���ؼ�������ʵ��PID�� processes[processKey] = { process: newProcess, pid: newProcess.pid // ����PID���ں�����ֹ }; newProcess.on("error", err => { processes[processKey] = null; reject(`����ʧ��: ${err.message}`); }); console.log(`spawned with PID ${newProcess.pid}`); resolve(`${fileName} �����ɹ� (PID: ${newProcess.pid})`); } catch (err) { reject(`�����쳣: ${err.message}`); } }); } // ֹͣ���н��� async function stopAllProcesses() { try { // ����������ԣ���ɿն��� 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 };