🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

ding-dong

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ding-dong - npm Package Compare versions

Comparing version

to
0.1.2

API.md

12

example/app.js
var AGIServer = require('./../lib/index');
var handler = function (context) {
context.onEvent('variables')
context.onEvent('variables')
.then(function (vars) {
return context.streamFile('beep');
console.log('vars', vars);
return context.streamFile();
})

@@ -13,6 +14,7 @@ .then(function (result) {

return context.end();
});
})
.fail(console.log);
};
var agi = new AGIServer(handler);
agi.start(3000);
var agi = new AGIServer(handler, {debug: true});
agi.start(3007);

@@ -5,18 +5,26 @@ var Readable = require('readable-stream');

var Q = require('q');
var commands = require('./command');
//base context
var Context = function (stream, debug) {
EventEmitter.call(this);
this.debug = debug;
this.stream = new Readable();
this.stream.setEncoding('utf8');
this.stream.wrap(stream);
this.state = state.init;
this.msg = "";
this.variables = {};
this.pending = null;
var self = this;
this.stream.on('readable', function () {
//always keep the 'leftover' part of the message
//always keep the 'leftover' part of the message
self.msg = self.read();
});
this.msg = this.read();
this.variables = {};
this.pending = null;
this.stream.on('error', this.emit.bind(this, 'error'));

@@ -28,28 +36,31 @@ this.stream.on('close', this.emit.bind(this, 'close'));

Context.prototype.read = function() {
var buffer = this.stream.read();
if(!buffer) return this.msg;
this.msg += buffer.toString('utf8');
if(this.state === state.init) {
if(this.msg.indexOf('\n\n') < 0) return this.msg; //we don't have whole message
Context.prototype.read = function () {
var buffer = this.stream.read();
if (!buffer) return this.msg;
this.msg += buffer;
if (this.state === state.init) {
if (this.msg.indexOf('\n\n') < 0) return this.msg; //we don't have whole message
this.readVariables(this.msg);
} else if(this.state === state.waiting) {
if(this.msg.indexOf('\n') < 0) return this.msg; //we don't have whole message
} else if (this.state === state.waiting) {
if (this.msg.indexOf('\n') < 0) return this.msg; //we don't have whole message
this.readResponse(this.msg);
}
return "";
return '';
};
Context.prototype.readVariables = function (msg) {
var lines = msg.split('\n');
for(var i = 0; i < lines.length; i++) {
var line = lines[i];
var split = line.split(':')
var lines = msg.split('\n');
lines.map(function (line) {
var split = line.split(':');
var name = split[0];
var value = split[1];
this.variables[name] = (value||'').trim();
}
this.variables[name] = (value || '').trim();
}, this);
this.emit('variables', this.variables);
this.setState(state.waiting);
return "";
};

@@ -59,23 +70,26 @@

var lines = msg.split('\n');
for(var i = 0; i < lines.length; i++) {
this.readResponseLine(lines[i]);
}
return "";
lines.map(function (line) {
this.readResponseLine(line);
}, this);
};
Context.prototype.readResponseLine = function (line) {
if(!line) return;
if (!line) return;
var parsed = /^(\d{3})(?: result=)(.*)/.exec(line);
//var parsed = /^(\d{3})(?: result=)(.*)/.exec(line);
var parsed = /^(\d{3})(?: result=)([^(]*)(?:\((.*)\))?/.exec(line);
if(!parsed) {
if (!parsed) {
return this.emit('hangup');
}
var response = {
code: parseInt(parsed[1]),
result: parsed[2]
result: parsed[2].trim(),
};
//our last command had a pending callback
if(this.pending) {
if (this.pending) {
var pending = this.pending;

@@ -88,7 +102,7 @@ this.pending = null;

Context.prototype.setState = function(state) {
Context.prototype.setState = function (state) {
this.state = state;
};
Context.prototype.send = function(msg, cb) {
Context.prototype.send = function (msg, cb) {
this.pending = cb;

@@ -126,203 +140,48 @@ this.stream.write(msg);

Context.prototype.exec = function() {
var args = Array.prototype.slice.call(arguments, 0);
return this.sendCommand('EXEC ' + args.join(' '));
};
//additional agi commands
Context.prototype.dial = function (num, timeout, params) {
return this.exec('Dial', num + ',' + timeout + ',' + params);
};
commands.map(function (command) {
var str = '';
Context.prototype[command.name] = function () {
if (command.params > 0) {
var args = [].slice.call(arguments, 0, command.params);
str = command.command + " " + prepareArgs(args, command.paramRules, command.params).join(" ");
} else {
str = command.command;
}
return this.sendCommand(str);
};
});
Context.prototype.databaseDel = function (family, key) {
return this.sendCommand('DATABASE DEL ' + family + ' ' + key);
};
var prepareArgs = function (args, argsRules, count) {
var q, argsP = [];
if (argsRules && count) {
Context.prototype.databaseDelTree = function (family, keytree) {
return this.sendCommand('DATABASE DELTREE ' + family + ' ' + keytree);
};
args = args.map(function (arg){
return arg.toString();
});
Context.prototype.databaseGet = function (family, key) {
return this.sendCommand('DATABASE GET ' + family + ' ' + key);
};
for (var i = 0; i < count; i++) {
argsP[i] = (args[i]) ?
args[i] :
((argsRules[i] && argsRules[i].default) ?
argsRules[i].default :
'');
}
Context.prototype.databasePut = function (family, key, value) {
return this.sendCommand('DATABASE PUT ' + family + ' ' + key + ' ' + value);
q = argsP.map(function (arg, i) {
return (argsRules[i] && argsRules[i].prepare) ? argsRules[i].prepare(arg) : arg;
});
} else {
q = args;
}
return q;
};
Context.prototype.speechCreate = function (engine) {
return this.sendCommand('SPEECH CREATE ' + engine);
};
//sugar commands
Context.prototype.speechDestroy = function () {
return this.sendCommand('SPEECH DESTROY');
Context.prototype.dial = function (target, timeout, params) {
return this.exec('Dial', target + ',' + timeout + ',' + params);
};
Context.prototype.speechActivateGrammar = function (name) {
return this.sendCommand('SPEECH ACTIVATE GRAMMAR ' + name);
};
Context.prototype.speechDeactivateGrammar = function (name) {
return this.sendCommand('SPEECH DEACTIVATE GRAMMAR ' + name);
};
Context.prototype.speechLoadGrammar = function (name, path) {
return this.sendCommand('SPEECH LOAD GRAMMAR ' + name + ' ' + path);
};
Context.prototype.speechUnloadGrammar = function (name) {
return this.sendCommand('SPEECH UNLOAD GRAMMAR ' + name);
};
Context.prototype.speechSet = function (name, value) {
return this.sendCommand('SPEECH SET ' + name + ' ' + value);
};
Context.prototype.speechRecognize = function (prompt, timeout, offset) {
return this.sendCommand('SPEECH RECOGNIZE ' + prompt + ' ' + timeout + ' ' + offset);
};
Context.prototype.getVariable = function (name) {
return this.sendCommand('GET VARIABLE ' + name);
};
Context.prototype.getFullVariable = function (variable, channel) {
return this.sendCommand('GET FULL VARIABLE ' + variable + ' ' + channel);
};
Context.prototype.getData = function (file, timeout, maxdigits) {
return this.sendCommand('GET DATA ' + file + ' ' + timeout + ' ' + maxdigits);
};
Context.prototype.getOption = function (file, escape_digits, timeout) {
return this.sendCommand('GET OPTION ' + file + ' "' + escape_digits + '" ' + timeout);
};
Context.prototype.receiveChar = function (timeout) {
return this.sendCommand('RECEIVE CHAR ' + timeout);
};
Context.prototype.receiveText = function (timeout) {
return this.sendCommand('RECEIVE TEXT ' + timeout);
};
Context.prototype.setAutoHangup = function (seconds) {
return this.sendCommand('SET AUTOHANGUP ' + seconds);
};
Context.prototype.setCallerID = function (number) {
return this.sendCommand('SET CALLERID ' + number);
};
Context.prototype.setContext = function (context) {
return this.sendCommand('SET CONTEXT ' + context);
};
Context.prototype.setExtension = function (extension) {
return this.sendCommand('SET EXTENSION ' + extension);
};
Context.prototype.setPriority = function (priority) {
return this.sendCommand('SET PRIORITY ' + priority);
};
Context.prototype.setMusic = function (musicclass) {
return this.sendCommand('SET MUSIC ' + musicclass);
};
Context.prototype.setVariable = function (name, value) {
return this.sendCommand('SET VARIABLE ' + name + ' "' + value + '"');
};
Context.prototype.sendImage = function (image) {
return this.sendCommand('SEND IMAGE ' + image);
};
Context.prototype.sendText = function (text) {
return this.sendCommand('SEND TEXT "' + text + '"');
};
Context.prototype.channelStatus = function (name) {
return this.sendCommand('CHANNEL STATUS ' + name);
};
Context.prototype.answer = function () {
return this.sendCommand('ANSWER');
};
Context.prototype.verbose = function (message, level) {
return this.sendCommand('VERBOSE "' + message + '" ' + level);
};
Context.prototype.tddMode = function (value) {
return this.sendCommand('TDD MODE ' + value);
};
Context.prototype.noop = function (cb) {
return this.sendCommand('NOOP');
};
Context.prototype.gosub = function (context, extension, priority, option) {
var str = [context, extension, priority, option].join(' ');
return this.sendCommand('GOSUB ' + str);
};
Context.prototype.recordFile = function (filename, format, escape_digits, timeout, offset, beep, silence) {
var str = [
'"' + filename + '"',
format,
escape_digits,
parseInt(timeout)*1000,
offset,
beep,
silence
].join(' ');
return this.sendCommand('RECORD FILE ' + str);
};
Context.prototype.sayNumber = function (number, escape_digits) {
return this.sendCommand('SAY NUMBER ' + number + ' "' + escape_digits + '"');
};
Context.prototype.sayAlpha = function (number, escape_digits) {
return this.sendCommand('SAY ALPHA ' + number + ' "' + escape_digits + '"');
};
Context.prototype.sayDate = function (seconds, escape_digits) { //seconds since 1.01.1970
return this.sendCommand('SAY DATE ' + seconds + ' "' + escape_digits + '"');
};
Context.prototype.sayTime = function (seconds, escape_digits) { //seconds since 1.01.1970
return this.sendCommand('SAY TIME ' + seconds + ' "' + escape_digits + '"');
};
Context.prototype.sayDateTime = function (seconds, escape_digits, format, timezone) { //seconds since 1.01.1970
return this.sendCommand('SAY DATETIME ' + seconds + ' "' + escape_digits + '" ' + format + ' ' + timezone);
};
Context.prototype.sayDigits = function (digits, escape_digits) {
return this.sendCommand('SAY DIGITS ' + digits + ' "' + escape_digits + '"');
};
Context.prototype.sayPhonetic = function (string, escape_digits) {
return this.sendCommand('SAY PHONETIC ' + string + ' "' + escape_digits + '"');
};
Context.prototype.streamFile = function (filename, digits) {
var acceptDigits = digits ? digits : "1234567890#*";
return this.sendCommand('STREAM FILE "' + filename + '" "' + acceptDigits + '"');
};
Context.prototype.waitForDigit = function (timeoutIn) {
var timeout = timeoutIn ? timeoutIn : 5000;
return this.sendCommand('WAIT FOR DIGIT ' + timeout);
};
Context.prototype.hangup = function () {
return this.sendCommand('HANGUP');
};
Context.prototype.asyncAGIBreak = function () {
return this.sendCommand('ASYNCAGI BREAK');
};
module.exports = Context;

@@ -5,3 +5,3 @@ {

"description": "Write AGI-server quickly! (AGI - Asterisk Gateway Interface)",
"version": "0.1.1",
"version": "0.1.2",
"repository": {

@@ -8,0 +8,0 @@ "type": "git",

@@ -5,9 +5,15 @@ # ding-dong

Create AGI server with ding-dong. Use with Asterisk for fast telephony apps. [Fork of node-agi](http://github.com/brianc/node-agi)
Create AGI server with ding-dong. Use with Asterisk for fast telephony apps.
[Fork of node-agi](http://github.com/brianc/node-agi)
stable version 0.1.1
unstable version 0.1.2
Use ding-dong
=============
[voicer](http://github.com/antirek/voicer) - AGI yandex voice recognizer for Asterisk
[voicer](http://github.com/antirek/voicer) - AGI voice recognizer for Asterisk (use Yandex and Google speech recognizers)

@@ -60,41 +66,12 @@ [agi-number-archer](http://github.com/antirek/agi-number-archer) - AGI server for find region code of phone number (Russia)

### And call to 1000 and view asterisk output.
### And call to 1000 and view asterisk output. Profit!
## API
see [API.md](API.md)
## API
attention: using javascript promises
### context.exec(command, [args])
Dispatches the `EXEC` AGI command to asterisk with supplied command name and arguments. _callback_ is called with the result of the dispatch.
```js
context.exec('Dial', opt1, opt2, .., optN)
.then(function(result)
//the channel call app Dial with options
});
context.exec('RecieveFax', '/tmp/myfax.tif')
.then(function(result) {
//fax has been recieved by asterisk and written to /tmp/myfax.tif
});
```
### context.hangup()
Dispatches the 'HANGUP' AGI command to asterisk. Does __not__ close the sockets automatically. _callback_ is called with the result of the dispatch.
```js
context.hangup()
.then(function(){
//do something
});
```
## Links
[Asterisk AGI](https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+AGI+Commands)

@@ -24,5 +24,7 @@ var MemoryStream = require('memorystream');

};
ctx.once('variables', function(vars) {
cb(ctx);
});
writeVars(stream);

@@ -32,5 +34,5 @@ };

describe('Context', function() {
beforeEach(function(done) {
beforeEach(function (done) {
var self = this;
context(function(context) {
context(function (context) {
self.context = context;

@@ -422,3 +424,3 @@ done();

it('sends with default timeout', function() {
this.context.waitForDigit();
this.context.waitForDigit(5000);
expect(this.context.sent.join('')).to.eql('WAIT FOR DIGIT 5000\n');

@@ -456,3 +458,3 @@ });

it('sends correct command', function() {
this.context.verbose("good", 2);
this.context.verbose('good', 2);
expect(this.context.sent.join('')).to.eql('VERBOSE "good" 2\n');

@@ -459,0 +461,0 @@ });