config.service.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import { Injectable } from '@nestjs/common';
  2. import Database from 'better-sqlite3';
  3. import fs from 'fs';
  4. import path from 'path';
  5. @Injectable()
  6. export class ConfigService {
  7. private dataDir: string;
  8. private unifiedDbPath: string;
  9. constructor() {
  10. // Find project root by traversing up from current directory until we find the root package.json
  11. let projectRoot = process.cwd();
  12. while (projectRoot !== path.dirname(projectRoot)) {
  13. if (fs.existsSync(path.join(projectRoot, 'package.json'))) {
  14. try {
  15. const pkg = JSON.parse(
  16. fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf-8'),
  17. );
  18. if (pkg.name === 'watch-finished-turbo') {
  19. break;
  20. }
  21. } catch (e) {
  22. // ignore
  23. }
  24. }
  25. projectRoot = path.dirname(projectRoot);
  26. }
  27. this.dataDir = path.resolve(projectRoot, 'data');
  28. this.unifiedDbPath = path.resolve(this.dataDir, 'database.db');
  29. console.log('ConfigService: Database path:', this.unifiedDbPath);
  30. console.log('ConfigService: Project root:', projectRoot);
  31. console.log('ConfigService: Current working directory:', process.cwd());
  32. // Ensure database and tables exist
  33. const db = new Database(this.unifiedDbPath);
  34. db.exec(`
  35. CREATE TABLE IF NOT EXISTS settings (
  36. key TEXT PRIMARY KEY,
  37. value TEXT
  38. );
  39. `);
  40. db.close();
  41. }
  42. getSettings(key?: string, defaultValue?: any): any {
  43. try {
  44. const db = new Database(this.unifiedDbPath, { readonly: true });
  45. if (key) {
  46. const row = db
  47. .prepare('SELECT value FROM settings WHERE key = ?')
  48. .get(key) as { value?: string } | undefined;
  49. db.close();
  50. return row && row.value !== undefined
  51. ? JSON.parse(row.value)
  52. : defaultValue;
  53. } else {
  54. const rows = db
  55. .prepare('SELECT key, value FROM settings')
  56. .all() as Array<{ key: string; value: string }>;
  57. db.close();
  58. const settings: Record<string, any> = {};
  59. for (const row of rows) {
  60. settings[row.key] = JSON.parse(row.value);
  61. }
  62. return settings;
  63. }
  64. } catch (e) {
  65. if (key) return defaultValue;
  66. return {};
  67. }
  68. }
  69. getConfigFile(name: string): any {
  70. // For datasources: name = kids.json, pr0n.json, tvshows.json
  71. const base = name.replace(/\.json$/, '');
  72. try {
  73. const db = new Database(this.unifiedDbPath, { readonly: true });
  74. const row = db
  75. .prepare('SELECT data FROM datasets WHERE name = ?')
  76. .get(base) as { data?: string } | undefined;
  77. db.close();
  78. return row && row.data !== undefined ? JSON.parse(row.data) : null;
  79. } catch (e) {
  80. return null;
  81. }
  82. }
  83. listConfigs(): string[] {
  84. // Return all dataset names as .json (regardless of enabled)
  85. try {
  86. const db = new Database(this.unifiedDbPath, { readonly: true });
  87. const rows = db.prepare('SELECT name FROM datasets').all() as Array<{
  88. name: string;
  89. }>;
  90. db.close();
  91. // Debug: log found rows
  92. if (rows.length === 0) {
  93. console.warn('No configs found in datasets table');
  94. }
  95. return rows.map((row) => row.name + '.json');
  96. } catch (e) {
  97. console.error('Error in listConfigs:', e);
  98. return [];
  99. }
  100. }
  101. setSettings(settings: Record<string, any>): boolean {
  102. try {
  103. const db = new Database(this.unifiedDbPath);
  104. const insert = db.prepare(
  105. 'INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)',
  106. );
  107. for (const [key, value] of Object.entries(settings)) {
  108. // If value is already a JSON string, save it as-is
  109. // Otherwise, stringify it
  110. let valueToSave: string;
  111. if (typeof value === 'string') {
  112. // Check if it's already valid JSON
  113. try {
  114. JSON.parse(value);
  115. valueToSave = value;
  116. } catch {
  117. // Not valid JSON, stringify it
  118. valueToSave = JSON.stringify(value);
  119. }
  120. } else {
  121. // It's an object, stringify it
  122. valueToSave = JSON.stringify(value);
  123. }
  124. insert.run(key, valueToSave);
  125. }
  126. db.close();
  127. return true;
  128. } catch (e) {
  129. console.error('Error setting settings:', e);
  130. return false;
  131. }
  132. }
  133. deleteSetting(key: string): boolean {
  134. try {
  135. const db = new Database(this.unifiedDbPath);
  136. const result = db.prepare('DELETE FROM settings WHERE key = ?').run(key);
  137. db.close();
  138. return result.changes > 0;
  139. } catch (e) {
  140. console.error('Error deleting setting:', e);
  141. return false;
  142. }
  143. }
  144. }