fix: clone sources blocked by content-type check and TLS fingerprint
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s

- fetchSourceFurnidata now parses JSON regardless of content-type,
  so GitHub raw mirrors (Kyzegs, sphynxkitten) that serve JSON as
  text/plain work again instead of forcing a FlareSolverr round-trip.
- Add curl subprocess fallback (curl-fetch.ts) for CDNs that block
  Node's fetch by TLS fingerprint (Leet.city) — used for furnidata,
  nitro bundle and icon downloads before giving up.
- Merge verified default clone source presets with stored user sources
  so the admin always offers many working sources.
This commit is contained in:
openhands committed 2026-08-19 19:39:32 +02:00
1 parent 7911a25ced
commit 121dda7249
4 files changed
+173 -18

No files matched your search

+11 -2
View File
@@ -160,12 +160,21 @@ export const DEFAULT_NITRO_SOURCES: CloneSource[] = DEFAULT_SOURCES.filter(
export async function listSources(): Promise<CloneSource[]> {
const raw = (await siteSettings.get(KEY, "[]")) ?? "[]";
let stored: CloneSource[] = [];
try {
const arr = JSON.parse(raw);
return Array.isArray(arr) && arr.length > 0 ? arr : DEFAULT_SOURCES;
if (Array.isArray(arr)) stored = arr;
} catch {
return DEFAULT_SOURCES;
// fall through to defaults-only
}
// Merge the verified default presets with any user-added/edited sources so
// the admin always has many sources to pick from. User entries win on id.
const merged = new Map<string, CloneSource>();
for (const src of DEFAULT_SOURCES) merged.set(src.id, src);
for (const src of stored) {
if (src.id && src.furnidataUrl) merged.set(src.id, src);
}
return Array.from(merged.values());
}
export async function upsertSource(