From b64ddafab9c811d55ab97feed15f39c963a37dab Mon Sep 17 00:00:00 2001 From: Nils Pukropp Date: Sat, 21 Feb 2026 04:38:43 +0100 Subject: [PATCH] fix: implement proactive session capture and harden Steam registry/VDF injection for cross-machine reliability --- frontend/dist-electron/main.js | 50 +++++++++++++++++++++++++++++++++- frontend/electron/main.ts | 47 +++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/frontend/dist-electron/main.js b/frontend/dist-electron/main.js index 65c236f..4b529a1 100644 --- a/frontend/dist-electron/main.js +++ b/frontend/dist-electron/main.js @@ -345,11 +345,20 @@ const handleLocalAccountsFound = async (localAccounts) => { const profile = await (0, steam_web_1.fetchProfileData)(local.steamId); const bans = await (0, steam_web_1.scrapeBanStatus)(profile.profileUrl); const localPath = await downloadAvatar(profile.steamId, profile.avatar); + // Wait and retry snagging the config (Steam takes time to write it) + let loginConfig = undefined; + for (let i = 0; i < 3; i++) { + await new Promise(r => setTimeout(r, 2000)); + loginConfig = steam_client_1.steamClient.extractAccountConfig(local.accountName); + if (loginConfig) + break; + } currentAccounts.push({ _id: Date.now().toString() + Math.random().toString().slice(2, 5), steamId: local.steamId, personaName: profile.personaName || local.accountName, loginName: local.accountName, autoCheckCooldown: false, avatar: profile.avatar, localAvatar: localPath, profileUrl: profile.profileUrl, + loginConfig, sessionUpdatedAt: loginConfig ? new Date().toISOString() : undefined, status: (bans.vacBanned || bans.gameBans > 0) ? 'banned' : 'none', vacBanned: bans.vacBanned, gameBans: bans.gameBans, lastBanCheck: new Date().toISOString() }); @@ -579,7 +588,46 @@ electron_1.ipcMain.handle('admin-delete-user', async (event, userId) => { initBa electron_1.ipcMain.handle('admin-get-accounts', async () => { initBackend(); return backend ? await backend.getAdminAccounts() : []; }); electron_1.ipcMain.handle('admin-remove-account', async (event, steamId) => { initBackend(); if (backend) await backend.forceRemoveAccount(steamId); return true; }); -electron_1.ipcMain.handle('switch-account', async (event, loginName) => await handleSwitchAccount(loginName)); +electron_1.ipcMain.handle('switch-account', async (event, loginName) => { + if (!loginName) + return false; + try { + // PROACTIVE SYNC: Try to snag the freshest token before we kill Steam + const accounts = store.get('accounts'); + const account = accounts.find(a => a.loginName === loginName); + if (account && !account._id.startsWith('shared_')) { + const freshConfig = steam_client_1.steamClient.extractAccountConfig(loginName); + if (freshConfig) { + account.loginConfig = freshConfig; + account.sessionUpdatedAt = new Date().toISOString(); + if (backend) + await backend.shareAccount(account); + store.set('accounts', accounts); + } + } + await killSteam(); + if (process.platform === 'win32') { + const regBase = 'reg add "HKCU\\Software\\Valve\\Steam"'; + const commands = [ + `${regBase} /v AutoLoginUser /t REG_SZ /d "${loginName}" /f`, + `${regBase} /v RememberPassword /t REG_DWORD /d 1 /f`, + `${regBase} /v AlreadyLoggedIn /t REG_DWORD /d 1 /f`, + `${regBase} /v WantsOfflineMode /t REG_DWORD /d 0 /f` + ]; + await new Promise((res, rej) => (0, child_process_1.exec)(commands.join(' && '), (e) => e ? rej(e) : res())); + if (account && account.loginConfig) + steam_client_1.steamClient.injectAccountConfig(loginName, account.loginConfig); + } + else if (process.platform === 'linux') { + await steam_client_1.steamClient.setAutoLoginUser(loginName, account?.loginConfig, account?.steamId); + } + startSteam(); + return true; + } + catch (e) { + return false; + } +}); electron_1.ipcMain.handle('open-external', (event, url) => electron_1.shell.openExternal(url)); electron_1.ipcMain.handle('open-steam-app-login', async () => { await killSteam(); diff --git a/frontend/electron/main.ts b/frontend/electron/main.ts index b9e5072..8d3335c 100644 --- a/frontend/electron/main.ts +++ b/frontend/electron/main.ts @@ -356,11 +356,21 @@ const handleLocalAccountsFound = async (localAccounts: LocalSteamAccount[]) => { const profile = await fetchProfileData(local.steamId); const bans = await scrapeBanStatus(profile.profileUrl); const localPath = await downloadAvatar(profile.steamId, profile.avatar); + + // Wait and retry snagging the config (Steam takes time to write it) + let loginConfig = undefined; + for (let i = 0; i < 3; i++) { + await new Promise(r => setTimeout(r, 2000)); + loginConfig = steamClient.extractAccountConfig(local.accountName); + if (loginConfig) break; + } + currentAccounts.push({ _id: Date.now().toString() + Math.random().toString().slice(2, 5), steamId: local.steamId, personaName: profile.personaName || local.accountName, loginName: local.accountName, autoCheckCooldown: false, avatar: profile.avatar, localAvatar: localPath, profileUrl: profile.profileUrl, + loginConfig, sessionUpdatedAt: loginConfig ? new Date().toISOString() : undefined, status: (bans.vacBanned || bans.gameBans > 0) ? 'banned' : 'none', vacBanned: bans.vacBanned, gameBans: bans.gameBans, lastBanCheck: new Date().toISOString() }); @@ -561,7 +571,42 @@ ipcMain.handle('admin-delete-user', async (event, userId: string) => { initBacke ipcMain.handle('admin-get-accounts', async () => { initBackend(); return backend ? await backend.getAdminAccounts() : []; }); ipcMain.handle('admin-remove-account', async (event, steamId: string) => { initBackend(); if (backend) await backend.forceRemoveAccount(steamId); return true; }); -ipcMain.handle('switch-account', async (event, loginName: string) => await handleSwitchAccount(loginName)); +ipcMain.handle('switch-account', async (event, loginName: string) => { + if (!loginName) return false; + try { + // PROACTIVE SYNC: Try to snag the freshest token before we kill Steam + const accounts = store.get('accounts') as Account[]; + const account = accounts.find(a => a.loginName === loginName); + if (account && !account._id.startsWith('shared_')) { + const freshConfig = steamClient.extractAccountConfig(loginName); + if (freshConfig) { + account.loginConfig = freshConfig; + account.sessionUpdatedAt = new Date().toISOString(); + if (backend) await backend.shareAccount(account); + store.set('accounts', accounts); + } + } + + await killSteam(); + + if (process.platform === 'win32') { + const regBase = 'reg add "HKCU\\Software\\Valve\\Steam"'; + const commands = [ + `${regBase} /v AutoLoginUser /t REG_SZ /d "${loginName}" /f`, + `${regBase} /v RememberPassword /t REG_DWORD /d 1 /f`, + `${regBase} /v AlreadyLoggedIn /t REG_DWORD /d 1 /f`, + `${regBase} /v WantsOfflineMode /t REG_DWORD /d 0 /f` + ]; + await new Promise((res, rej) => exec(commands.join(' && '), (e) => e ? rej(e) : res())); + if (account && account.loginConfig) steamClient.injectAccountConfig(loginName, account.loginConfig); + } else if (process.platform === 'linux') { + await steamClient.setAutoLoginUser(loginName, account?.loginConfig, account?.steamId); + } + startSteam(); + return true; + } catch (e) { return false; } +}); + ipcMain.handle('open-external', (event, url: string) => shell.openExternal(url)); ipcMain.handle('open-steam-app-login', async () => {