fixed files not downloading properly

This commit is contained in:
2026-09-07 11:21:39 -07:00
parent bb39db0272
commit ba8266bd86
6 changed files with 85 additions and 25 deletions

4
.gitignore vendored
View File

@@ -35,4 +35,6 @@ yarn-error.log*
*.tmp
*.temp
download-temp.zip
download-temp.zip
.env

View File

@@ -172,7 +172,6 @@ function validatePayload(zipPath) {
zip.extractAllTo(TEMP_EXTRACT_DIR, true);
const requiredFiles = [
'player/server.js',
'frontend/index.html'
];

48
main.js
View File

@@ -216,18 +216,20 @@ async function start() {
debugLog(`Is First Run: ${isFirstRun}, Local Version: ${localVersion}, Local SHA: ${localSha}`);
function findLocalZip() {
const searchRoots = [__dirname, process.cwd()];
const searchRoots = [__dirname, process.cwd(), path.join(__dirname, '../../..')];
for (const root of searchRoots) {
let cur = root;
for (let i = 0; i < 6; i++) {
const zp = path.join(cur, 'update-payload.zip');
if (fs.existsSync(zp)) {
const mp = path.join(cur, 'manifest.json');
return { zipPath: zp, manifestPath: fs.existsSync(mp) ? mp : null };
}
const parent = path.dirname(cur);
if (parent === cur) break;
cur = parent;
try {
const zp = path.join(cur, 'update-payload.zip');
if (fs.existsSync(zp)) {
const mp = path.join(cur, 'manifest.json');
return { zipPath: zp, manifestPath: fs.existsSync(mp) ? mp : null };
}
const parent = path.dirname(cur);
if (parent === cur) break;
cur = parent;
} catch (e) { }
}
}
return null;
@@ -309,12 +311,24 @@ async function start() {
debugLog("Update available. Prompting user...");
sendToTauri('status', { message: `New update available (${release.version}). Awaiting confirmation...` });
try {
if (process.platform === 'win32') {
require('child_process').spawnSync('powershell.exe', [
'-NoProfile', '-NonInteractive', '-Command',
`Get-NetTCPConnection -LocalPort 4891 -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force }`
], { stdio: 'ignore', windowsHide: true });
} else {
require('child_process').spawnSync('fuser', ['-k', '-9', `4891/tcp`], { stdio: 'ignore' });
}
} catch (e) { }
const tempApp = express();
let userDecision = null;
tempApp.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
res.header('Access-Control-Allow-Headers', '*');
res.header('Connection', 'close');
if (req.method === 'OPTIONS') return res.sendStatus(200);
next();
});
@@ -326,15 +340,27 @@ async function start() {
const tempServer = await new Promise((resolve) => {
const s = tempApp.listen(4891, '127.0.0.1', () => resolve(s));
s.on('error', (err) => {
debugLog(`Update server bind error: ${err.message}`);
resolve(null);
});
});
sendToTauri('update-available', { current: localVersion, latest: release.version });
let waitLoops = 0;
while (userDecision === null) {
if (!tempServer && waitLoops > 400) {
userDecision = false;
break;
}
waitLoops++;
await new Promise(r => setTimeout(r, 25));
}
await new Promise((resolve) => tempServer.close(resolve));
if (tempServer) {
tempServer.close();
}
if (userDecision) {
debugLog("User accepted update.");
@@ -374,7 +400,7 @@ async function start() {
sendToTauri('status', { message: 'Validating critical components...' });
if (!patcher.verifyExtraction()) {
throw new Error('No application files found. Ensure you run "npm run build:payload" to generate the local development payload.');
throw new Error('No application files found. Ensure you ran "npm run build:payload" and the extraction succeeded.');
}
sendToTauri('status', { message: 'Loading encrypted credentials...' });

View File

@@ -84,8 +84,25 @@ class Patcher {
}
extractZipPayload(zipPath) {
const AdmZip = require('adm-zip');
const zip = new AdmZip(zipPath);
const entries = zip.getEntries();
if (!entries || entries.length === 0) {
throw new Error('Downloaded archive is empty, invalid, or truncated.');
}
zip.extractAllTo(this.appDataPath, true);
const testPath = path.join(this.appDataPath, 'frontend', 'index.html');
if (!fs.existsSync(testPath)) {
const { execSync } = require('child_process');
if (process.platform === 'win32') {
execSync(`powershell.exe -NoProfile -NonInteractive -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${this.appDataPath}' -Force"`, { windowsHide: true });
} else {
execSync(`unzip -o "${zipPath}" -d "${this.appDataPath}"`);
}
}
}
verifyChecksum(zipPath, expectedSha256) {
@@ -99,8 +116,8 @@ class Patcher {
verifyExtraction() {
const requiredFiles = [
'player/server.js',
'frontend/index.html'
'frontend/index.html',
'player/server.js'
];
for (const file of requiredFiles) {
@@ -112,12 +129,16 @@ class Patcher {
if (stat.size === 0) {
return false;
}
const sampleSize = Math.min(stat.size, 4096);
const fd = fs.openSync(fullPath, 'r');
const buffer = Buffer.alloc(sampleSize);
fs.readSync(fd, buffer, 0, sampleSize, 0);
fs.closeSync(fd);
if (buffer.every(byte => byte === 0)) {
try {
const sampleSize = Math.min(stat.size, 4096);
const fd = fs.openSync(fullPath, 'r');
const buffer = Buffer.alloc(sampleSize);
fs.readSync(fd, buffer, 0, sampleSize, 0);
fs.closeSync(fd);
if (buffer.every(byte => byte === 0)) {
return false;
}
} catch (e) {
return false;
}
}

View File

@@ -831,7 +831,12 @@ fn main() {
let msg = match serde_json::from_str::<BackendMessage>(&line) {
Ok(m) => m,
Err(_) => continue,
Err(_) => {
if !line.trim().is_empty() {
debug_log(&format!("[NODE RAW] {}", line));
}
continue;
}
};
debug_log(&format!("[MAIN-DEBUG] Received event: {}", msg.event));

View File

@@ -136,7 +136,14 @@ class UpdateClient {
});
file.on('finish', () => {
file.close(resolve);
file.close(() => {
if (totalSize && downloadedSize < totalSize) {
fs.unlink(destPath, () => { });
reject(new Error(`Download truncated: Received ${downloadedSize} of ${totalSize} bytes. Connection dropped prematurely.`));
} else {
resolve();
}
});
});
file.on('error', (err) => {
@@ -150,10 +157,10 @@ class UpdateClient {
reject(err);
});
req.setTimeout(120000, () => {
req.setTimeout(900000, () => {
req.destroy();
fs.unlink(destPath, () => { });
reject(new Error('Download timeout'));
reject(new Error('Download timeout (15 minutes reached)'));
});
};