feat: acervo Brasiliana Fotográfica coletado e mural 3D no ar
Captura integral do acervo da Brasiliana Fotográfica (Biblioteca Nacional) para s3://brasiliana: 13.060 itens, 12.985 com imagem de preservação, 13.059 com miniatura derivada, 2.137 cópias legadas e 636 posts do blog. 41.444 objetos no ledger. Os 75 itens sem preservação estão em errors.md: a página do item responde 200, mas a origem serve o bitstream com HTTP 500. Nenhum fica fora do mural, porque todos têm thumbnail. Não versionado, por viver no bucket ou ser reconstruível: catálogo, posts .jsonl, atlas .webp, sqlite de estado e logs. Credenciais ficam de fora pelo .gitignore.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
* ler-localstorage.js — lê o localStorage do Chrome direto do disco, sem
|
||||
* depender da extensão Claude-in-Chrome estar conectada.
|
||||
*
|
||||
* Achado 2026-09-11: o progresso de BAIXA/BAIXA_THUMB (arrays de handles em
|
||||
* localStorage.bras_baixados / bras_thumbs_v2) sobrevive em
|
||||
* "~/Library/Application Support/Google/Chrome/Default/Local Storage/leveldb"
|
||||
* mesmo com a extensão desconectada — é só um arquivo leveldb no disco.
|
||||
* Copiamos antes de ler pra não brigar com o LOCK do Chrome (que está com o
|
||||
* diretório aberto o tempo todo).
|
||||
*
|
||||
* Uso: node ler-localstorage.js [chave1] [chave2] ...
|
||||
* sem argumentos, lê as chaves conhecidas do projeto.
|
||||
*/
|
||||
const { ClassicLevel } = require('classic-level');
|
||||
const { execSync } = require('child_process');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
const ORIGIN = 'https://brasilianafotografica.bn.gov.br';
|
||||
const SRC = path.join(os.homedir(),
|
||||
'Library/Application Support/Google/Chrome/Default/Local Storage/leveldb');
|
||||
const COPY = '/tmp/ls-copy-' + Date.now();
|
||||
|
||||
const KEYS_PADRAO = ['bras_baixados', 'bras_thumbs', 'bras_thumbs_v2'];
|
||||
|
||||
function mk(name) {
|
||||
return Buffer.concat([
|
||||
Buffer.from('_' + ORIGIN, 'latin1'),
|
||||
Buffer.from([0x00, 0x01]),
|
||||
Buffer.from(name, 'latin1'),
|
||||
]);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const keys = process.argv.slice(2);
|
||||
const alvo = keys.length ? keys : KEYS_PADRAO;
|
||||
|
||||
execSync(`cp -r "${SRC}" "${COPY}"`);
|
||||
const db = new ClassicLevel(COPY, { valueEncoding: 'buffer', keyEncoding: 'buffer' });
|
||||
await db.open({ errorIfExists: false, createIfMissing: false });
|
||||
|
||||
const resultado = {};
|
||||
for (const label of alvo) {
|
||||
try {
|
||||
const v = await db.get(mk(label));
|
||||
const flag = v[0];
|
||||
const str = flag === 0 ? v.slice(1).toString('utf16le') : v.slice(1).toString('utf8');
|
||||
const arr = JSON.parse(str);
|
||||
resultado[label] = Array.isArray(arr) ? arr.length : str.length;
|
||||
} catch (e) {
|
||||
resultado[label] = null; // chave não existe ou não é JSON — ok, só ausente
|
||||
}
|
||||
}
|
||||
await db.close();
|
||||
execSync(`rm -rf "${COPY}"`);
|
||||
console.log(JSON.stringify(resultado, null, 2));
|
||||
}
|
||||
|
||||
main().catch(e => { console.error('ERRO', e.message); process.exit(1); });
|
||||
Reference in New Issue
Block a user