21f33c88a4
continuous-integration/webhook Deploy concluído (VPS4)
- Adiciona coluna clinic_name em images (ALTER TABLE IF NOT EXISTS) - Todas as funções de storage recebem clinicName como parâmetro: saveImage, getImageBuffer, getImageUrl, deleteImage, getDownloadPresignedUrl, getUploadPresignedUrl - Chave Wasabi passa de pc_name/patient/arquivo → clinic_name/pc_name/patient/arquivo - server.js: usa socket.user.clinicName (preenchido via machine_token auth do DB) como fonte primária do nome da clínica nos 3 handlers de upload e na rota thumbnail - Todos os INSERTs em images passam a gravar clinic_name - Corrige bug oculto: wipe de clínica agora apaga o prefixo correto no Wasabi - Scripts utilitários atualizados: backfill-wasabi-thumbs, recreate-all-thumbs, migrate-to-wasabi - client-monitor.js: envia clinicName no client-identify (fallback para clientes legados) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
87 lines
2.7 KiB
JavaScript
87 lines
2.7 KiB
JavaScript
const db = require('./database');
|
|
const storage = require('./storage');
|
|
const imageProcessor = require('./image-processor');
|
|
const fetch = require('node-fetch');
|
|
|
|
async function delay(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
async function run() {
|
|
console.log('🚀 Iniciando recriação de thumbnails para imagens legadas no Wasabi...');
|
|
|
|
await db.initDatabase();
|
|
await storage.loadConfigFromDb();
|
|
|
|
if (!storage.isWasabiEnabled()) {
|
|
console.error('❌ Wasabi não está configurado/habilitado no sistema.');
|
|
process.exit(1);
|
|
}
|
|
|
|
const rows = await db.all(`
|
|
SELECT id, filename, clinic_name, client_name, patient_name
|
|
FROM images
|
|
WHERE thumb_filename IS NULL AND enabled = 1
|
|
`);
|
|
|
|
console.log(`🔍 Encontradas ${rows.length} imagens sem miniatura.`);
|
|
|
|
let successCount = 0;
|
|
let failCount = 0;
|
|
|
|
for (const row of rows) {
|
|
console.log(`\n⚙️ Processando ID ${row.id}: ${row.filename}`);
|
|
|
|
try {
|
|
// 1. Obter URL de download do Wasabi
|
|
const url = await storage.getDownloadPresignedUrl(row.filename, row.clinic_name, row.client_name, row.patient_name);
|
|
if (!url) {
|
|
console.error(`❌ Não foi possível gerar URL de download para ${row.filename}`);
|
|
failCount++;
|
|
continue;
|
|
}
|
|
|
|
// 2. Baixar a imagem original do Wasabi
|
|
const response = await fetch(url);
|
|
if (!response.ok) {
|
|
console.error(`❌ Erro ao baixar imagem do Wasabi (${response.status}): ${response.statusText}`);
|
|
failCount++;
|
|
continue;
|
|
}
|
|
|
|
const arrayBuffer = await response.arrayBuffer();
|
|
const imageBuffer = Buffer.from(arrayBuffer);
|
|
|
|
// 3. Gerar miniatura
|
|
const thumbBuffer = await imageProcessor.getThumbnail(imageBuffer, 400, 400);
|
|
|
|
// 4. Salvar miniatura no Wasabi (usando a mesma lógica de rotas/VPS)
|
|
const thumbFilename = `thumb_${row.filename}`;
|
|
await storage.saveImage(thumbFilename, thumbBuffer, row.clinic_name, row.client_name, row.patient_name, false);
|
|
|
|
// 5. Atualizar o banco de dados
|
|
await db.run('UPDATE images SET thumb_filename = $1 WHERE id = $2', [thumbFilename, row.id]);
|
|
|
|
console.log(`✅ Miniatura gerada e salva com sucesso para ID ${row.id}`);
|
|
successCount++;
|
|
|
|
// Aguardar 1 segundo para não sobrecarregar a VPS/Wasabi
|
|
await delay(1000);
|
|
|
|
} catch (err) {
|
|
console.error(`❌ Erro ao processar ID ${row.id}:`, err.message);
|
|
failCount++;
|
|
}
|
|
}
|
|
|
|
console.log(`\n🎉 Processamento concluído!`);
|
|
console.log(`✅ Sucessos: ${successCount}`);
|
|
console.log(`❌ Falhas: ${failCount}`);
|
|
process.exit(0);
|
|
}
|
|
|
|
run().catch(err => {
|
|
console.error('❌ Erro crítico:', err);
|
|
process.exit(1);
|
|
});
|