This is the flow I tried to use with ARI, but Stasis cannot add the originating channel to the transfer bridge I created in the stasis application.
Remembering that this flow that I’m trying to do, is only after the originator is served by the agent.
features.conf =>
[applicationmap]
transferCall => #4,peer,Gosub(transfer-call,call,1),default
custom.conf =>
;=====================================
[transfer-call]
;=====================================
exten => call,1,Noop(##### TRANSFERRING CALL#####)
exten => call,n,Stasis(meu_app_ari)
exten => call,n,hangup()
app.js =>
// Criar servidor WebSocket
const wss = new WebSocket.Server({ port: 8081 });
wss.on(‘connection’, (ws) => {
console.log(‘Cliente WebSocket conectado!’);
ws.on(‘message’, (message) => {
console.log(Mensagem recebida: ${message}
);
ws.send(Echo: ${message}
);
});
ws.on(‘close’, () => {
console.log(‘Cliente WebSocket desconectado.’);
});
});
Ari.connect(ARI_URL, USERNAME, PASSWORD)
.then((client) => {
console.log(‘Conectado ao Asterisk ARI!’);
client.on('StasisStart', async (event, channel) => {
console.log(`📞 Canal recebido no Stasis: ${channel.id}`);
console.log(`📞 Canal recebido no Stasis: ${channel.name}`);
// Verifica se o canal já está em uma bridge
bridgeId = await listarBridges(client,channel.id)
transferCall(channel,bridgeId);
});
let transferInProgress = false; // Flag para evitar múltiplas chamadas
async function listarBridges(client,channelId) {
var bridgeId;
var bridges = await client.bridges.list()
if (bridges.length === 0) {
console.log(‘Nenhuma Bridge ativa no momento.’);
} else {
bridges.forEach(bridge => {
if(bridge.channels.includes(channelId)){
console.log(Bridge ID: ${bridge.id}, Tipo: ${bridge.bridge_type}, Canais: ${bridge.channels}
);
bridgeId = bridge.id;
}
});
}
return bridgeId;
}
async function transferCall(originateChannel,bridgeOriId) {
if (!originateChannel || !originateChannel.id) {
console.error('❌ Erro: canal inválido ou não definido!');
return;
}
if (transferInProgress) {
console.log('⚠️ Transferência já em andamento. Ignorando solicitação repetida.');
return;
}
transferInProgress = true; // Marca como em andamento
console.log(`🔀 Transferindo chamada para número externo...`);
try {
// Criar uma nova chamada para o número externo
let externalChannel = await client.channels.originate({
// endpoint: 'SIP/300', // Substitua pelo número desejado
endpoint: 'Local/11963001933@Padrao', // Substitua pelo número desejado
app: 'meu_app_ari',
appArgs: 'external',
callerId: originateChannel.caller.id
});
// Criar uma nova bridge para conectar o chamador e a chamada externa
let transferBridge = await client.bridges.create({ type: 'mixing' });
console.log(`🔄 Criando bridge de transferência: ${transferBridge}`);
await client.bridges.addChannel({
bridgeId: transferBridge.id,
channel: originateChannel.id
});
// Quando a chamada externa for atendida, conectamos os canais
externalChannel.on('StasisStart', async () => {
console.log('📞 Chamada externa conectada.');
await client.bridges.addChannel({
bridgeId: transferBridge.id,
channel: externalChannel.id
});
});
// Quando a chamada externa terminar, reconectar o agente
externalChannel.on('ChannelHangupRequest', async () => {
await client.bridges.destroy({
bridgeId: transferBridge.id
});
console.log('❌ Chamada externa finalizada. Retornando agente.');
// adicionar o chamador da bridge de orignal
await client.bridges.addChannel({
bridgeId: bridgeOriId,
channel: originateChannel.id
});
await client.channels.continueInDialplan(
{channelId: originateChannel.id}
);
});
} catch (error) {
console.error('❌ Erro ao tentar realizar a transferência:', error);
}
}
client.start(APP_NAME);
})
.catch(console.error);