@gibme/asterisk-gateway-interface 1.0.1

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/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2016-2022 Brandon Lehmann
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # Simple [Asterisk Gateway Interface](https://wiki.asterisk.org/wiki/pages/viewpage.action?pageId=32375589) Helper
2
+
3
+ ```typescript
4
+ import AGI, { Channel } from '@gibme/asterisk-gateway-interface';
5
+
6
+ (async () => {
7
+ const agi = new AMI({
8
+ port: 3000
9
+ });
10
+
11
+ agi.on('channel', async (channel: Channel) => {
12
+ await channel.answer();
13
+ await channel.sayNumber(12345);
14
+ await channel.hangup();
15
+ });
16
+
17
+ await agi.start();
18
+ })()
19
+ ```
@@ -0,0 +1,46 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import Channel from './channel';
4
+ export { Channel };
5
+ export { ChannelState, DialStatus, PlaybackStatus } from './types';
6
+ /**
7
+ * Represents an AGI server instance
8
+ */
9
+ export default class AsteriskGatewayInterface extends EventEmitter {
10
+ readonly port: number;
11
+ readonly ip: string;
12
+ private readonly m_server;
13
+ /**
14
+ * Constructs a new instance of the object
15
+ * @param port
16
+ * @param ip
17
+ * @param maximumListeners
18
+ */
19
+ constructor(port?: number, ip?: string, maximumListeners?: number);
20
+ /**
21
+ * Event that is emitted when a new AGI channel has been established and is ready for interation
22
+ * @param event
23
+ * @param listener
24
+ */
25
+ on(event: 'channel', listener: (channel: Channel) => void): this;
26
+ /**
27
+ * Event that is emitted when the server encounters and error
28
+ * @param event
29
+ * @param listener
30
+ */
31
+ on(event: 'error', listener: (error: any) => void): this;
32
+ /**
33
+ * Event that emitted when the server is closed and stopped
34
+ * @param event
35
+ * @param listener
36
+ */
37
+ on(event: 'close', listener: () => void): this;
38
+ /**
39
+ * Starts the AGI server
40
+ */
41
+ start(): Promise<void>;
42
+ /**
43
+ * Stops the AGI server
44
+ */
45
+ stop(): Promise<void>;
46
+ }
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ // Copyright (c) 2016-2022 Brandon Lehmann
3
+ //
4
+ // Please see the included LICENSE file for more information.
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.PlaybackStatus = exports.DialStatus = exports.ChannelState = exports.Channel = void 0;
19
+ const net_1 = require("net");
20
+ const events_1 = require("events");
21
+ const channel_1 = __importDefault(require("./channel"));
22
+ exports.Channel = channel_1.default;
23
+ var types_1 = require("./types");
24
+ Object.defineProperty(exports, "ChannelState", { enumerable: true, get: function () { return types_1.ChannelState; } });
25
+ Object.defineProperty(exports, "DialStatus", { enumerable: true, get: function () { return types_1.DialStatus; } });
26
+ Object.defineProperty(exports, "PlaybackStatus", { enumerable: true, get: function () { return types_1.PlaybackStatus; } });
27
+ /**
28
+ * Represents an AGI server instance
29
+ */
30
+ class AsteriskGatewayInterface extends events_1.EventEmitter {
31
+ /**
32
+ * Constructs a new instance of the object
33
+ * @param port
34
+ * @param ip
35
+ * @param maximumListeners
36
+ */
37
+ constructor(port = 3000, ip = '0.0.0.0', maximumListeners = 20) {
38
+ super();
39
+ this.port = port;
40
+ this.ip = ip;
41
+ this.m_server = (0, net_1.createServer)();
42
+ this.setMaxListeners(maximumListeners);
43
+ this.m_server.on('connection', (socket) => {
44
+ const channel = new channel_1.default(socket);
45
+ channel.on('ready', () => this.emit('channel', channel));
46
+ });
47
+ this.m_server.on('close', () => this.emit('close'));
48
+ }
49
+ on(event, listener) {
50
+ return super.on(event, listener);
51
+ }
52
+ /**
53
+ * Starts the AGI server
54
+ */
55
+ start() {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ return new Promise((resolve, reject) => {
58
+ this.m_server.once('error', error => {
59
+ return reject(error);
60
+ });
61
+ this.m_server.listen(this.port, this.ip, () => {
62
+ this.m_server.removeAllListeners('error');
63
+ this.m_server.on('error', error => this.emit('error', error));
64
+ return resolve();
65
+ });
66
+ });
67
+ });
68
+ }
69
+ /**
70
+ * Stops the AGI server
71
+ */
72
+ stop() {
73
+ return __awaiter(this, void 0, void 0, function* () {
74
+ if (!this.m_server.listening) {
75
+ return;
76
+ }
77
+ return new Promise((resolve, reject) => {
78
+ this.m_server.close((error) => {
79
+ if (error) {
80
+ return reject(error);
81
+ }
82
+ return resolve();
83
+ });
84
+ });
85
+ });
86
+ }
87
+ }
88
+ exports.default = AsteriskGatewayInterface;
@@ -0,0 +1,457 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { Socket } from 'net';
4
+ import { EventEmitter } from 'events';
5
+ import { IResponse, DialStatus, PlaybackStatus, ChannelState } from './types';
6
+ /**
7
+ * Represents an AGI Channel
8
+ */
9
+ export default class Channel extends EventEmitter {
10
+ private readonly m_connection;
11
+ private m_state;
12
+ private m_message;
13
+ private m_network;
14
+ private m_network_script;
15
+ private m_request;
16
+ private m_channel;
17
+ private m_language;
18
+ private m_type;
19
+ private m_uniqueid;
20
+ private m_version;
21
+ private m_callerid;
22
+ private m_calleridname;
23
+ private m_callingpres;
24
+ private m_callingani2;
25
+ private m_callington;
26
+ private m_callingtns;
27
+ private m_dnid;
28
+ private m_rdnis;
29
+ private m_context;
30
+ private m_extension;
31
+ private m_priority;
32
+ private m_enhanced;
33
+ private m_accountcode;
34
+ private m_threadid;
35
+ /**
36
+ * Creates a new instance of a channel object
37
+ * @param connection the AGI socket connection
38
+ */
39
+ constructor(connection: Socket);
40
+ /**
41
+ * Event that is emitted when the underlying socket encounters an error
42
+ * @param event
43
+ * @param listener
44
+ */
45
+ on(event: 'error', listener: (error: any) => void): this;
46
+ /**
47
+ * Event that is emitted when the underlying socket is closed
48
+ * @param event
49
+ * @param listener
50
+ */
51
+ on(event: 'close', listener: () => void): this;
52
+ /**
53
+ * Event that emitted when the underlying socket times out
54
+ * @param event
55
+ * @param listener
56
+ */
57
+ on(event: 'timeout', listener: () => void): this;
58
+ /**
59
+ * Event that is emitted when the channel is ready
60
+ * @param event
61
+ * @param listener
62
+ */
63
+ on(event: 'ready', listener: () => void): this;
64
+ /**
65
+ * Event that is emitted when a response is received from the Asterisk server
66
+ * @param event
67
+ * @param listener
68
+ */
69
+ on(event: 'recv', listener: (response: string) => void): this;
70
+ /**
71
+ * Event that emitted when the channel is hung up
72
+ * @param event
73
+ * @param listener
74
+ */
75
+ on(event: 'hangup', listener: () => void): this;
76
+ /**
77
+ * Event that emitted when the response from the Asterisk server is processed into a structured response
78
+ * @param event
79
+ * @param listener
80
+ */
81
+ on(event: 'response', listener: (response: IResponse) => void): this;
82
+ /**
83
+ * Event that is emitted when data is sent to the Asterisk server
84
+ * @param event
85
+ * @param listener
86
+ */
87
+ on(event: 'send', listener: (data: string) => void): this;
88
+ /**
89
+ * Whether this AGI request is over the network
90
+ */
91
+ get network(): boolean;
92
+ /**
93
+ * The network path included in the AGI request
94
+ * ie. agi://127.0.0.1:3000/test
95
+ * This value would return 'test'
96
+ */
97
+ get network_script(): string;
98
+ /**
99
+ * The version of Asterisk
100
+ */
101
+ get version(): string;
102
+ /**
103
+ * The filename of your script
104
+ * ie. agi
105
+ */
106
+ get request(): string;
107
+ /**
108
+ * The originating channel (your phone)
109
+ */
110
+ get channel(): string;
111
+ /**
112
+ * The language code (e.g. “en”)
113
+ */
114
+ get language(): string;
115
+ /**
116
+ * The originating channel type (e.g. “SIP” or “ZAP”)
117
+ */
118
+ get type(): string;
119
+ /**
120
+ * A unique ID for the call
121
+ */
122
+ get uniqueid(): string;
123
+ /**
124
+ * The caller ID number (or “unknown”)
125
+ */
126
+ get callerid(): string;
127
+ /**
128
+ * The caller ID name (or “unknown”)
129
+ */
130
+ get calleridname(): string;
131
+ /**
132
+ * The presentation for the callerid in a ZAP channel
133
+ */
134
+ get callingpres(): string;
135
+ /**
136
+ * The number which is defined in ANI2 see Asterisk Detailed Variable List (only for PRI Channels)
137
+ */
138
+ get callingani2(): string;
139
+ /**
140
+ * The type of number used in PRI Channels see Asterisk Detailed Variable List
141
+ */
142
+ get callington(): string;
143
+ /**
144
+ * An optional 4 digit number (Transit Network Selector) used in PRI Channels see Asterisk Detailed Variable List
145
+ */
146
+ get callingtns(): string;
147
+ /**
148
+ * The dialed number id (or “unknown”)
149
+ */
150
+ get dnid(): string;
151
+ /**
152
+ * The referring DNIS number (or “unknown”)
153
+ */
154
+ get rdnis(): string;
155
+ /**
156
+ * Origin context in extensions.conf
157
+ */
158
+ get context(): string;
159
+ /**
160
+ * The called number
161
+ */
162
+ get extension(): string;
163
+ /**
164
+ * The priority it was executed as in the dial plan
165
+ */
166
+ get priority(): string;
167
+ /**
168
+ * The flag value is 1.0 if started as an EAGI script, 0.0 otherwise
169
+ */
170
+ get enhanced(): string;
171
+ /**
172
+ * Account code of the origin channel
173
+ */
174
+ get accountcode(): string;
175
+ /**
176
+ * Thread ID of the AGI script
177
+ */
178
+ get threadid(): string;
179
+ /**
180
+ * Answers channel if not already in answer state.
181
+ */
182
+ answer(): Promise<void>;
183
+ /**
184
+ * Interrupts expected flow of Async AGI commands and returns control to
185
+ * previous source (typically, the PBX dialplan).
186
+ */
187
+ break(): Promise<void>;
188
+ /**
189
+ * Returns status of the connected channel.
190
+ * @param channel
191
+ */
192
+ channelStatus(channel?: string): Promise<ChannelState>;
193
+ /**
194
+ * Sends audio file on channel and allows the listener to control the stream.
195
+ * @param filename
196
+ * @param escapeDigits
197
+ * @param skipms
198
+ * @param fastForwardCharacter
199
+ * @param rewindCharacter
200
+ * @param pauseCharacter
201
+ */
202
+ controlStreamFile(filename: string, escapeDigits?: string, skipms?: number, fastForwardCharacter?: string, rewindCharacter?: string, pauseCharacter?: string): Promise<{
203
+ digit: string;
204
+ playbackStatus: PlaybackStatus;
205
+ playbackOffset: number;
206
+ }>;
207
+ /**
208
+ * Attempts to establish a new outgoing connection on a channel, and then link it to the calling input channel.
209
+ * @param target
210
+ * @param timeout
211
+ * @param params
212
+ */
213
+ dial(target: string, timeout?: number, params?: string): Promise<DialStatus>;
214
+ /**
215
+ * Deletes an entry in the Asterisk database for a given family and key.
216
+ * @param family
217
+ * @param key
218
+ */
219
+ databaseDel(family: string, key: string): Promise<void>;
220
+ /**
221
+ * Deletes a family or specific keytree within a family in the Asterisk database.
222
+ * @param family
223
+ * @param keyTree
224
+ */
225
+ databaseDelTree(family: string, keyTree?: string): Promise<boolean>;
226
+ /**
227
+ * Retrieves an entry in the Asterisk database for a given family and key.
228
+ * @param family
229
+ * @param key
230
+ */
231
+ databaseGet(family: string, key: string): Promise<string>;
232
+ /**
233
+ * Adds or updates an entry in the Asterisk database for a given family, key, and value.
234
+ * @param family
235
+ * @param key
236
+ * @param value
237
+ */
238
+ databasePut(family: string, key: string, value: string): Promise<string>;
239
+ /**
240
+ * Executes application with given options
241
+ * @param application.
242
+ * @param args
243
+ */
244
+ exec(application: string, ...args: string[]): Promise<number>;
245
+ /**
246
+ * Stream the given file, and receive DTMF data.
247
+ * @param soundFile
248
+ * @param timeout
249
+ * @param maxDigits
250
+ */
251
+ getData(soundFile: string, timeout?: number, maxDigits?: number): Promise<{
252
+ digits: string;
253
+ timeout: boolean;
254
+ }>;
255
+ /**
256
+ * Evaluates a channel expression
257
+ * Understands complex variable names and builtin variables, unlike GET VARIABLE.
258
+ * @param key
259
+ * @param channel
260
+ */
261
+ getFullVariable(key: string, channel?: string): Promise<string>;
262
+ /**
263
+ * Stream file, prompt for DTMF, with timeout.
264
+ * Behaves similar to STREAM FILE but used with a timeout option.
265
+ * @param soundFile
266
+ * @param escapeDigits
267
+ * @param timeout
268
+ */
269
+ getOption(soundFile: string, escapeDigits?: string, timeout?: number): Promise<{
270
+ digit: string;
271
+ endpos: number;
272
+ }>;
273
+ /**
274
+ * Gets a channel variable.
275
+ * @param key
276
+ */
277
+ getVariable(key: string): Promise<string>;
278
+ /**
279
+ * Cause the channel to execute the specified dialplan subroutine.
280
+ * @param context
281
+ * @param extension
282
+ * @param priority
283
+ * @param argument
284
+ */
285
+ goSub(context: string, extension: string, priority: number, argument?: string): Promise<void>;
286
+ /**
287
+ * Hangs up the specified channel. If no channel name is given, hangs up the current channel
288
+ * @param channel
289
+ */
290
+ hangup(channel?: string): Promise<void>;
291
+ /**
292
+ * Does nothing
293
+ */
294
+ noop(): Promise<void>;
295
+ /**
296
+ * Receives one character from channels supporting it.
297
+ * @param timeout
298
+ */
299
+ receiveChar(timeout?: number): Promise<{
300
+ char: string;
301
+ timeout: boolean;
302
+ }>;
303
+ /**
304
+ * Receives text from channels supporting it.
305
+ * @param timeout
306
+ */
307
+ receiveText(timeout?: number): Promise<string>;
308
+ /**
309
+ * Records to a given file.
310
+ * @param filename
311
+ * @param fileFormat
312
+ * @param escapeDigits
313
+ * @param timeout
314
+ * @param beep
315
+ * @param silence
316
+ * @param offsetSamples
317
+ */
318
+ recordFile(filename: string, fileFormat?: string, escapeDigits?: string, timeout?: number, beep?: boolean, silence?: number, offsetSamples?: number): Promise<{
319
+ digit: string;
320
+ endpos: number;
321
+ timeout: boolean;
322
+ }>;
323
+ /**
324
+ * Says a given character string.
325
+ * @param value
326
+ * @param escapeDigits
327
+ */
328
+ sayAlpha(value: string, escapeDigits?: string): Promise<string>;
329
+ /**
330
+ * Says a given date.
331
+ * @param value
332
+ * @param escapeDigits
333
+ */
334
+ sayDate(value: Date | number, escapeDigits?: string): Promise<string>;
335
+ /**
336
+ * Says a given time as specified by the format given.
337
+ * @param value
338
+ * @param escapeDigits
339
+ * @param dateFormat
340
+ * @param timezone
341
+ */
342
+ sayDateTime(value: Date | number, escapeDigits?: string, dateFormat?: string, timezone?: string): Promise<string>;
343
+ /**
344
+ * Says a given digit string.
345
+ * @param value
346
+ * @param escapeDigits
347
+ */
348
+ sayDigits(value: string, escapeDigits?: string): Promise<string>;
349
+ /**
350
+ * Says a given number.
351
+ * @param value
352
+ * @param escapeDigits
353
+ */
354
+ sayNumber(value: number, escapeDigits?: string): Promise<string>;
355
+ /**
356
+ * Says a given character string with phonetics.
357
+ * @param value
358
+ * @param escapeDigits
359
+ */
360
+ sayPhonetic(value: string, escapeDigits?: string): Promise<string>;
361
+ /**
362
+ * Says a given time.
363
+ * @param value
364
+ * @param escapeDigits
365
+ */
366
+ sayTime(value: Date | number, escapeDigits?: string): Promise<string>;
367
+ /**
368
+ * Sends images to channels supporting it.
369
+ * @param image
370
+ */
371
+ sendImage(image: string): Promise<void>;
372
+ /**
373
+ * Sends text to channels supporting it.
374
+ * @param text
375
+ */
376
+ sendText(text: string): Promise<void>;
377
+ /**
378
+ * Autohangup channel in some time.
379
+ * @param timeout
380
+ */
381
+ setAutoHangup(timeout?: number): Promise<void>;
382
+ /**
383
+ * Sets callerid for the current channel.
384
+ * @param callerNumber
385
+ * @param callerName
386
+ */
387
+ setCallerID(callerNumber: number, callerName?: string): Promise<void>;
388
+ /**
389
+ * Sets channel context.
390
+ * @param context
391
+ */
392
+ setContext(context: string): Promise<void>;
393
+ /**
394
+ * Changes channel extension.
395
+ * @param extension
396
+ */
397
+ setExtension(extension: string): Promise<void>;
398
+ /**
399
+ * Enable/Disable Music on hold generator
400
+ * @param status
401
+ * @param musicClass
402
+ */
403
+ setMusic(status?: boolean, musicClass?: string): Promise<void>;
404
+ /**
405
+ * Set channel dialplan priority.
406
+ * @param priority
407
+ */
408
+ setPriority(priority: number): Promise<void>;
409
+ /**
410
+ * Set channel dialplan priority.
411
+ * @param key
412
+ * @param value
413
+ */
414
+ setVariable(key: string, value: string): Promise<void>;
415
+ speechActivateGrammar(grammar: string): Promise<IResponse>;
416
+ speechCreate(engine: string): Promise<IResponse>;
417
+ speechDeactivateGrammar(grammar: string): Promise<IResponse>;
418
+ speechDestroy(): Promise<IResponse>;
419
+ speechLoadGrammar(grammar: string, path: string): Promise<IResponse>;
420
+ speechRecognize(soundFile: string, timeout: number | undefined, offset: number): Promise<IResponse>;
421
+ speechSet(key: string, value: string): Promise<IResponse>;
422
+ speedUnloadGrammar(grammar: string): Promise<IResponse>;
423
+ /**
424
+ * Sends audio file on channel.
425
+ * @param filename
426
+ * @param escapeDigits
427
+ * @param offset
428
+ */
429
+ streamFile(filename: string, escapeDigits?: string, offset?: number): Promise<{
430
+ digit: string;
431
+ endpos: number;
432
+ }>;
433
+ /**
434
+ * Toggles TDD mode (for the deaf).
435
+ * @param status
436
+ */
437
+ tddMode(status: boolean): Promise<void>;
438
+ /**
439
+ * Logs a message to the asterisk verbose log.
440
+ * @param message
441
+ * @param level
442
+ */
443
+ verbose(message: string, level?: number): Promise<void>;
444
+ /**
445
+ * Waits for a digit to be pressed.
446
+ * @param timeout
447
+ */
448
+ waitForDigit(timeout?: number): Promise<string>;
449
+ private close;
450
+ private read;
451
+ private handleVariable;
452
+ private readVariables;
453
+ private readResponse;
454
+ private readResponseLine;
455
+ private send;
456
+ private sendCommand;
457
+ }