/* =================================================================== Baixa as imagens EXTRAS de itens com mais de um bitstream real (achado do reparo-multibitstream.js: 114 itens, a maioria com 2, alguns com 3). A maior de cada item ja e o preservation_url, coberta pelo baixador-navegador.js -- este script pega as demais. PRE-REQUISITO: reparo-multibitstream.js ja rodado (precisa dos campos all_preservation_urls / all_preservation_sizes no IndexedDB). Nomeia como extra_seqN.jpg -- sobe pra preservacao/extra_seqN.jpg junto com a imagem principal do item (subidor.py nao precisa de ajuste, ja trata qualquer nome que nao comece com THUMB__). =================================================================== */ (() => { const PAUSA = 3000; const sleep = ms => new Promise(r => setTimeout(r, ms)); const jit = () => PAUSA + Math.floor(Math.random() * 1000); 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 getAll = st => new Promise((res, rej) => { const r = db.transaction(st).objectStore(st).getAll(); r.onsuccess = () => res(r.result); r.onerror = () => rej(r.error); }); const S = {fase: 'ocioso', feito: 0, erros: 0, total: 0, atual: '', parar: false}; const FEITOS = new Set(JSON.parse(localStorage.getItem('bras_extras') || '[]')); const marcar = k => { FEITOS.add(k); localStorage.setItem('bras_extras', JSON.stringify([...FEITOS])); }; async function alvos() { const itens = await getAll('itens'); const tarefas = []; for (const o of itens) { if (!o.all_preservation_urls || o.all_preservation_urls.length < 2) continue; o.all_preservation_urls.forEach((u, idx) => { if (u === o.preservation_url) return; // a maior ja e coberta pelo BAIXA principal tarefas.push({handle: o.handle, url: u, idx}); }); } return tarefas; } async function iniciar() { S.parar = false; S.fase = 'baixando'; const lista = (await alvos()).filter(t => !FEITOS.has(`${t.handle}#${t.idx}`)); S.total = lista.length; console.log(`${lista.length} imagens extras a baixar (itens com multiplos bitstreams)`); for (let i = 0; i < lista.length; i++) { if (S.parar) { S.fase = 'parado'; return; } const o = lista[i]; S.atual = `${i + 1}/${lista.length}`; const chave = `${o.handle}#${o.idx}`; try { const r = await fetch(o.url, {credentials: 'same-origin'}); if (!r.ok) throw new Error('HTTP ' + r.status); const b = await r.blob(); const seq = o.url.match(/\/(\d+)\/[^/]+$/)?.[1] || o.idx; const nome = `extra_seq${seq}.jpg`; const arqNome = `BRAS__${o.handle.replace(/\//g, '_')}__${nome}`; const a = document.createElement('a'); a.href = URL.createObjectURL(b); a.download = arqNome; document.body.appendChild(a); a.click(); a.remove(); setTimeout(() => URL.revokeObjectURL(a.href), 30000); marcar(chave); S.feito++; } catch (e) { S.erros++; console.warn(` ${chave}: ${e.message}`); } if (i % 20 === 0) console.log(` ${i}/${lista.length} ok=${S.feito} erro=${S.erros}`); await sleep(jit()); } S.fase = 'concluido'; console.log(`\nExtras concluido. ok=${S.feito} erro=${S.erros}`); } window.BAIXA_EXTRA = { quantos: async () => { const a = await alvos(); return {total: a.length, jaFeitos: FEITOS.size}; }, iniciar, status: () => ({...S}), parar: () => { S.parar = true; }, }; (async () => { db = await abrir(); })(); })();