#!/usr/bin/env npx ts-node /** * Script de Busca Diária de Publicações * * Executa busca de publicações em todos os processos ativos de todos os usuários. * Pode ser executado via cron ou manualmente. * * Uso: npx ts-node scripts/buscar-publicacoes.ts * Ou: node dist/scripts/buscar-publicacoes.js (se compilado) */ import { PrismaClient } from '@prisma/client' import { buscarPublicacoesReais, buscarPublicacoesEmLote, PublicacaoEncontrada } from '../src/lib/diarios-service' const prisma = new PrismaClient() interface BuscaStats { totalProcessos: number processosComNovas: number totalPublicacoes: number erros: string[] inicioEm: Date fimEm?: Date } async function buscarPublicacoesDiarias(): Promise { const stats: BuscaStats = { totalProcessos: 0, processosComNovas: 0, totalPublicacoes: 0, erros: [], inicioEm: new Date(), } console.log('='.repeat(60)) console.log(`[${new Date().toISOString()}] Iniciando busca diária de publicações`) console.log('='.repeat(60)) try { // Busca todos os processos ativos const processos = await prisma.processoMonitorado.findMany({ where: { status: 'ATIVO' }, select: { id: true, numeroProcesso: true, tribunal: true, userId: true, user: { select: { email: true } } }, }) stats.totalProcessos = processos.length console.log(`\n📋 Total de processos ativos: ${processos.length}`) if (processos.length === 0) { console.log('Nenhum processo ativo encontrado.') return stats } // Busca publicações em lote com rate limiting (500ms entre requisições) console.log('\n🔍 Buscando publicações nos diários oficiais...\n') const resultados = await buscarPublicacoesEmLote( processos.map(p => ({ id: p.id, numeroProcesso: p.numeroProcesso, tribunal: p.tribunal, })), 500 // delay entre requisições ) // Processa resultados for (const processo of processos) { const resultado = resultados.get(processo.id) if (!resultado) { stats.erros.push(`${processo.numeroProcesso}: Sem resultado`) continue } if (!resultado.sucesso) { stats.erros.push(`${processo.numeroProcesso}: ${resultado.erro}`) continue } let novasDoProcesso = 0 for (const pub of resultado.publicacoes) { // Verifica duplicata const existing = await prisma.publicacao.findFirst({ where: { processoId: processo.id, dataPublicacao: { gte: new Date(pub.dataPublicacao.toDateString()), lt: new Date(new Date(pub.dataPublicacao).setDate(pub.dataPublicacao.getDate() + 1)), }, tipo: pub.tipo, }, }) if (!existing) { await prisma.publicacao.create({ data: { processoId: processo.id, dataPublicacao: pub.dataPublicacao, diario: pub.diario, conteudo: pub.conteudo, tipo: pub.tipo, prazoCalculado: pub.prazoCalculado, prazoTipo: pub.prazoTipo, visualizado: false, }, }) novasDoProcesso++ stats.totalPublicacoes++ } } if (novasDoProcesso > 0) { stats.processosComNovas++ console.log(` ✅ ${processo.numeroProcesso}: ${novasDoProcesso} nova(s) publicação(ões)`) } else { console.log(` ➖ ${processo.numeroProcesso}: sem novas publicações`) } } } catch (error) { const msg = error instanceof Error ? error.message : 'Erro desconhecido' stats.erros.push(`Erro geral: ${msg}`) console.error('\n❌ Erro durante execução:', error) } finally { await prisma.$disconnect() } stats.fimEm = new Date() // Resumo final console.log('\n' + '='.repeat(60)) console.log('📊 RESUMO DA BUSCA') console.log('='.repeat(60)) console.log(`Processos verificados: ${stats.totalProcessos}`) console.log(`Processos com novas publicações: ${stats.processosComNovas}`) console.log(`Total de novas publicações: ${stats.totalPublicacoes}`) console.log(`Erros: ${stats.erros.length}`) if (stats.erros.length > 0) { console.log('\n⚠️ Erros encontrados:') stats.erros.forEach(e => console.log(` - ${e}`)) } const duracao = ((stats.fimEm.getTime() - stats.inicioEm.getTime()) / 1000).toFixed(1) console.log(`\n⏱️ Tempo de execução: ${duracao}s`) console.log(`[${stats.fimEm.toISOString()}] Busca finalizada\n`) return stats } // Executar buscarPublicacoesDiarias() .then(stats => { process.exit(stats.erros.length > 0 ? 1 : 0) }) .catch(error => { console.error('Erro fatal:', error) process.exit(1) })