Release v1.4.30 with startup and UI race-condition fixes
Build and Release / build (push) Has been cancelled
Build and Release / build (push) Has been cancelled
This commit is contained in:
+1
-1
@@ -5,7 +5,7 @@ import { RealDebridClient, UnrestrictedLink } from "./realdebrid";
|
||||
import { compactErrorText, filenameFromUrl, looksLikeOpaqueFilename, sleep } from "./utils";
|
||||
|
||||
const API_TIMEOUT_MS = 30000;
|
||||
const DEBRID_USER_AGENT = "RD-Node-Downloader/1.4.29";
|
||||
const DEBRID_USER_AGENT = "RD-Node-Downloader/1.4.30";
|
||||
const RAPIDGATOR_SCAN_MAX_BYTES = 512 * 1024;
|
||||
|
||||
const BEST_DEBRID_API_BASE = "https://bestdebrid.com/api/v1";
|
||||
|
||||
+30
-7
@@ -343,6 +343,13 @@ function isNoExtractorError(errorText: string): boolean {
|
||||
return String(errorText || "").toLowerCase().includes("nicht gefunden");
|
||||
}
|
||||
|
||||
function isUnsupportedArchiveFormatError(errorText: string): boolean {
|
||||
const text = String(errorText || "").toLowerCase();
|
||||
return text.includes("kein rar-archiv")
|
||||
|| text.includes("not a rar archive")
|
||||
|| text.includes("is not a rar archive");
|
||||
}
|
||||
|
||||
function isUnsupportedExtractorSwitchError(errorText: string): boolean {
|
||||
const text = String(errorText || "").toLowerCase();
|
||||
return text.includes("unknown switch")
|
||||
@@ -705,17 +712,26 @@ async function runExternalExtract(
|
||||
}
|
||||
|
||||
function isZipSafetyGuardError(error: unknown): boolean {
|
||||
const text = String(error || "").toLowerCase();
|
||||
return text.includes("path traversal")
|
||||
|| text.includes("zip-eintrag verdächtig groß")
|
||||
|| text.includes("zip-eintrag verdaechtig gross");
|
||||
}
|
||||
|
||||
function isZipInternalLimitError(error: unknown): boolean {
|
||||
const text = String(error || "").toLowerCase();
|
||||
return text.includes("zip-eintrag zu groß")
|
||||
|| text.includes("zip-eintrag komprimiert zu groß")
|
||||
|| text.includes("zip-eintrag ohne sichere groessenangabe")
|
||||
|| text.includes("path traversal");
|
||||
|| text.includes("zip-eintrag ohne sichere groessenangabe");
|
||||
}
|
||||
|
||||
function shouldFallbackToExternalZip(error: unknown): boolean {
|
||||
if (isZipSafetyGuardError(error)) {
|
||||
return false;
|
||||
}
|
||||
if (isZipInternalLimitError(error)) {
|
||||
return true;
|
||||
}
|
||||
const text = String(error || "").toLowerCase();
|
||||
if (text.includes("aborted:extract") || text.includes("extract_aborted")) {
|
||||
return false;
|
||||
@@ -1190,11 +1206,18 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
||||
if (!shouldFallbackToExternalZip(error)) {
|
||||
throw error;
|
||||
}
|
||||
const usedPassword = await runExternalExtract(archivePath, options.targetDir, options.conflictMode, passwordCandidates, (value) => {
|
||||
archivePercent = Math.max(archivePercent, value);
|
||||
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
||||
}, options.signal);
|
||||
passwordCandidates = prioritizePassword(passwordCandidates, usedPassword);
|
||||
try {
|
||||
const usedPassword = await runExternalExtract(archivePath, options.targetDir, options.conflictMode, passwordCandidates, (value) => {
|
||||
archivePercent = Math.max(archivePercent, value);
|
||||
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
||||
}, options.signal);
|
||||
passwordCandidates = prioritizePassword(passwordCandidates, usedPassword);
|
||||
} catch (externalError) {
|
||||
if (isNoExtractorError(String(externalError)) || isUnsupportedArchiveFormatError(String(externalError))) {
|
||||
throw error;
|
||||
}
|
||||
throw externalError;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
+2
-1
@@ -34,7 +34,8 @@ function validateStringArray(value: unknown, name: string): string[] {
|
||||
/* ── Single Instance Lock ───────────────────────────────────────── */
|
||||
const gotLock = app.requestSingleInstanceLock();
|
||||
if (!gotLock) {
|
||||
app.quit();
|
||||
app.exit(0);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
/* ── Unhandled error protection ─────────────────────────────────── */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { API_BASE_URL, REQUEST_RETRIES } from "./constants";
|
||||
import { compactErrorText, sleep } from "./utils";
|
||||
|
||||
const DEBRID_USER_AGENT = "RD-Node-Downloader/1.4.29";
|
||||
const DEBRID_USER_AGENT = "RD-Node-Downloader/1.4.30";
|
||||
|
||||
export interface UnrestrictedLink {
|
||||
fileName: string;
|
||||
|
||||
@@ -59,9 +59,6 @@ function normalizeBandwidthSchedules(raw: unknown): BandwidthScheduleEntry[] {
|
||||
|
||||
function normalizeAbsoluteDir(value: unknown, fallback: string): string {
|
||||
const text = asText(value);
|
||||
if (/^\/[\s\S]+/.test(text)) {
|
||||
return text.replace(/\\/g, "/");
|
||||
}
|
||||
if (!text || !path.isAbsolute(text)) {
|
||||
return path.resolve(fallback);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user