config.service.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. // Ensure database and tables exist
  30. const db = new Database(this.unifiedDbPath);
  31. db.exec(`
  32. CREATE TABLE IF NOT EXISTS settings (
  33. key TEXT PRIMARY KEY,
  34. value TEXT
  35. );
  36. `);
  37. db.close();
  38. }
  39. getSettings(key?: string, defaultValue?: any): any {
  40. try {
  41. const db = new Database(this.unifiedDbPath, { readonly: true });
  42. if (key) {
  43. const row = db
  44. .prepare('SELECT value FROM settings WHERE key = ?')
  45. .get(key) as { value?: string } | undefined;
  46. db.close();
  47. return row && row.value !== undefined
  48. ? JSON.parse(row.value)
  49. : defaultValue;
  50. } else {
  51. const rows = db
  52. .prepare('SELECT key, value FROM settings')
  53. .all() as Array<{ key: string; value: string }>;
  54. db.close();
  55. const settings: Record<string, any> = {};
  56. for (const row of rows) {
  57. settings[row.key] = JSON.parse(row.value);
  58. }
  59. return settings;
  60. }
  61. } catch (e) {
  62. if (key) return defaultValue;
  63. return {};
  64. }
  65. }
  66. getConfigFile(name: string): any {
  67. // For datasources: name = kids.json, pr0n.json, tvshows.json
  68. const base = name.replace(/\.json$/, '');
  69. try {
  70. const db = new Database(this.unifiedDbPath, { readonly: true });
  71. const row = db
  72. .prepare('SELECT data FROM datasets WHERE name = ?')
  73. .get(base) as { data?: string } | undefined;
  74. db.close();
  75. return row && row.data !== undefined ? JSON.parse(row.data) : null;
  76. } catch (e) {
  77. return null;
  78. }
  79. }
  80. listConfigs(): string[] {
  81. // Return all dataset names as .json (regardless of enabled)
  82. try {
  83. const db = new Database(this.unifiedDbPath, { readonly: true });
  84. const rows = db.prepare('SELECT name FROM datasets').all() as Array<{
  85. name: string;
  86. }>;
  87. db.close();
  88. // Debug: log found rows
  89. if (rows.length === 0) {
  90. console.warn('No configs found in datasets table');
  91. }
  92. return rows.map((row) => row.name + '.json');
  93. } catch (e) {
  94. console.error('Error in listConfigs:', e);
  95. return [];
  96. }
  97. }
  98. setSettings(settings: Record<string, any>): boolean {
  99. try {
  100. const db = new Database(this.unifiedDbPath);
  101. const insert = db.prepare(
  102. 'INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)',
  103. );
  104. for (const [key, value] of Object.entries(settings)) {
  105. // If value is already a JSON string, save it as-is
  106. // Otherwise, stringify it
  107. let valueToSave: string;
  108. if (typeof value === 'string') {
  109. // Check if it's already valid JSON
  110. try {
  111. JSON.parse(value);
  112. valueToSave = value;
  113. } catch {
  114. // Not valid JSON, stringify it
  115. valueToSave = JSON.stringify(value);
  116. }
  117. } else {
  118. // It's an object, stringify it
  119. valueToSave = JSON.stringify(value);
  120. }
  121. insert.run(key, valueToSave);
  122. }
  123. db.close();
  124. return true;
  125. } catch (e) {
  126. console.error('Error setting settings:', e);
  127. return false;
  128. }
  129. }
  130. deleteSetting(key: string): boolean {
  131. try {
  132. const db = new Database(this.unifiedDbPath);
  133. const result = db.prepare('DELETE FROM settings WHERE key = ?').run(key);
  134. db.close();
  135. return result.changes > 0;
  136. } catch (e) {
  137. console.error('Error deleting setting:', e);
  138. return false;
  139. }
  140. }
  141. }