diff --git a/lib/log-mode.js b/lib/log-mode.js index 2bb7987..20b04ea 100644 --- a/lib/log-mode.js +++ b/lib/log-mode.js @@ -1,7 +1,7 @@ // Log-file mode resolution for fileuploader.log: // - "single" → one file: fileuploader.log // - "daily" → per-day: fileuploader-YYYY-MM-DD.log -// - "session" → per-launch: fileuploader-session-YYYY-MM-DD_HH-MM-SS-.log +// - "session" → per-launch: DD-MM-YYYY-mdu-session-HH-MM.log // // Pure functions only — no fs, no Date.now() at call time — so they unit-test // cleanly and the main.js call sites pass in `new Date()` + the session stamp. @@ -38,13 +38,10 @@ return `${date.getFullYear()}-${_two(date.getMonth() + 1)}-${_two(date.getDate())}`; } - function formatSessionStamp(date, pid) { - const d = `${date.getFullYear()}-${_two(date.getMonth() + 1)}-${_two(date.getDate())}`; - const t = `${_two(date.getHours())}-${_two(date.getMinutes())}-${_two(date.getSeconds())}`; - // PID disambiguates a same-second close→reopen — a human can't but two - // automated runs might. Cheap belt to a suspenders-not-required problem. - const pidStr = pid !== undefined && pid !== null ? `-${pid}` : ''; - return `${d}_${t}${pidStr}`; + function formatSessionStamp(date) { + const d = `${_two(date.getDate())}-${_two(date.getMonth() + 1)}-${date.getFullYear()}`; + const t = `${_two(date.getHours())}-${_two(date.getMinutes())}`; + return `${d}-mdu-session-${t}`; } /** @@ -67,9 +64,10 @@ const date = a.date instanceof Date ? a.date : new Date(); return `${base}-${formatDateStamp(date)}${ext}`; } - // session + // session — the stamp is the full app-defined stem (DD-MM-YYYY-mdu-session-HH-MM), + // independent of baseName. const sid = a.sessionId && String(a.sessionId).trim(); - if (sid) return `${base}-session-${sid}${ext}`; + if (sid) return `${sid}${ext}`; // Defensive: if a session-id wasn't passed, fall back to single rather // than emit a malformed name. main.js always supplies one. return `${base}${ext}`; @@ -85,6 +83,9 @@ */ function stripModeStampFromFileName(fileName) { if (!fileName || typeof fileName !== 'string') return fileName; + const newSessionRe = /^\d{2}-\d{2}-\d{4}-mdu-session-\d{2}-\d{2}(\.[^.]+)?$/; + const mNew = fileName.match(newSessionRe); + if (mNew) return `fileuploader${mNew[1] || ''}`; // Order matters: session first (longer, more specific) before daily. // Both regexes are anchored to $ with no nested/ambiguous quantifiers, so // matching is linear — the eslint security warning is precautionary. diff --git a/package.json b/package.json index b05d620..b025ae5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "multi-hoster-uploader", - "version": "3.3.106", + "version": "3.3.107", "description": "Upload files to doodstream, voe, vidmoly, byse simultaneously", "main": "main.js", "scripts": { diff --git a/tasks/todo.md b/tasks/todo.md index c503f8a..2ac109d 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -1,3 +1,18 @@ +# v3.3.107 — session log filename template → DD-MM-YYYY-mdu-session-HH-MM + +User: change the session log filename from fileuploader-session-YYYY-MM-DD_HH-MM-SS-.log to +DD-MM-YYYY-mdu-session-HH-MM.log (hour-minute, no seconds/pid). lib/log-mode.js: +- formatSessionStamp(date) now returns `${DD}-${MM}-${YYYY}-mdu-session-${HH}-${MM}` (pid arg dropped; main.js + still passes process.pid, harmlessly ignored). +- resolveLogFileName session branch returns `${sid}${ext}` (the stamp is the full app-defined stem, baseName + ignored — single/daily still use baseName 'fileuploader'). +- stripModeStampFromFileName recognizes the new format (^DD-MM-YYYY-mdu-session-HH-MM(.ext)$) and resets to the + default 'fileuploader' base (the new format embeds no base); the old daily + old-session strip regexes stay + for backward-compat with any persisted old paths. The compounding round-trip stays idempotent. +Tests updated (formatSessionStamp, resolveLogFileName session, strip new-format, idempotency). 410 pass. + +--- + # v3.3.106 — intermittent white-screen on startup (RDP/VM GPU) + export filename Two asks. (A) White screen: user sometimes gets a PURE-WHITE window on start (no error banner, NOT even the diff --git a/tests/log-mode.test.js b/tests/log-mode.test.js index 86cf29f..1eb77c1 100644 --- a/tests/log-mode.test.js +++ b/tests/log-mode.test.js @@ -57,13 +57,18 @@ test('resolveLogFileName: daily mode → fileuploader-YYYY-MM-DD.log', () => { ); }); -test('resolveLogFileName: session mode → fileuploader-session-.log', () => { +test('resolveLogFileName: session mode → .log (baseName ignored)', () => { assert.equal( - resolveLogFileName({ baseName: 'fileuploader', ext: '.log', mode: 'session', sessionId: '2026-05-28_22-44-52-12345' }), - 'fileuploader-session-2026-05-28_22-44-52-12345.log' + resolveLogFileName({ baseName: 'fileuploader', ext: '.log', mode: 'session', sessionId: '26-05-2026-mdu-session-22-44' }), + '26-05-2026-mdu-session-22-44.log' ); }); +test('formatSessionStamp: DD-MM-YYYY-mdu-session-HH-MM', () => { + const { formatSessionStamp } = require('../lib/log-mode'); + assert.equal(formatSessionStamp(new Date(2026, 5, 26, 6, 2, 36)), '26-06-2026-mdu-session-06-02'); +}); + test('resolveLogFileName: session mode with missing sessionId falls back to single (never emits malformed name)', () => { assert.equal( resolveLogFileName({ baseName: 'fileuploader', ext: '.log', mode: 'session' }), @@ -102,12 +107,16 @@ test('stripModeStampFromFileName: strips a session-stamp suffix (with and withou ); }); +test('stripModeStampFromFileName: new DD-MM-YYYY-mdu-session-HH-MM resets to the default base', () => { + assert.equal(stripModeStampFromFileName('26-06-2026-mdu-session-06-02.log'), 'fileuploader.log'); +}); + test('regression: resolveLogFileName(stripModeStampFromFileName(...)) is idempotent — persisting then re-resolving never compounds stamps', () => { // This is the exact bug shape: persist the resolved path, then on next call // re-resolve from the saved base — must produce the same file, not a doubled // session-stamped one. The fix is the strip; this test guards against // regressing _persistFallbackLogPath into the 3.3.35 bug. - const sessionId = '2026-06-03_18-16-20-8132'; + const sessionId = '03-06-2026-mdu-session-18-16'; const dailyDate = new Date(2026, 5, 3); for (const mode of ['daily', 'session']) { const date = mode === 'daily' ? dailyDate : new Date(); @@ -129,12 +138,7 @@ test('formatDateStamp: zero-pads month and day', () => { assert.equal(formatDateStamp(new Date(2026, 11, 31)), '2026-12-31'); }); -test('formatSessionStamp: produces YYYY-MM-DD_HH-MM-SS-pid', () => { - const d = new Date(2026, 4, 28, 7, 9, 5); - assert.equal(formatSessionStamp(d, 12345), '2026-05-28_07-09-05-12345'); -}); - -test('formatSessionStamp: omits the pid suffix when none provided', () => { - const d = new Date(2026, 4, 28, 22, 44, 52); - assert.equal(formatSessionStamp(d), '2026-05-28_22-44-52'); +test('formatSessionStamp: DD-MM-YYYY-mdu-session-HH-MM (no seconds/pid)', () => { + assert.equal(formatSessionStamp(new Date(2026, 4, 28, 7, 9, 5)), '28-05-2026-mdu-session-07-09'); + assert.equal(formatSessionStamp(new Date(2026, 4, 28, 22, 44, 52)), '28-05-2026-mdu-session-22-44'); });