agi 0.0.4 → 0.0.666

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,54 +0,0 @@
1
- # node-agi
2
-
3
- Client for asterisk AGI protocol. Parses incomming messages into events. Dispatches AGI commands and their responses from asterisk. Most commonly used as a low level client for a fAGI server.
4
-
5
- ## note: still a work in progress
6
-
7
- ## install
8
- ```
9
- npm install agi
10
- ```
11
-
12
- ## API
13
-
14
- ### agi.createServer([listener])
15
-
16
- Returns a new net.Server instance. The _listener_ will be called on a new agi connection with a single __Context__ object as described below.
17
-
18
- ```js
19
- require('agi').createServer(function(context) {
20
- //context is a new instance of agi.Context for each new agi session
21
- //immedately after asterisk connects to the node process
22
- context.on('variables', function(vars) {
23
- console.log('received new call from: ' + vars.agi_callerid + ' with uniqueid: ' + vars.agi_uniqueid);
24
- });
25
- }).listen(3000);
26
- ```
27
-
28
- ### new agi.Context(stream)
29
-
30
- Constructor to create a new instance of a context. Supply a readable and writable stream to the constructor. Commonly _stream_ will be a `net.Socket` instance.
31
-
32
- ### context.exec(command, [args], [callback])
33
-
34
- Dispatches the `EXEC` AGI command to asterisk with supplied command name and arguments. _callback_ is called with the result of the dispatch.
35
-
36
- ```js
37
- context.exec('ANSWER', function(err, res) {
38
- //the channel is now answered
39
- });
40
-
41
- context.exec('RecieveFax', '/tmp/myfax.tif', function(err, res) {
42
- //fax has been recieved by asterisk and written to /tmp/myfax.tif
43
- });
44
- ```
45
-
46
- ### context.hangup([callbac])
47
-
48
- Dispatches the 'HANGUP' AGI command to asterisk. Does __not__ close the sockets automatically. _callback_ is called with the result of the dispatch.
49
-
50
- ```js
51
- context.hangup(function(err, res) {
52
- //the channel has now been hungup.
53
- });
54
- ```
package/package.json CHANGED
@@ -1,12 +1,8 @@
1
1
  {
2
- "author": "Brian M. Carlson <brian@enginode.com> (http://enginode.com)",
2
+ "author": "Div Garg (http://divyanshgarg.com)",
3
3
  "name": "agi",
4
- "description": "AGI (Asterisk Gateway Interface) for writing dialplan scripts",
5
- "version": "0.0.4",
6
- "repository": {
7
- "type": "git",
8
- "url": "git://github.com/brianc/node-agi.git"
9
- },
4
+ "description": "AGI - Artificial General Intelligence",
5
+ "version": "0.0.666",
10
6
  "main": "lib/",
11
7
  "scripts": {
12
8
  "test": "mocha -R tap"
package/.npmignore DELETED
@@ -1 +0,0 @@
1
- node_modules/
package/.travis.yml DELETED
@@ -1,9 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - 0.8
4
-
5
- script:
6
- - "npm test"
7
-
8
- notifications:
9
- email: false
package/lib/context.js DELETED
@@ -1,129 +0,0 @@
1
- var Readable = require('readable-stream');
2
- var EventEmitter = require('events').EventEmitter;
3
- var state = require('./state');
4
-
5
- var Context = function(stream) {
6
- EventEmitter.call(this);
7
- this.stream = new Readable();
8
- this.stream.wrap(stream);
9
- this.state = state.init;
10
- this.msg = "";
11
- var self = this;
12
- this.stream.on('readable', function() {
13
- //always keep the 'leftover' part of the message
14
- self.msg = self.read();
15
- });
16
- this.msg = this.read();
17
- this.variables = {};
18
- this.pending = null;
19
- this.stream.on('error', this.emit.bind(this, 'error'));
20
- this.stream.on('close', this.emit.bind(this, 'close'));
21
- };
22
-
23
- require('util').inherits(Context, EventEmitter);
24
-
25
- Context.prototype.read = function() {
26
- var buffer = this.stream.read();
27
- if(!buffer) return this.msg;
28
- this.msg += buffer.toString('utf8');
29
- if(this.state === state.init) {
30
- if(this.msg.indexOf('\n\n') < 0) return this.msg; //we don't have whole message
31
- this.readVariables(this.msg);
32
- } else if(this.state === state.waiting) {
33
- if(this.msg.indexOf('\n') < 0) return this.msg; //we don't have whole message
34
- this.readResponse(this.msg);
35
- }
36
- return "";
37
- };
38
-
39
- Context.prototype.readVariables = function(msg) {
40
- var lines = msg.split('\n');
41
- for(var i = 0; i < lines.length; i++) {
42
- var line = lines[i];
43
- var split = line.split(':')
44
- var name = split[0];
45
- var value = split[1];
46
- this.variables[name] = (value||'').trim();
47
- }
48
- this.emit('variables', this.variables);
49
- this.setState(state.waiting);
50
- return "";
51
- };
52
-
53
- Context.prototype.readResponse = function(msg) {
54
- var lines = msg.split('\n');
55
- for(var i = 0; i < lines.length; i++) {
56
- this.readResponseLine(lines[i]);
57
- }
58
- return "";
59
- };
60
-
61
- Context.prototype.readResponseLine = function(line) {
62
- if(!line) return;
63
- var parsed = /^(\d{3})(?: result=)(.*)/.exec(line);
64
- if(!parsed) {
65
- return this.emit('hangup');
66
- }
67
- var response = {
68
- code: parseInt(parsed[1]),
69
- result: parsed[2]
70
- };
71
-
72
- //our last command had a pending callback
73
- if(this.pending) {
74
- var pending = this.pending;
75
- this.pending = null;
76
- pending(null, response);
77
- }
78
- this.emit('response', response);
79
- }
80
-
81
- Context.prototype.setState = function(state) {
82
- this.state = state;
83
- };
84
-
85
- Context.prototype.send = function(msg, cb) {
86
- this.pending = cb;
87
- this.stream.write(msg);
88
- };
89
-
90
- Context.prototype.exec = function() {
91
- var args = Array.prototype.slice.call(arguments, 0);
92
- var last = args.pop();
93
- if(typeof last !== 'function') {
94
- args.push(last);
95
- last = function() { }
96
- }
97
- this.send('EXEC ' + args.join(' ') + '\n', last);
98
- };
99
-
100
- Context.prototype.getVariable = function(name, cb) {
101
- this.send('GET VARIABLE ' + name + '\n', cb || function() { });
102
- };
103
-
104
- Context.prototype.streamFile = function(filename, acceptDigits, cb) {
105
- if(typeof acceptDigits === 'function') {
106
- cb = acceptDigits;
107
- acceptDigits = "1234567890#*";
108
- }
109
- this.send('STREAM FILE "' + filename + '" "' + acceptDigits + '"\n', cb);
110
- };
111
-
112
- Context.prototype.waitForDigit = function(timeout, cb) {
113
- if(typeof timeout === 'function') {
114
- cb = timeout;
115
- //default to 2 second timeout
116
- timeout = 5000;
117
- }
118
- this.send('WAIT FOR DIGIT ' + timeout + '\n', cb);
119
- };
120
-
121
- Context.prototype.hangup = function(cb) {
122
- this.send('HANGUP\n', cb);
123
- };
124
-
125
- Context.prototype.end = function() {
126
- this.stream.end();
127
- };
128
-
129
- module.exports = Context;
package/lib/index.js DELETED
@@ -1,14 +0,0 @@
1
- var Context = require('./context');
2
-
3
- var agi = {
4
- state: require('./state'),
5
- Context: Context,
6
- createServer: function(handler) {
7
- return require('net').createServer(function(stream) {
8
- var context = new Context(stream);
9
- handler(context);
10
- });
11
- }
12
- };
13
-
14
- module.exports = agi;
package/lib/state.js DELETED
@@ -1,7 +0,0 @@
1
- //states for context
2
- var state = {
3
- init: 0,
4
- waiting: 2
5
- };
6
-
7
- module.exports = state;
package/test/index.js DELETED
@@ -1,238 +0,0 @@
1
- var MemoryStream = require('memstream').MemoryStream;
2
- var agi = require('./../lib')
3
- var expect = require('expect.js');
4
- var Context = agi.Context;
5
- var state = agi.state;
6
-
7
- //helpers
8
- var writeVars = function(stream) {
9
- stream.write('agi_network: yes\n');
10
- stream.write('agi_uniqueid: 13507138.14\n');
11
- stream.write('agi_arg_1: test\n');
12
- stream.write('\n\n');
13
- };
14
-
15
- var context = function(cb) {
16
- var stream = new MemoryStream();
17
- var ctx = new Context(stream);
18
- //TODO nasty
19
- ctx.send = function(msg, cb) {
20
- ctx.pending = cb;
21
- ctx.sent = ctx.sent || [];
22
- ctx.sent.push(msg);
23
- };
24
- ctx.once('variables', function(vars) {
25
- cb(ctx);
26
- });
27
- writeVars(stream);
28
- };
29
-
30
- describe('Context', function() {
31
- beforeEach(function(done) {
32
- var self = this;
33
- context(function(context) {
34
- self.context = context;
35
- done();
36
- });
37
- });
38
-
39
- describe('parsing variables', function() {
40
- it('works', function(done) {
41
- var vars = this.context.variables;
42
- expect(vars['agi_network']).ok();
43
- expect(vars['agi_network']).to.eql('yes');
44
- expect(vars['agi_uniqueid']).to.eql('13507138.14');
45
- expect(vars['agi_arg_1']).to.eql('test');
46
- done();
47
-
48
- });
49
-
50
- it('puts context into waiting state', function() {
51
- expect(this.context.state).to.eql(state.waiting);
52
- });
53
- });
54
-
55
- describe('sending command', function() {
56
- it('writes out', function() {
57
- this.context.send('EXEC test');
58
- expect(this.context.sent.length).to.eql(1);
59
- expect(this.context.sent.join('')).to.eql('EXEC test');
60
- });
61
- });
62
-
63
- describe('context.exec', function() {
64
- it('sends exec command', function() {
65
- this.context.exec('test', 'bang', 'another');
66
- expect(this.context.sent.join('')).to.eql('EXEC test bang another\n');
67
- });
68
- });
69
-
70
- describe('command flow', function() {
71
- describe('success', function() {
72
- it('emits proper repsonse', function(done) {
73
- var context = this.context;
74
-
75
- process.nextTick(function() {
76
- context.exec('test', 'bang', 'another');
77
- context.stream.write('200');
78
- context.stream.write(' result=0\n\n');
79
- });
80
-
81
- context.on('response', function(msg) {
82
- expect(msg.code).to.equal(200);
83
- expect(msg.result).to.eql('0');
84
- done();
85
- });
86
-
87
- });
88
-
89
- it('invokes callback with response', function(done) {
90
- var context = this.context;
91
-
92
- process.nextTick(function(){
93
- context.stream.write('200 result=0');
94
- context.stream.write('\n');
95
- context.stream.write('200 result=0');
96
- context.stream.write('\n');
97
- });
98
-
99
- context.exec('test', 'boom', function(err, res) {
100
- done(err);
101
- });
102
- });
103
- });
104
-
105
- describe('two commands', function(done) {
106
-
107
- it('invokes two callbacks', function(done) {
108
- var context = this.context;
109
-
110
- process.nextTick(function() {
111
- context.stream.write('200 result=0\n');
112
- });
113
-
114
- context.exec('test', function(err, res) {
115
- expect(res.result).to.eql('0');
116
-
117
- context.exec('test 2', function(err, res) {
118
- expect(res.result).to.eql('1');
119
- done();
120
- });
121
-
122
- process.nextTick(function() {
123
- context.stream.write('200 result=1\n');
124
- });
125
- });
126
- });
127
- });
128
- });
129
-
130
- describe('hangup', function() {
131
- it('raises hangup on context', function(done) {
132
- this.context.on('hangup', done);
133
- this.context.stream.write('HANGUP\n');
134
- });
135
-
136
- describe('in command response', function() {
137
- it('is passed to callback', function(done) {
138
- var context = this.context;
139
- this.context.exec('whatever', function(err, res) {
140
- });
141
- this.context.on('hangup', done);
142
- process.nextTick(function() {
143
- context.stream.write('200 result=-1\nHANGUP\n');
144
- })
145
- });
146
- });
147
- });
148
-
149
- describe('getVariable', function() {
150
- it('sends correct command', function() {
151
- this.context.getVariable('test');
152
- expect(this.context.sent.join('')).to.eql('GET VARIABLE test\n');
153
- });
154
-
155
- it('gets result', function(done) {
156
- this.context.getVariable('test', function(err, res) {
157
- expect(res.result).eql('1 (abcd)');
158
- done();
159
- });
160
- var self = this;
161
- process.nextTick(function() {
162
- self.context.stream.write('200 result=1 (abcd)\n');
163
- })
164
- });
165
- });
166
-
167
- describe('stream file', function() {
168
- it('sends', function() {
169
- this.context.streamFile('test', '1234567890#*', function() {});
170
- expect(this.context.sent.join('')).to.eql('STREAM FILE "test" "1234567890#*"\n');
171
- });
172
-
173
- it('defaults to all digits', function() {
174
- this.context.streamFile('test', function() {});
175
- expect(this.context.sent.join('')).to.eql('STREAM FILE "test" "1234567890#*"\n');
176
-
177
- });
178
- });
179
-
180
- describe('waitForDigit', function() {
181
- it('sends with default timeout', function() {
182
- this.context.waitForDigit(function() {});
183
- expect(this.context.sent.join('')).to.eql('WAIT FOR DIGIT 5000\n');
184
- });
185
-
186
- it('sends with specified timeout', function() {
187
- this.context.waitForDigit(-1, function() {});
188
- expect(this.context.sent.join('')).to.eql('WAIT FOR DIGIT -1\n');
189
- });
190
- });
191
-
192
- describe('hangup', function() {
193
- it('sends "HANGUP\\n"', function() {
194
- this.context.hangup();
195
- expect(this.context.sent.join('')).to.eql('HANGUP\n');
196
- });
197
- });
198
-
199
- describe('events', function() {
200
- describe('error', function () {
201
- it('is emitted when socket emits error', function(done) {
202
- this.context.on('error', function(err) {
203
- expect(err).to.eql('test');
204
- done();
205
- });
206
- this.context.stream.emit('error', "test");
207
- });
208
- });
209
-
210
- describe('close', function() {
211
- it('is emitted when socket emits close', function(done) {
212
- this.context.on('close', function(hasError) {
213
- expect(hasError).ok();
214
- done();
215
- });
216
-
217
- this.context.stream.emit('close', true);
218
- });
219
- });
220
- });
221
- });
222
-
223
- describe('agi#createServer', function() {
224
- it('returns instance of net.Server', function() {
225
- var net = require('net');
226
- var server = agi.createServer();
227
- expect(server instanceof net.Server).ok();
228
- });
229
-
230
- it('invokes callback when a new connection is established', function(done) {
231
- var server = agi.createServer(function(context) {
232
- expect(context instanceof agi.Context);
233
- done();
234
- });
235
-
236
- server.emit('connection', new MemoryStream());
237
- });
238
- });