mirror of
https://github.com/direct-img/direct-img.link.git
synced 2026-10-29 15:34:51 +00:00
A third of queries (by query hash) search Firecrawl first and the rest Brave, so Firecrawl's free 500 searches a month and Brave's ~1,000 run out together. Each falls back to the other on an error or no results. Searches that find nothing serve bad.webp, both providers failing serves donate.webp, and AI images only fill ?i= past a search's working images. A Firecrawl query's ?i= past 10 serves an AI image without searching. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
38 lines
1.8 KiB
JavaScript
38 lines
1.8 KiB
JavaScript
// AI images for ai.direct-img.link, and the fallback for an ?i= past a search's working images
|
|
const SOURCES = { "auroraimg-6m": auroraImage };
|
|
export const DEFAULT_AI_SOURCE = "auroraimg-6m";
|
|
|
|
// ?src= on ai.*, case-insensitive. Returns null if invalid.
|
|
export function parseAiSource(searchParams) {
|
|
const src = searchParams.get("src")?.toLowerCase() || DEFAULT_AI_SOURCE;
|
|
return Object.hasOwn(SOURCES, src) ? src : null;
|
|
}
|
|
|
|
// Same result shape as fetchImage: { success, buffer, contentType } or { success: false, reason }
|
|
export async function aiImage(src, query, i, env) {
|
|
try {
|
|
return await SOURCES[src](query, seedFor(query, i), env);
|
|
} catch (err) {
|
|
return { success: false, reason: err.name === "TimeoutError" ? "Timeout" : err.message };
|
|
}
|
|
}
|
|
|
|
// Deterministic per query and i, so each ?i= is a different image of the same prompt and repeats are identical.
|
|
// 32-bit FNV-1a: the API takes a 32-bit seed, and this is ~28x faster than crypto.subtle (seeds don't need security)
|
|
function seedFor(query, i) {
|
|
let h = 0x811c9dc5, s = `${query}\n${i}`;
|
|
for (let k = 0; k < s.length; k++) h = Math.imul(h ^ s.charCodeAt(k), 0x01000193);
|
|
return h >>> 0;
|
|
}
|
|
|
|
// AuroraIMG-6M on our Dokploy server: https://github.com/direct-img/AuroraIMG-6M
|
|
async function auroraImage(query, seed, env) {
|
|
if (!env.AURORA_API_KEY) return { success: false, reason: "AURORA_API_KEY not set" };
|
|
const res = await fetch(`https://aurora.direct-img.link/generate?${new URLSearchParams({ prompt: query, seed })}`, {
|
|
headers: { Authorization: `Bearer ${env.AURORA_API_KEY}` },
|
|
signal: AbortSignal.timeout(15000),
|
|
});
|
|
if (!res.ok) return { success: false, reason: `HTTP ${res.status}` };
|
|
return { success: true, buffer: await res.arrayBuffer(), contentType: res.headers.get("content-type") };
|
|
}
|