/** * Import nóżki meblowej ze strony produktu (mir-tex24.pl). * Strona → parseMirtexLegPage → zdjęcie do source_assets (rola leg_reference, * dedup po sha256) → upsert furniture_legs z image_asset_id. * Zdjęcie staje się trzecią referencją multi-image w runGenerateShot. */ import type { Db } from "../db.js"; import type { AppConfig } from "../config.js"; import { ingestUpload } from "../media/ingest.js"; import { createSourceFetcher, normalizeSourceUrl, type SourceFetcher } from "../media/sourceFetch.js"; import { parseMirtexLegPage, legPromptFromParsed, LegParseError } from "../import/legMirtex.js"; import { upsertFurnitureLeg, legIdFromName } from "./furnitureLegs.js"; import { audit } from "./audit.js"; export class LegImportError extends Error { constructor(public readonly code: string, message: string) { super(message); this.name = "LegImportError"; } } export async function importLegFromUrl( db: Db, cfg: AppConfig, input: { url: string; actor: string }, fetcher?: SourceFetcher ): Promise<{ leg: ReturnType; sourceId: string; duplicate: boolean }> { // Walidacja URL (https + allowlista mir-tex24.pl) zanim cokolwiek pobierzemy. const normalized = normalizeSourceUrl(input.url, "leg_page"); const fetch = fetcher ?? createSourceFetcher(); const page = await fetch(normalized.fetchUrl, "leg_page"); const parsed = parseMirtexLegPage(page.buffer.toString("utf8"), page.finalUrl || normalized.fetchUrl); const img = await fetch(parsed.imageUrl, "leg_image"); const out = await ingestUpload(db, cfg, { buffer: img.buffer, originalName: `mirtex-${parsed.imageUrl.split("/").pop() ?? "leg"}`, productId: null, role: "leg_reference", note: `Zdjęcie nóżki: ${parsed.name} (mir-tex24.pl)`, uploadedBy: input.actor, sourceUrl: parsed.imageUrl, fetchedAt: img.fetchedAt, }); const leg = upsertFurnitureLeg(db, { id: legIdFromName(parsed.name), name: parsed.name, aiPrompt: legPromptFromParsed(parsed), finishType: parsed.shape ?? parsed.material, imageAssetId: out.id, heightCm: parsed.heightCm, material: parsed.material, sourceUrl: normalized.requestedUrl, }); audit(db, { actor: input.actor, action: "furniture_leg.imported", entity: "furniture_legs", entityId: leg.id, detail: { url: normalized.requestedUrl, sourceId: out.id, duplicate: out.duplicate, heightCm: leg.height_cm }, }); return { leg, sourceId: out.id, duplicate: out.duplicate }; } export { LegParseError };