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.
62 lines
2.2 KiB
JavaScript
62 lines
2.2 KiB
JavaScript
#!/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); });
|