UNPKG

@minscof/node-red-contrib-asterisk-ari

Version:
210 lines (176 loc) 9.27 kB
const { connectionPool } = require("../lib/ari-client"); const { handleEvent } = require("../lib/helpers"); module.exports = function (RED) { "use strict"; function ari_bridgedial(n) { RED.nodes.createNode(this, n); var node = this; this.destination = n.destination; this.callerId = n.callerId; node.on('input', async function (msg) { node.status({ fill: "blue", shape: "dot" }); node.app = msg.app; node.topics = [ "StasisStart", "StasisEnd" ]; console.debug(`${node.type} static output endpoint (node) = ${n.destination} `) const destination = msg.payload.destination ?? n.destination; console.debug(`${node.type} call endpoint = ${destination} `); const callee = destination.includes('/') ? destination.split('/')[1].split('@')[0] : null; console.debug(`${node.type} call destination = ${destination} callee = ${callee}`); if (!destination) { node.error("destination undefined"); node.status({}); return; }; const connection = connectionPool.getconn(msg.asteriskId); //console.debug(`ari_bridgedial `, connection); if (!connection) { const err = 'ari_bridgedial ari connection undefined !'; node.error(err); node.status({}); return; } console.debug(`asteriskId : ${msg.asteriskId} `); const channel = connectionPool.getchan(msg.channelId); connection.on('BridgeCreated', async event => { // event.bridge contains the raw bridge data console.log('Bridge debug created:', event.bridge.id); // event.instanceBridge provides a ready-to-use BridgeInstance const bridgeInstance = event.instanceBridge; // Direct control through the instance //await bridgeInstance.add({ channel: [channel.id, dialed.id] }); }); // Create outbound channel const dialed = await connection.Channel(); console.debug(`Channel dialed id: ${dialed.id}`); /* const secondChannel = await connection.channels.createChannel({ endpoint: this.destination, app: 'attendant'}); console.log("🔍 second channel created:", secondChannel); const bridgeInfo = await connection.bridges.createBridge({ type: 'mixing', name: 'myBridge debug' }); console.log(`✅ Bridge created id: ${bridgeInfo.id}`); const bridge = connection.Bridge(bridgeInfo.id); */ channel.on('StasisEnd', async function (event, channel) { console.debug(`channel StasisEnd`); var msg = {} msg.event = 'StasisEnd'; msg.channelId = dialed.id; msg.payload = event; //bridge.destroy(function (err) { }); //const remove = await connection.bridges.destroy(bridge.id); //console.log(`✅ Bridge destroyed with id: ${bridge.id}`); node.send([null, msg]); node.status({}); }); channel.on('ChannelDtmfReceived', function (event, channel) { console.debug(`channel ChannelDtmfReceived`); var msg = {} msg.type = "DTMF"; msg.channelId = channel.id; msg.payload = event; node.send([msg, null]); }); channel.on('ChannelStateChange', event => { console.log('Channel state changed:', event.channel.state); }); channel.on('ChannelDialplan', event => { console.log('Channel ChannelDialplan:', event.channel.state); }); // Listen for specific events connection.on('StasisStart', event => handleEvent(node, event)); connection.on('StasisEnd', event => handleEvent(node, event)); connection.on('ChannelDestroyed', event => handleEvent(node, event)); connection.on('ChannelHangupRequest', event => handleEvent(node, event)); connection.on('ChannelDialplan', event => handleEvent(node, event)); connection.on('Dial', event => handleEvent(node, event)); connection.on('BridgeDestroyed', event => handleEvent(node, event)); connection.on('PeerStatusChange', event => handleEvent(node, event)); /* connection.on('ChannelDestroyed', event => { console.log('ChannelDestroyed2:', event.channel.id); const detail = Object.fromEntries( Object.entries(event).filter(([key]) => key !== 'instanceChannel') ); node.send([null, { event: 'ChannelDestroyed', channelId: event.channel.id, asteriskId: detail.asterisk_id, payload: detail }]); }); connection.on('ChannelHangupRequest', event => { console.log('ChannelHangupRequest2:', event.channel.id); const detail = Object.fromEntries( Object.entries(event).filter(([key]) => key !== 'instanceChannel') ); node.send([null, { event: 'ChannelHangupRequest', channelId: event.channel.id, asteriskId: detail.asterisk_id, payload: detail }]); }); connection.on('ChannelDialplan', event => { console.log('ChannelDialplan2', event.channel.id); const detail = Object.fromEntries( Object.entries(event).filter(([key]) => key !== 'instanceChannel') ); node.send([null, { event: 'ChannelDialplan', channelId: event.channel.id, asteriskId: detail.asterisk_id, payload: detail }]); }); connection.on('Dial', event => { console.log('Dialing:', event.peer.id); //console.debug(`Dial event`,event); node.send([null, { event: 'Dial', peerId: event.peer.id, asteriskId: event.asterisk_id, payload: event }]); node.status({ fill: "blue", shape: "dot", text: `${event.dialstatus} -> ${event.dialstring}` }); }); connection.on('BridgeDestroyed', event => { console.log('BridgeDestroyed2:', event.bridge.id); const detail = Object.fromEntries( Object.entries(event).filter(([key]) => key !== 'instanceChannel') ); node.send([null, { event: 'BridgeDestroyed', bridgeId: event.bridge.id, asteriskId: detail.asterisk_id, payload: detail }]); }); connection.on('PeerStatusChange', event => { console.log('PeerStatusChange2:', event); const detail = Object.fromEntries( Object.entries(event).filter(([key]) => key !== 'instanceChannel') ); node.send([null, { event: 'PeerStatusChange', endpoint: '?', asteriskId: detail.asterisk_id, payload: detail }]); }); */ console.log("📞 Trying to call..."); /* await dialed.originate({ endpoint: this.destination, callerId: this.callerId, app: bridge.id, appArgs: 'dialed' }, function (err, response) { if (err) { throw err; }; if (response) { console.debug(`dialed originate`); console.debug(`Bridgedial bridge:`,bridge); // Monitor channel events in bridge bridge.on('ChannelEnteredBridge', event => { console.log('Channel entered bridge:', event.channel.id); }); bridge.on('ChannelLeftBridge', event => { console.log('Channel left bridge:', event.channel.id); }); bridge.on('BridgeMerged', event => { console.log('Bridge merged:', event.bridge.id); }); } }); */ console.log("🔄 Setting up call..."); await dialed.originate({ endpoint: this.destination, callerId: this.callerId, app: msg.app, appArgs: 'dialed' }); console.log("📞 After trying to call..."); /* // add channels to bridge await bridge.add({ channel: [channel.id, secondChannel.id] }); //console.log("🔍 Bridge channels added:", bridge); */ }); this.on("close", function () { // Called when the node is shutdown - eg on redeploy. // Allows ports to be closed, connections dropped etc. // eg: node.cliant.disconnect(); }); } RED.nodes.registerType("ari_bridgedial", ari_bridgedial); }