From 019147a6cea3e50accbd21d35adf24861c3944a6 Mon Sep 17 00:00:00 2001 From: legop3 Date: Tue, 28 Apr 2026 20:12:39 -0400 Subject: [PATCH] stupid --- rulesdocs/refector_rules_and_tracking.md | 2 + server/src/helpers/dataPaths.js | 41 +++++++++++++++++++ .../src/services/adminReasonService/index.js | 6 +-- .../src/services/audioLevelsService/index.js | 6 +-- server/src/services/buttonBoxService/index.js | 6 +-- .../services/communityGoalService/index.js | 6 +-- .../src/services/discordGuildStore/index.js | 6 +-- .../services/llmCommentaryService/index.js | 2 +- server/src/services/replayEngineV2/index.js | 3 +- .../src/services/verificationService/index.js | 5 +-- 10 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 server/src/helpers/dataPaths.js diff --git a/rulesdocs/refector_rules_and_tracking.md b/rulesdocs/refector_rules_and_tracking.md index 9cecc12c..41341838 100644 --- a/rulesdocs/refector_rules_and_tracking.md +++ b/rulesdocs/refector_rules_and_tracking.md @@ -66,6 +66,8 @@ - Split `server/src/services/turnService/index.js` by extracting constants, shared state helpers, and side-effect action helpers into `turnService/constants.js`, `turnService/state.js`, and `turnService/actions.js`. - Split `server/src/services/sessionService/index.js` by extracting config/timing constants, sync-throttle state storage, and visibility filter helpers into `sessionService/constants.js`, `sessionService/state.js`, and `sessionService/filters.js`. - Began splitting `server/src/services/roverManager/index.js` by extracting immutable constants and shared state containers into `roverManager/constants.js` and `roverManager/state.js`. +- Hotfix: corrected `llmCommentaryService` prompt file path to `server/prompts/commentary_system.txt` after service folder move. +- Hotfix: added `server/src/helpers/dataPaths.js` and rewired data-backed services to resolve canonical + legacy data-file locations safely after folderization (`adminReason`, `audioLevels`, `buttonBox`, `communityGoal`, `discordGuildStore`, `verification`, `replayEngineV2`). ## WebUI frontend ### BIGGEST OFFENDERS diff --git a/server/src/helpers/dataPaths.js b/server/src/helpers/dataPaths.js new file mode 100644 index 00000000..0dc60afb --- /dev/null +++ b/server/src/helpers/dataPaths.js @@ -0,0 +1,41 @@ +// data Paths helper +// Purpose: Resolves persistent data paths across refactors so services keep loading prior state files. +// Scope: Preserves runtime behavior by preferring configured/canonical paths while supporting legacy locations. +const fs = require('fs'); +const path = require('path'); + +const CANONICAL_DATA_DIR = path.resolve(__dirname, '..', '..', 'data'); +const LEGACY_DATA_DIR = path.resolve(__dirname, '..', 'data'); + +function pathExists(target) { + try { + fs.accessSync(target, fs.constants.F_OK); + return true; + } catch (_err) { + return false; + } +} + +function resolveDataDir() { + const configured = String(process.env.SERVER_DATA_DIR || '').trim(); + if (configured) return path.resolve(configured); + if (pathExists(CANONICAL_DATA_DIR)) return CANONICAL_DATA_DIR; + if (pathExists(LEGACY_DATA_DIR)) return LEGACY_DATA_DIR; + return CANONICAL_DATA_DIR; +} + +function resolveDataPath(fileName) { + const configured = String(process.env.SERVER_DATA_DIR || '').trim(); + if (configured) return path.join(path.resolve(configured), fileName); + + const canonicalPath = path.join(CANONICAL_DATA_DIR, fileName); + const legacyPath = path.join(LEGACY_DATA_DIR, fileName); + if (pathExists(canonicalPath)) return canonicalPath; + if (pathExists(legacyPath)) return legacyPath; + return canonicalPath; +} + +module.exports = { + resolveDataDir, + resolveDataPath, +}; diff --git a/server/src/services/adminReasonService/index.js b/server/src/services/adminReasonService/index.js index 1d609727..546a48dc 100644 --- a/server/src/services/adminReasonService/index.js +++ b/server/src/services/adminReasonService/index.js @@ -2,14 +2,14 @@ // Purpose: Defines the admin Reason Service module and the helpers/state used by this service unit. // Scope: Keeps runtime behavior unchanged while isolating responsibilities into a clear module boundary. const fs = require('fs'); -const path = require('path'); const io = require('../../globals/io'); const logger = require('../../globals/logger').child('adminReasonService'); const { isAdmin } = require('../roleService'); const { publishEvent } = require('../eventBus'); +const { resolveDataDir, resolveDataPath } = require('../../helpers/dataPaths'); -const DATA_DIR = path.join(__dirname, '..', '..', '..', 'data'); -const STORE_PATH = path.join(DATA_DIR, 'admin-reason.json'); +const DATA_DIR = resolveDataDir(); +const STORE_PATH = resolveDataPath('admin-reason.json'); const MAX_REASON_LENGTH = 240; let cache = null; diff --git a/server/src/services/audioLevelsService/index.js b/server/src/services/audioLevelsService/index.js index 98b7427b..3308b580 100644 --- a/server/src/services/audioLevelsService/index.js +++ b/server/src/services/audioLevelsService/index.js @@ -2,18 +2,18 @@ // Purpose: Defines the audio Levels Service module and the helpers/state used by this service unit. // Scope: Keeps runtime behavior unchanged while isolating responsibilities into a clear module boundary. const fs = require('fs'); -const path = require('path'); const EventEmitter = require('events'); const io = require('../../globals/io'); const logger = require('../../globals/logger').child('audioLevelsService'); const { loadConfig } = require('../../helpers/configLoader'); +const { resolveDataDir, resolveDataPath } = require('../../helpers/dataPaths'); const { isAdmin } = require('../roleService'); const roverManager = require('../roverManager'); const { issueCommand } = require('../commandService'); const audioLevelsEvents = new EventEmitter(); -const DATA_DIR = path.join(__dirname, '..', '..', '..', 'data'); -const STORE_PATH = path.join(DATA_DIR, 'audio-levels.json'); +const DATA_DIR = resolveDataDir(); +const STORE_PATH = resolveDataPath('audio-levels.json'); const config = loadConfig(); const configuredDefaults = config.audioLevels || {}; diff --git a/server/src/services/buttonBoxService/index.js b/server/src/services/buttonBoxService/index.js index f7faab59..cd500613 100644 --- a/server/src/services/buttonBoxService/index.js +++ b/server/src/services/buttonBoxService/index.js @@ -2,11 +2,11 @@ // Purpose: Defines the button Box Service module and the helpers/state used by this service unit. // Scope: Keeps runtime behavior unchanged while isolating responsibilities into a clear module boundary. const fs = require('fs'); -const path = require('path'); const express = require('express'); const { app } = require('../../globals/http'); const io = require('../../globals/io'); const logger = require('../../globals/logger').child('buttonBoxService'); +const { resolveDataDir, resolveDataPath } = require('../../helpers/dataPaths'); const { publishEvent } = require('../eventBus'); const { getRewardById, listRewards } = require('../../rewards'); const roverManager = require('../roverManager'); @@ -23,8 +23,8 @@ const { } = require('../homeAssistantService'); const { getRequestIp, isLocalNetwork, normalizeIp } = require('../../helpers/ipResolver'); -const DATA_DIR = path.join(__dirname, '..', '..', '..', 'data'); -const STORE_PATH = path.join(DATA_DIR, 'buttonbox-state.json'); +const DATA_DIR = resolveDataDir(); +const STORE_PATH = resolveDataPath('buttonbox-state.json'); const BUTTON_COUNT = 4; const STORE_VERSION = 1; diff --git a/server/src/services/communityGoalService/index.js b/server/src/services/communityGoalService/index.js index b609ff4a..9f32f33d 100644 --- a/server/src/services/communityGoalService/index.js +++ b/server/src/services/communityGoalService/index.js @@ -2,14 +2,14 @@ // Purpose: Defines the community Goal Service module and the helpers/state used by this service unit. // Scope: Keeps runtime behavior unchanged while isolating responsibilities into a clear module boundary. const fs = require('fs'); -const path = require('path'); const io = require('../../globals/io'); const logger = require('../../globals/logger').child('communityGoalService'); const { isAdmin } = require('../roleService'); const { publishEvent } = require('../eventBus'); +const { resolveDataDir, resolveDataPath } = require('../../helpers/dataPaths'); -const DATA_DIR = path.join(__dirname, '..', '..', '..', 'data'); -const STORE_PATH = path.join(DATA_DIR, 'community-goal.json'); +const DATA_DIR = resolveDataDir(); +const STORE_PATH = resolveDataPath('community-goal.json'); const MAX_GOAL_LENGTH = 240; let cache = null; diff --git a/server/src/services/discordGuildStore/index.js b/server/src/services/discordGuildStore/index.js index 8768be5a..2c30a860 100644 --- a/server/src/services/discordGuildStore/index.js +++ b/server/src/services/discordGuildStore/index.js @@ -2,11 +2,11 @@ // Purpose: Defines the discord Guild Store module and the helpers/state used by this service unit. // Scope: Keeps runtime behavior unchanged while isolating responsibilities into a clear module boundary. const fs = require('fs'); -const path = require('path'); const logger = require('../../globals/logger').child('discordGuildStore'); +const { resolveDataDir, resolveDataPath } = require('../../helpers/dataPaths'); -const DATA_DIR = path.join(__dirname, '..', '..', '..', 'data'); -const STORE_PATH = path.join(DATA_DIR, 'discord-guilds.json'); +const DATA_DIR = resolveDataDir(); +const STORE_PATH = resolveDataPath('discord-guilds.json'); const VALID_MODES = new Set(['global', 'private']); let cache = null; diff --git a/server/src/services/llmCommentaryService/index.js b/server/src/services/llmCommentaryService/index.js index 81b596c4..ea5fa128 100644 --- a/server/src/services/llmCommentaryService/index.js +++ b/server/src/services/llmCommentaryService/index.js @@ -13,7 +13,7 @@ const { getActiveDrivers } = require('../turnService'); const { getNickname } = require('../nicknameService'); const { getRecentMessages, sendSystemMessage } = require('../chatService'); -const PROMPT_PATH = path.join(__dirname, '..', '..', 'prompts', 'commentary_system.txt'); +const PROMPT_PATH = path.join(__dirname, '..', '..', '..', 'prompts', 'commentary_system.txt'); const DEFAULT_FREQUENCY_MS = 0; const MIN_FREQUENCY_MS = 0; const JITTER_MS = 0; diff --git a/server/src/services/replayEngineV2/index.js b/server/src/services/replayEngineV2/index.js index a309369e..8de0cba9 100644 --- a/server/src/services/replayEngineV2/index.js +++ b/server/src/services/replayEngineV2/index.js @@ -15,12 +15,13 @@ const io = require('../../globals/io'); const { getActiveDrivers } = require('../turnService'); const { getNickname } = require('../nicknameService'); const { getRecentMessages } = require('../chatService'); +const { resolveDataDir } = require('../../helpers/dataPaths'); const sharp = require('sharp'); const execFileAsync = promisify(execFile); const FFMPEG_BIN = process.env.FFMPEG_BIN || 'ffmpeg'; -const SEGMENT_ROOT = path.resolve(__dirname, '..', '..', '..', 'data', 'replay-segments'); +const SEGMENT_ROOT = path.join(resolveDataDir(), 'replay-segments'); const SEGMENT_SECONDS = Math.max(1, Number.parseInt(process.env.REPLAY_SEGMENT_SECONDS || '1', 10)); const BUFFER_SECONDS = Math.max(20, Number.parseInt(process.env.REPLAY_BUFFER_SECONDS || '45', 10)); const CLEANUP_INTERVAL_MS = 10_000; diff --git a/server/src/services/verificationService/index.js b/server/src/services/verificationService/index.js index b6b4e4d0..3d409278 100644 --- a/server/src/services/verificationService/index.js +++ b/server/src/services/verificationService/index.js @@ -1,12 +1,12 @@ // verification Service // Purpose: Defines the verification Service module and the helpers/state used by this service unit. // Scope: Keeps runtime behavior unchanged while isolating responsibilities into a clear module boundary. -const path = require('path'); const crypto = require('crypto'); const net = require('net'); const EventEmitter = require('events'); const io = require('../../globals/io'); const logger = require('../../globals/logger').child('verificationService'); +const { resolveDataPath } = require('../../helpers/dataPaths'); const { publishEvent } = require('../eventBus'); const { normalizeIp } = require('../../helpers/ipResolver'); const { getNickname, setNickname } = require('../nicknameService'); @@ -20,8 +20,7 @@ const { createJsonStore, } = require('../identityService'); -const DATA_DIR = path.join(__dirname, '..', '..', '..', 'data'); -const STORE_PATH = path.join(DATA_DIR, 'verified-users.json'); +const STORE_PATH = resolveDataPath('verified-users.json'); const verificationEvents = new EventEmitter();