ligar-cobranca
Version:
Ferramenta CLI para fazer chamadas automáticas usando a API da Zenvia
247 lines (216 loc) • 7.72 kB
JavaScript
;
const axios = require('axios');
const fs = require('fs');
const path = require('path');
require('dotenv').config();
const ZENVIA_TOKEN = process.env.ZENVIA_TOKEN;
const ZENVIA_PHONE_NUMBER = process.env.ZENVIA_PHONE_NUMBER;
// Função para log condicional baseado no modo debug
const debugLog = (message, debug = false) => {
if (debug) {
console.log(message);
}
};
// Função para salvar token no arquivo .env
const salvarToken = (token) => {
const envPath = path.join(process.cwd(), '.env');
let envContent = '';
// Verifica se o arquivo .env existe
if (fs.existsSync(envPath)) {
envContent = fs.readFileSync(envPath, 'utf8');
}
// Remove espaços em branco e quebras de linha extras
envContent = envContent.trim();
// Atualiza ou adiciona o token
if (envContent.includes('ZENVIA_TOKEN=')) {
envContent = envContent.replace(/ZENVIA_TOKEN=.*/, `ZENVIA_TOKEN=${token}`);
} else {
envContent += `\nZENVIA_TOKEN=${token}`;
}
// Garante que o arquivo termine com uma quebra de linha
if (!envContent.endsWith('\n')) {
envContent += '\n';
}
// Salva o arquivo
fs.writeFileSync(envPath, envContent);
console.log('✅ Token salvo com sucesso no arquivo .env');
console.log('🔍 Token atual:', token);
};
// Função para formatar número brasileiro
const formatarNumero = (numero) => {
// Remove todos os caracteres não numéricos
numero = numero.replace(/\D/g, '');
// Se o número começa com 0, remove o 0
if (numero.startsWith('0')) {
numero = numero.substring(1);
}
// Se o número não começa com 55 e tem 10 ou 11 dígitos (DDD + número), adiciona 55
if (!numero.startsWith('55') && (numero.length === 10 || numero.length === 11)) {
numero = '55' + numero;
}
// Adiciona o + no início
return '+' + numero;
};
const call = async (token, para, texto, voz, velocidade, de, gravar, debug = false) => {
const voiceMap = {
0: 'br-Ricardo',
1: 'br-Vitoria',
2: 'en-Joey',
3: 'rus-Maxim'
};
const speedMap = {
1: 0.5, // Muito lento
2: 0.75, // Lento
3: 1, // Normal
4: 1.5, // Rápido
5: 2 // Muito rápido
};
try {
debugLog('\n🔍 Iniciando chamada:', debug);
debugLog(' - Para: ' + para, debug);
debugLog(' - De: ' + de, debug);
debugLog(' - Voz: ' + voiceMap[voz], debug);
debugLog(' - Velocidade: ' + speedMap[velocidade], debug);
debugLog(' - Gravar: ' + (gravar ? 'Sim' : 'Não'), debug);
debugLog(' - Mensagem: ' + texto, debug);
const response = await axios.post('https://voice-api.zenvia.com/tts', {
numero_destino: para,
mensagem: texto,
resposta_usuario: false,
tipo_voz: voiceMap[voz],
bina: de,
gravar_audio: gravar,
detecta_caixa: false,
bina_inteligente: true,
velocidade: speedMap[velocidade] || 1
}, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Access-Token': token
}
});
debugLog('✅ Chamada iniciada com sucesso!', debug);
debugLog(' - ID: ' + response.data.dados?.id, debug);
debugLog(' - Status: ' + response.data.status, debug);
debugLog(' - Mensagem: ' + response.data.mensagem, debug);
return {
success: true,
messageId: response.data.dados?.id,
status: response.data.status,
message: response.data.mensagem,
number: para
};
} catch (error) {
debugLog('❌ Erro na chamada:', debug);
debugLog(' - Número: ' + para, debug);
debugLog(' - Status: ' + error.response?.status, debug);
debugLog(' - Mensagem: ' + (error.response?.data?.mensagem || error.message), debug);
if (error.response?.data) {
debugLog(' - Detalhes: ' + JSON.stringify(error.response.data, null, 2), debug);
}
return {
success: false,
error: error.response?.data?.mensagem || error.message,
number: para,
status: error.response?.status,
details: error.response?.data
};
}
};
async function makeMultipleCalls(args) {
const results = [];
const totalCalls = args.quantidade;
let currentCall = 0;
// Faz as chamadas em sequência para o mesmo número
for (let i = 0; i < args.quantidade; i++) {
try {
const result = await call(
args.token || ZENVIA_TOKEN,
args.para,
args.texto,
args.voz,
args.velocidade,
args.de,
args.gravar,
args.debug
);
results.push(result);
currentCall++;
if (args.onProgress) {
args.onProgress(currentCall);
}
} catch (error) {
results.push({
success: false,
number: args.para,
error: error.message
});
currentCall++;
if (args.onProgress) {
args.onProgress(currentCall);
}
}
await new Promise(resolve => setTimeout(resolve, 1000));
}
return results;
}
const makeCall = async (args) => {
try {
// Usa o token fornecido ou o do .env
const token = args.token || process.env.ZENVIA_TOKEN;
if (!token) {
throw new Error('Token não encontrado. Configure ZENVIA_TOKEN no arquivo .env ou forneça um token via linha de comando');
}
const response = await axios.post(
'https://voice-api.zenvia.com/tts',
{
numero_destino: args.para,
mensagem: args.texto,
resposta_usuario: false,
tipo_voz: args.voz === 0 ? 'br-Ricardo' :
args.voz === 1 ? 'br-Vitoria' :
args.voz === 2 ? 'en-Joey' : 'rus-Maxim',
bina: args.de,
gravar_audio: args.gravar,
bina_inteligente: true,
velocidade: args.velocidade === 1 ? 0.5 :
args.velocidade === 2 ? 0.75 :
args.velocidade === 3 ? 1 :
args.velocidade === 4 ? 1.5 : 2
},
{
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Access-Token': token
}
}
);
return {
success: true,
number: args.para,
response: response.data
};
} catch (error) {
throw new Error(error.response?.data?.mensagem || error.message);
}
};
const cobranca = async (args) => {
try {
if (args.debug) {
console.log('Debug: Argumentos recebidos:', args);
}
// Se um token foi fornecido, salva no .env
if (args.token) {
if (!/^[a-zA-Z0-9]{32}$/.test(args.token)) {
throw new Error('Token inválido. O token da Zenvia deve ter 32 caracteres alfanuméricos.');
}
salvarToken(args.token);
}
return await makeMultipleCalls(args);
} catch (error) {
throw new Error(error.message);
}
};
module.exports = cobranca;