Git Product home page Git Product logo

ding-dong's Introduction

ding-dong

Build Status

node.js lib for Fast AGI (Asterisk Gateway Interface) server

Fork of node-agi

Use ding-dong

voicer - AGI voice recognizer for Asterisk (use Yandex and Google speech recognizers)

agi-number-archer - AGI server for find region code of phone number (Russia)

lcr-finder - least cost router for Asterisk

Install

npm install ding-dong

const AGIServer = require('ding-dong');

const handler = (context) => {
    context.onEvent('variables')
        .then((vars) => {
            return context.streamFile('beep');
        })
        .then((result) => {
            return context.setVariable('RECOGNITION_RESULT', 'I\'m your father, Luc');
        })
        .then((result) => {
            return context.close();
        });
};

var agi = new AGIServer(handler, {port: 3000});
agi.init();

Add to Asterisk extensions.conf

[default]
exten = > 1000,1,AGI(agi://localhost:3000)

API

see API.md

Links

Asterisk AGI

ding-dong's People

Contributors

adaxi avatar antirek avatar finnhaedicke avatar ipoddubny avatar sergey12313 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ding-dong's Issues

set music, send class

Good friends, I have time on this, so I will post it here. I want to send the class in the setmusic, but it always takes the default, this is what I send context.setMusic ("On", example);

Thanks.

Asterisk 13 not playing the audio

Running following on Asterisk 13, centos 7:

var AGIServer = require('ding-dong');

var handler = function (context) {
    context.onEvent('variables')        
        .then(function (vars) {
            console.log('vars', vars);
            return context.streamFile('sorry-youre-having-problems');
        })
        .then(function (result) {
            return context.setVariable('RECOGNITION_RESULT', 'I\'m your father, Luc');
        })
        .then(function (result) {       
            return context.end();
        })
        .fail(console.log);
};

var agi = new AGIServer(handler, {debug: true});
agi.start(3000);

Asterisk CLI says:
Playing 'sorry-youre-having-problems.gsm' (escape_digits=#) (sample_offset 0) (language 'en')

Running the NodeJs app with debug mode shows:
command STREAM FILE "sorry-youre-having-problems" "#" err: null result: { code: 200, result: '0 endpos=16000' } command SET VARIABLE RECOGNITION_RESULT "I'm your father, Luc" err: null result: { code: 200, result: '1' }

But I cannot hear the audio playing on the zoiper software phone.
My other non FastAGI scripts are playing audio and I can hear it.

Do you have any advise on what I might be doing wrong?

Identify source IP

IS there a simple way to identify the source ip of the box sending the AGI request

Not last version in NPM

If I download ding-dong via npm manager, it gets old version with errors. That version doesn`t have close and init methods also.

not tp able to streamFile or play from the http url

On nodejs public folder i have some audio files. that i want to play with streamFile

const filePath = `http://host.docker.internal:8081/audio/${voiceFileName}.wav`;
return elementApi.environment.variables.context.streamFile(filePath)
            .then((response) => {
              console.log("response played", response);
              return response;
            })
            .catch((err) => {
              console.log("error", err)
            });

the filePath that i have given, is accessible through browser and even using request api i checked that url is valid.

But agi server does not play the sound.

Setting max pool size

In the fastagi java server i can set the max pool size, is there any equivalent option in the ding-dong?

Unhandled Promise Rejection when writing to a closed/unavailable socket

If the AGI socket closes for some reason ding-dong (context.js) will throw an unhandled promise rejection error.

See line 117 of context.js in master branch.

UnhandledPromiseRejectionWarning: Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at writeAfterEnd (_stream_writable.js:266:14)
at Socket.Writable.write (_stream_writable.js:315:5)
at Readable.write (node_modules/readable-stream/lib/_stream_readable.js:855:33)
at Context.send (lib/context.js:117:15)
at lib/context.js:130:10
at new Promise ()
at Context.sendCommand (lib/context.js:129:10)

Asterisk AGI Gosub command

I've just needed to use gosub from my agi dialplan to reuse an old routine. I realized that context.gosub call resolves imediatly and found it wird. These are my findings and I wonder if its the right way to do it or not. Anyhow i'm sure it will help others.

Preparation:

extensions.ael

context start_agi_test {
	s => {
		AGI("agi://localhost:4001");
	}
}

context myTest {
	s => {
		Wait(2);
		Return(GOSUB_AGI_TEST_OK);
	}
}

gosubTest.js

"use strict;"
const AGIServer = require('ding-dong');            // https://github.com/antirek/ding-dong
const { performance } = require('perf_hooks')
const time = (ms) => { try { return new Date(ms).toISOString().slice(11, -1) } catch (err) {return `${(ms) && ms} --> ${err.message}`}}   // Convert Miliseconds to hh:mm:ss.mmm - Ref: https://zaiste.net/convert_miliseconds_to_time/

(async () => {
    const agi = AGIServer((context) => {
        let t_start
        context.onEvent('variables')
            .then( async function(vars) { 
                t_start = performance.now()
                console.log(`[${time(performance.now() - t_start)}] Conection received`)
                const gosubRes = await context.gosub('myTest','s','1')
                if (gosubRes) {
                    console.log(`[${time(performance.now() - t_start)}] Gosub result ${gosubRes.code} ${gosubRes.result}`)
                } else {
                    console.log(`[${time(performance.now() - t_start)}] Gosub result ${gosubRes}`)
                }
                //const noOp = await context.noop()
                let gosubRetVal = await context.getVariable('GOSUB_RETVAL')
                if (gosubRetVal) {
                    console.log(`[${time(performance.now() - t_start)}] First getVariable GOSUB_RETVAL code={${gosubRetVal.code}} result={${gosubRetVal.result}} value={${gosubRetVal.value}}`)
                } else {
                    console.log(`[${time(performance.now() - t_start)}] getVariable GOSUB_RETVAL ${gosubRetVal}`)
                }

                gosubRetVal = await context.getVariable('GOSUB_RETVAL')
                if (gosubRetVal) {
                    console.log(`[${time(performance.now() - t_start)}] Second getVariable GOSUB_RETVAL code={${gosubRetVal.code}} result={${gosubRetVal.result}} value={${gosubRetVal.value}}`)
                } else {
                    console.log(`[${time(performance.now() - t_start)}] getVariable GOSUB_RETVAL ${gosubRetVal}`)
                }

                gosubRetVal = await context.getVariable('GOSUB_RETVAL')
                if (gosubRetVal) {
                    console.log(`[${time(performance.now() - t_start)}] Third getVariable GOSUB_RETVAL code={${gosubRetVal.code}} result={${gosubRetVal.result}} value={${gosubRetVal.value}}`)
                } else {
                    console.log(`[${time(performance.now() - t_start)}] getVariable GOSUB_RETVAL ${gosubRetVal}`)
                }


                await context.end()
            } )
            .catch((err) => {console.log(`Excepción capturada en el contexto general ${err}`); context.end()})

            context.onEvent('close')
                .then( function(res){ console.log(`[${time(performance.now() - t_start)}] Connection Closed`) } )

            context.onEvent('hangup')
                .then( function(res){ console.log(`[${time(performance.now() - t_start)}] Connection HungUp`) } )
        })
    agi.start(4001)
    console.log('AGI Started')
})();

Execution
on asterisk side

asteriskpbxpre02*CLI> originate local/s@start_agi_test application wait 4
    -- Executing [s@start_agi_test:1] AGI("Local/s@start_agi_test-00000011;2", ""agi://localhost:4001"") in new stack
    -- Called s@start_agi_test
    -- Local/s@start_agi_test-00000011;2 AGI Gosub(myTest,s,1) start
    -- Executing [s@myTest:1] Wait("Local/s@start_agi_test-00000011;2", "2") in new stack
    -- Executing [s@myTest:2] Return("Local/s@start_agi_test-00000011;2", "GOSUB_AGI_TEST_OK") in new stack
  == Spawn extension (start_agi_test, s, 1) exited non-zero on 'Local/s@start_agi_test-00000011;2'
    -- Local/s@start_agi_test-00000011;2 AGI Gosub(myTest,s,1) complete GOSUB_RETVAL=GOSUB_AGI_TEST_OK
    -- <Local/s@start_agi_test-00000011;2>AGI Script agi://localhost:4001 completed, returning 0
    -- Auto fallthrough, channel 'Local/s@start_agi_test-00000011;2' status is 'UNKNOWN'

on server side

~/Projects/acca-agi$ node ./gosubTest.js
AGI Started
[00:00:00.000] Conection received
[00:00:00.017] Gosub result 100 0 Trying...
[00:00:02.019] First getVariable GOSUB_RETVAL code={200} result={0 Gosub complete} value={undefined}
[00:00:02.035] Second getVariable GOSUB_RETVAL code={200} result={1} value={GOSUB_AGI_TEST_OK}
[00:00:02.049] Third getVariable GOSUB_RETVAL code={200} result={1} value={GOSUB_AGI_TEST_OK}
[00:00:02.052] Connection Closed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.