返回 AiToEarn
index.ts
1 /*
2 * @Author: nevin
3 * @Date: 2025-01-20 16:22:03
4 * @LastEditTime: 2025-03-18 22:53:17
5 * @LastEditors: nevin
6 * @Description: 数据库
7 */
8 import { DataSource } from 'typeorm';
9 import { AccountModel } from './models/account';
10 import { UserModel } from './models/user';
11 import { PubRecordModel } from './models/pubRecord';
12 import { VideoModel } from './models/video';
13 import * as migrations from './migrations';
14 import path from 'path';
15 import { app } from 'electron';
16 import fs from 'fs/promises';
17 import { logger } from '../global/log';
18 import { AutoRunModel } from './models/autoRun';
19 import { AutoRunRecordModel } from './models/autoRunRecord';
20 import { ImgTextModel } from './models/imgText';
21 import { ReplyCommentRecordModel } from './models/replyCommentRecord';
22 import { InteractionRecordModel } from './models/interactionRecord';
23 import { AccountGroupModel } from './models/accountGroup';
24 import { defaultAccountGroupId } from '../../commont/AccountEnum';
25
26 const configPath = app.getPath('userData');
27 const database = path.join(configPath, 'database.sqlite');
28 logger.log('att database path:', database);
29
30 export const AppDataSource = new DataSource({
31 type: 'better-sqlite3', // 设定链接的数据库类型
32 database, // 数据库存放地址
33 synchronize: true, // 确保每次运行应用程序时实体都将与数据库同步
34 logging: false, // 日志,默认在控制台中打印,数组列举错误类型枚举
35 entities: [
36 AccountModel,
37 UserModel,
38 PubRecordModel,
39 VideoModel,
40 AutoRunModel,
41 AutoRunRecordModel,
42 ImgTextModel,
43 ReplyCommentRecordModel,
44 InteractionRecordModel,
45 AccountGroupModel,
46 ], // 实体或模型表
47 migrations: Object.values(migrations), // 迁移类
48 migrationsRun: true, // 确保在连接时自动运行迁移
49 });
50
51 // 数据库默认数据添加
52 async function sqliteDefaultDataInit() {
53 // 添加用户组 【默认列表】
54 const accountGroupRepository = AppDataSource.getRepository(AccountGroupModel);
55 const accountGroup = await accountGroupRepository.findOne({
56 where: { id: defaultAccountGroupId },
57 });
58 if (!accountGroup) {
59 await accountGroupRepository.save({
60 id: defaultAccountGroupId,
61 name: '默认列表',
62 rank: 0,
63 });
64 }
65 }
66
67 /**
68 * 初始化sqlite3数据库
69 */
70 export async function initSqlite3Db() {
71 if (!AppDataSource.isInitialized) {
72 try {
73 await AppDataSource.initialize();
74 await sqliteDefaultDataInit();
75 // await AppDataSource.runMigrations(); // 上面已经有自动迁移
76 return true;
77 } catch (error) {
78 logger.error('Error during database initialization:', error);
79 return false;
80 }
81 }
82 return true;
83 }
84
85 /**
86 * 导出数据库到SQL文件
87 * @param filePath 导出文件路径
88 */
89 export async function exportDatabase(filePath: string): Promise<void> {
90 try {
91 if (!AppDataSource.isInitialized) {
92 logger.error('Database is not initialized');
93 throw new Error('Database is not initialized');
94 }
95
96 const queryRunner = AppDataSource.createQueryRunner();
97 await queryRunner.connect();
98
99 // 获取所有表的数据
100 const tables = AppDataSource.entityMetadatas.map(
101 (entity) => entity.tableName,
102 );
103 let sqlContent = '';
104
105 for (const table of tables) {
106 const records = await queryRunner.query(`SELECT * FROM ${table}`);
107 if (records.length > 0) {
108 sqlContent += `-- Table: ${table}\n`;
109 for (const record of records) {
110 const columns = Object.keys(record).join(', ');
111 const values = Object.values(record)
112 .map((value) => {
113 if (value === null) return 'NULL';
114 if (typeof value === 'string')
115 return `'${value.replace(/'/g, "''")}'`;
116 return value;
117 })
118 .join(', ');
119 sqlContent += `INSERT INTO ${table} (${columns}) VALUES (${values});\n`;
120 }
121 sqlContent += '\n';
122 }
123 }
124
125 await fs.writeFile(filePath, sqlContent, 'utf8');
126 await queryRunner.release();
127 } catch (error) {
128 logger.error('Failed to export database:', error);
129 throw error;
130 }
131 }
132
133 /**
134 * 从SQL文件导入数据
135 * @param filePath SQL文件路径
136 */
137 export async function importDatabase(filePath: string): Promise<void> {
138 try {
139 if (!AppDataSource.isInitialized) {
140 throw new Error('Database is not initialized');
141 }
142
143 const sqlContent = await fs.readFile(filePath, 'utf8');
144 const queryRunner = AppDataSource.createQueryRunner();
145 await queryRunner.connect();
146 await queryRunner.startTransaction();
147
148 try {
149 // 清空所有表
150 const tables = AppDataSource.entityMetadatas.map(
151 (entity) => entity.tableName,
152 );
153 for (const table of tables) {
154 await queryRunner.query(`DELETE FROM ${table}`);
155 }
156
157 // 执行SQL语句
158 const statements = sqlContent
159 .split('\n')
160 .filter((line) => line.trim() && !line.startsWith('--'))
161 .join('\n')
162 .split(';')
163 .filter((statement) => statement.trim());
164
165 for (const statement of statements) {
166 await queryRunner.query(statement);
167 }
168
169 await queryRunner.commitTransaction();
170 } catch (error) {
171 await queryRunner.rollbackTransaction();
172 throw error;
173 } finally {
174 await queryRunner.release();
175 }
176 } catch (error) {
177 logger.error('Failed to import database:', error);
178 throw error;
179 }
180 }
181
181 lines TYPESCRIPT