/* =================================================================== v2 -- a v1 usava .file-wrapper a[href*="sequence="], que nao extrai nada (testado, retorna vazio). O que funciona: contar quantos .file-wrapper existem (bate com o numero real de bitstreams) e tentar as sequencias 1..N direto -- ja confirmado que o nome do arquivo na URL nao importa nessa rota, so a sequencia. Reparo: itens sem preservation_url que na verdade tem bitstream(s) real(is) -- so nao geram citation_pdf_url (provavelmente por terem mais de um bitstream no bundle ORIGINAL, o que confunde o gerador de citacao do DSpace). Grava all_preservation_urls / all_preservation_sizes (ordenado do maior pro menor) e preservation_url = o maior, pra compatibilidade com o pipeline existente. Rodar depois baixador-extras.js pra pegar as demais imagens dos itens com mais de uma. =================================================================== */ (async () => { const BASE = 'https://brasilianafotografica.bn.gov.br/brasiliana'; const PREFIX = '20.500.12156.1'; const PAUSA = 2000; const sleep = ms => new Promise(r => setTimeout(r, ms)); const jit = () => PAUSA + Math.floor(Math.random() * 600); // preencha com os handles a reparar (ex.: os que tem preservation_url nulo) const HANDLES = __HANDLES__; let db; const abrir = () => new Promise((res, rej) => { const q = indexedDB.open('bras', 1); q.onsuccess = () => res(q.result); q.onerror = () => rej(q.error); }); const get = (st, k) => new Promise(res => { const r = db.transaction(st).objectStore(st).get(k); r.onsuccess = () => res(r.result); r.onerror = () => res(undefined); }); const put = (st, k, v) => new Promise((res, rej) => { const t = db.transaction(st, 'readwrite'); t.objectStore(st).put(v, k); t.oncomplete = res; t.onerror = () => rej(t.error); }); async function contaBitstreams(h) { const r = await fetch(`${BASE}/handle/${PREFIX}/${h}`, {credentials: 'same-origin'}); if (!r.ok) throw new Error('HTTP ' + r.status); const html = await r.text(); const d = new DOMParser().parseFromString(html, 'text/html'); return d.querySelectorAll('.file-wrapper').length; } async function tamanho(url) { const r = await fetch(url, {credentials: 'same-origin'}); if (!r.ok) return -1; const b = await r.blob(); return b.size; } const RESULT = {ok: 0, erro: 0, multiplos: 0, total: HANDLES.length, atual: 0}; window.REPARO_MULTI = RESULT; db = await abrir(); console.log(`reparo-multibitstream v2: ${HANDLES.length} itens a checar`); for (let i = 0; i < HANDLES.length; i++) { const h = HANDLES[i]; RESULT.atual = i + 1; try { const n = await contaBitstreams(h); if (!n) { RESULT.erro++; console.warn(` ${h}: 0 file-wrapper (sem bitstream mesmo)`); await sleep(jit()); continue; } const comTamanho = []; for (let seq = 1; seq <= n; seq++) { const u = `${BASE}/bitstream/${PREFIX}/${h}/${seq}/imagem.jpg`; const bytes = await tamanho(u); if (bytes > 0) comTamanho.push({url: u, bytes}); await sleep(300); } if (!comTamanho.length) { RESULT.erro++; console.warn(` ${h}: ${n} wrapper(s) mas nenhuma sequencia respondeu`); await sleep(jit()); continue; } comTamanho.sort((a, b) => b.bytes - a.bytes); const item = await get('itens', h) || {}; item.preservation_url = comTamanho[0].url; item.all_preservation_urls = comTamanho.map(c => c.url); item.all_preservation_sizes = comTamanho.map(c => c.bytes); await put('itens', h, item); RESULT.ok++; if (comTamanho.length > 1) RESULT.multiplos++; console.log(` ${h}: ${comTamanho.length}/${n} bitstream(s), maior=${(comTamanho[0].bytes/1048576).toFixed(1)}MB`); } catch (e) { RESULT.erro++; console.warn(` ${h}: ${e.message}`); } await sleep(jit()); } console.log(`\nreparo-multibitstream v2 concluido. ok=${RESULT.ok} erro=${RESULT.erro} itens-com-multiplos-bitstreams=${RESULT.multiplos}`); })();