@gibme/asterisk-gateway-interface 1.0.2 → 1.0.3

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/dist/channel.js CHANGED
@@ -1,1033 +1,1098 @@
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
- const events_1 = require("events");
19
- const util_1 = require("util");
20
- const types_1 = require("./types");
21
- const response_arguments_1 = __importDefault(require("./response_arguments"));
22
- /**
23
- * Represents an AGI Channel
24
- */
25
- class Channel extends events_1.EventEmitter {
26
- /**
27
- * Creates a new instance of a channel object
28
- * @param connection the AGI socket connection
29
- */
30
- constructor(connection) {
31
- super();
32
- this.m_message = '';
33
- this.m_network = '';
34
- this.m_network_script = '';
35
- this.m_request = '';
36
- this.m_channel = '';
37
- this.m_language = '';
38
- this.m_type = '';
39
- this.m_uniqueid = '';
40
- this.m_version = '';
41
- this.m_callerid = '';
42
- this.m_calleridname = '';
43
- this.m_callingpres = '';
44
- this.m_callingani2 = '';
45
- this.m_callington = '';
46
- this.m_callingtns = '';
47
- this.m_dnid = '';
48
- this.m_rdnis = '';
49
- this.m_context = '';
50
- this.m_extension = '';
51
- this.m_priority = '';
52
- this.m_enhanced = '';
53
- this.m_accountcode = '';
54
- this.m_threadid = '';
55
- this.setMaxListeners(10);
56
- this.m_connection = connection;
57
- this.m_state = types_1.ContextState.INIT;
58
- this.m_connection.on('data', (data) => this.read(data));
59
- this.m_connection.on('close', () => this.emit('close'));
60
- this.m_connection.on('error', (error) => this.emit('error', error));
61
- this.m_connection.on('timeout', () => this.emit('timeout'));
62
- this.on('hangup', () => this.close());
63
- }
64
- on(event, listener) {
65
- return super.on(event, listener);
66
- }
67
- /**
68
- * Whether this AGI request is over the network
69
- */
70
- get network() {
71
- return (this.m_network.toLowerCase() === 'yes');
72
- }
73
- /**
74
- * The network path included in the AGI request
75
- * ie. agi://127.0.0.1:3000/test
76
- * This value would return 'test'
77
- */
78
- get network_script() {
79
- return this.m_network_script;
80
- }
81
- /**
82
- * The version of Asterisk
83
- */
84
- get version() {
85
- return this.m_version;
86
- }
87
- /**
88
- * The filename of your script
89
- * ie. agi
90
- */
91
- get request() {
92
- return this.m_request;
93
- }
94
- /**
95
- * The originating channel (your phone)
96
- */
97
- get channel() {
98
- return this.m_channel;
99
- }
100
- /**
101
- * The language code (e.g. “en”)
102
- */
103
- get language() {
104
- return this.m_language;
105
- }
106
- /**
107
- * The originating channel type (e.g. “SIP” or “ZAP”)
108
- */
109
- get type() {
110
- return this.m_type;
111
- }
112
- /**
113
- * A unique ID for the call
114
- */
115
- get uniqueid() {
116
- return this.m_uniqueid;
117
- }
118
- /**
119
- * The caller ID number (or “unknown”)
120
- */
121
- get callerid() {
122
- return this.m_callerid;
123
- }
124
- /**
125
- * The caller ID name (or “unknown”)
126
- */
127
- get calleridname() {
128
- return this.m_calleridname;
129
- }
130
- /**
131
- * The presentation for the callerid in a ZAP channel
132
- */
133
- get callingpres() {
134
- return this.m_callingpres;
135
- }
136
- /**
137
- * The number which is defined in ANI2 see Asterisk Detailed Variable List (only for PRI Channels)
138
- */
139
- get callingani2() {
140
- return this.m_callingani2;
141
- }
142
- /**
143
- * The type of number used in PRI Channels see Asterisk Detailed Variable List
144
- */
145
- get callington() {
146
- return this.m_callington;
147
- }
148
- /**
149
- * An optional 4 digit number (Transit Network Selector) used in PRI Channels see Asterisk Detailed Variable List
150
- */
151
- get callingtns() {
152
- return this.m_callingtns;
153
- }
154
- /**
155
- * The dialed number id (or “unknown”)
156
- */
157
- get dnid() {
158
- return this.m_dnid;
159
- }
160
- /**
161
- * The referring DNIS number (or “unknown”)
162
- */
163
- get rdnis() {
164
- return this.m_rdnis;
165
- }
166
- /**
167
- * Origin context in extensions.conf
168
- */
169
- get context() {
170
- return this.m_context;
171
- }
172
- /**
173
- * The called number
174
- */
175
- get extension() {
176
- return this.m_extension;
177
- }
178
- /**
179
- * The priority it was executed as in the dial plan
180
- */
181
- get priority() {
182
- return this.m_priority;
183
- }
184
- /**
185
- * The flag value is 1.0 if started as an EAGI script, 0.0 otherwise
186
- */
187
- get enhanced() {
188
- return this.m_enhanced;
189
- }
190
- /**
191
- * Account code of the origin channel
192
- */
193
- get accountcode() {
194
- return this.m_accountcode;
195
- }
196
- /**
197
- * Thread ID of the AGI script
198
- */
199
- get threadid() {
200
- return this.m_threadid;
201
- }
202
- /**
203
- * Answers channel if not already in answer state.
204
- */
205
- answer() {
206
- return __awaiter(this, void 0, void 0, function* () {
207
- const response = yield this.sendCommand('ANSWER');
208
- if (response.code !== 200 || response.result !== 0) {
209
- throw new Error('Could not answer call');
210
- }
211
- });
212
- }
213
- /**
214
- * Interrupts expected flow of Async AGI commands and returns control to
215
- * previous source (typically, the PBX dialplan).
216
- */
217
- break() {
218
- return __awaiter(this, void 0, void 0, function* () {
219
- const response = yield this.sendCommand('ASYNCAGI BREAK');
220
- if (response.code !== 200 || response.result !== 0) {
221
- throw new Error('Could not interrupt processing');
222
- }
223
- return this.close();
224
- });
225
- }
226
- /**
227
- * Returns status of the connected channel.
228
- * @param channel
229
- */
230
- channelStatus(channel) {
231
- return __awaiter(this, void 0, void 0, function* () {
232
- const response = yield this.sendCommand((0, util_1.format)('CHANNEL STATUS %s', channel || ''));
233
- if (response.code !== 200 || response.result === -1) {
234
- throw new Error('Could not get channel status');
235
- }
236
- return response.result;
237
- });
238
- }
239
- /**
240
- * Sends audio file on channel and allows the listener to control the stream.
241
- * @param filename
242
- * @param escapeDigits
243
- * @param skipms
244
- * @param fastForwardCharacter
245
- * @param rewindCharacter
246
- * @param pauseCharacter
247
- */
248
- controlStreamFile(filename, escapeDigits = '', skipms, fastForwardCharacter, rewindCharacter, pauseCharacter) {
249
- return __awaiter(this, void 0, void 0, function* () {
250
- const response = yield this.sendCommand((0, util_1.format)('CONTROL STREAM FILE %s "%s" %s %s %s %s', filename, escapeDigits, skipms || '', fastForwardCharacter || '', rewindCharacter || '', pauseCharacter || ''));
251
- if (response.code !== 200 || response.result === -1) {
252
- throw new Error('Could not control stream file');
253
- }
254
- const playbackStatus = yield this.getVariable('CPLAYBACKSTATUS ');
255
- const playbackOffset = yield this.getVariable('CPLAYBACKOFFSET ');
256
- let status = types_1.PlaybackStatus.ERROR;
257
- switch (playbackStatus.toUpperCase()) {
258
- case 'SUCCESS':
259
- status = types_1.PlaybackStatus.SUCCESS;
260
- break;
261
- case 'USERSTOPPED':
262
- status = types_1.PlaybackStatus.USER_STOPPED;
263
- break;
264
- case 'REMOTESTOPPED':
265
- status = types_1.PlaybackStatus.REMOTE_STOPPED;
266
- break;
267
- }
268
- return {
269
- digit: response.arguments.char('result'),
270
- playbackStatus: status,
271
- playbackOffset: parseInt(playbackOffset, 10)
272
- };
273
- });
274
- }
275
- /**
276
- * Attempts to establish a new outgoing connection on a channel, and then link it to the calling input channel.
277
- * @param target
278
- * @param timeout
279
- * @param params
280
- */
281
- dial(target, timeout = 30, params) {
282
- return __awaiter(this, void 0, void 0, function* () {
283
- yield this.exec('Dial', (0, util_1.format)('%s,%s,%s', target, timeout, params || ''));
284
- const dialstatus = yield this.getVariable('DIALSTATUS');
285
- switch (dialstatus.toUpperCase()) {
286
- case 'ANSWER':
287
- return types_1.DialStatus.ANSWER;
288
- case 'BUSY':
289
- return types_1.DialStatus.BUSY;
290
- case 'NOANSWER':
291
- return types_1.DialStatus.NOANSWER;
292
- case 'CANCEL':
293
- return types_1.DialStatus.CANCEL;
294
- case 'CONGESTION':
295
- return types_1.DialStatus.CONGESTION;
296
- case 'CHANUNAVAIL':
297
- return types_1.DialStatus.CHANUNAVAIL;
298
- case 'DONTCALL':
299
- return types_1.DialStatus.DONTCALL;
300
- case 'TORTURE':
301
- return types_1.DialStatus.TORTURE;
302
- case 'INVALIDARGS':
303
- return types_1.DialStatus.INVALIDARGS;
304
- default:
305
- throw new Error('Unknown dial status');
306
- }
307
- });
308
- }
309
- /**
310
- * Deletes an entry in the Asterisk database for a given family and key.
311
- * @param family
312
- * @param key
313
- */
314
- databaseDel(family, key) {
315
- return __awaiter(this, void 0, void 0, function* () {
316
- const response = yield this.sendCommand((0, util_1.format)('DATABASE DEL %s %s', family, key));
317
- if (response.code !== 200 || response.result === 0) {
318
- throw new Error('Could not delete from the database');
319
- }
320
- });
321
- }
322
- /**
323
- * Deletes a family or specific keytree within a family in the Asterisk database.
324
- * @param family
325
- * @param keyTree
326
- */
327
- databaseDelTree(family, keyTree) {
328
- return __awaiter(this, void 0, void 0, function* () {
329
- const response = yield this.sendCommand((0, util_1.format)('DATABASE DELTREE %s %s', family, keyTree || ''));
330
- if (response.code !== 200) {
331
- throw new Error('Could not delete tree from database');
332
- }
333
- return (response.result === 0);
334
- });
335
- }
336
- /**
337
- * Retrieves an entry in the Asterisk database for a given family and key.
338
- * @param family
339
- * @param key
340
- */
341
- databaseGet(family, key) {
342
- return __awaiter(this, void 0, void 0, function* () {
343
- const response = yield this.sendCommand((0, util_1.format)('DATABASE GET %s %s', family, key));
344
- if (response.code !== 200 || response.result === 0) {
345
- throw new Error('Database key not set');
346
- }
347
- return response.arguments.nokey();
348
- });
349
- }
350
- /**
351
- * Adds or updates an entry in the Asterisk database for a given family, key, and value.
352
- * @param family
353
- * @param key
354
- * @param value
355
- */
356
- databasePut(family, key, value) {
357
- return __awaiter(this, void 0, void 0, function* () {
358
- const response = yield this.sendCommand((0, util_1.format)('DATABASE PUT %s %s %s', family, key, value));
359
- if (response.code !== 200 || response.result === 0) {
360
- throw new Error('Database key not set');
361
- }
362
- return response.arguments.string('value');
363
- });
364
- }
365
- /**
366
- * Executes application with given options
367
- * @param application.
368
- * @param args
369
- */
370
- exec(application, ...args) {
371
- return __awaiter(this, void 0, void 0, function* () {
372
- const response = yield this.sendCommand((0, util_1.format)('EXEC %s %s', application, args.join(' ')));
373
- if (response.code !== 200 || response.result === -2) {
374
- throw new Error('Could not execute application');
375
- }
376
- return response.result;
377
- });
378
- }
379
- /**
380
- * Stream the given file, and receive DTMF data.
381
- * @param soundFile
382
- * @param timeout
383
- * @param maxDigits
384
- */
385
- getData(soundFile, timeout = 5, maxDigits) {
386
- return __awaiter(this, void 0, void 0, function* () {
387
- const response = yield this.sendCommand((0, util_1.format)('GET DATA %s %s %s', soundFile, timeout * 1000, maxDigits || ''));
388
- if (response.code !== 200 || response.result === -1) {
389
- throw new Error('Could not get data from channel');
390
- }
391
- return {
392
- digits: response.arguments.string('result'),
393
- timeout: (response.arguments.string('value') === '(timeout)')
394
- };
395
- });
396
- }
397
- /**
398
- * Evaluates a channel expression
399
- * Understands complex variable names and builtin variables, unlike GET VARIABLE.
400
- * @param key
401
- * @param channel
402
- */
403
- getFullVariable(key, channel) {
404
- return __awaiter(this, void 0, void 0, function* () {
405
- const response = yield this.sendCommand((0, util_1.format)('GET FULL VARIABLE %s %s', key.toUpperCase(), channel || ''));
406
- if (response.code !== 200 || response.result === 0) {
407
- throw new Error('Variable not set');
408
- }
409
- return response.arguments.nokey();
410
- });
411
- }
412
- /**
413
- * Stream file, prompt for DTMF, with timeout.
414
- * Behaves similar to STREAM FILE but used with a timeout option.
415
- * @param soundFile
416
- * @param escapeDigits
417
- * @param timeout
418
- */
419
- getOption(soundFile, escapeDigits = '#', timeout = 5) {
420
- return __awaiter(this, void 0, void 0, function* () {
421
- const response = yield this.sendCommand((0, util_1.format)('GET OPTION %s "%s" %s', soundFile, escapeDigits, timeout * 1000));
422
- if (response.code !== 200 || response.result === -1) {
423
- throw new Error('Could not get option');
424
- }
425
- if (response.arguments.number('endpos') === 0) {
426
- throw new Error('Could Not play file');
427
- }
428
- return {
429
- digit: response.arguments.char('result'),
430
- endpos: response.arguments.number('endpos')
431
- };
432
- });
433
- }
434
- /**
435
- * Gets a channel variable.
436
- * @param key
437
- */
438
- getVariable(key) {
439
- return __awaiter(this, void 0, void 0, function* () {
440
- const response = yield this.sendCommand((0, util_1.format)('GET VARIABLE %s', key.toUpperCase()));
441
- if (response.code !== 200 || response.result === 0) {
442
- throw new Error('Variable not set');
443
- }
444
- return response.arguments.nokey();
445
- });
446
- }
447
- /**
448
- * Cause the channel to execute the specified dialplan subroutine.
449
- * @param context
450
- * @param extension
451
- * @param priority
452
- * @param argument
453
- */
454
- goSub(context, extension, priority, argument) {
455
- return __awaiter(this, void 0, void 0, function* () {
456
- const response = yield this.sendCommand((0, util_1.format)('GOSUB %s %s %s %s', context, extension, priority, argument || ''));
457
- if (response.code !== 200 || response.result !== 0) {
458
- throw new Error('Could not execute gosub');
459
- }
460
- });
461
- }
462
- /**
463
- * Hangs up the specified channel. If no channel name is given, hangs up the current channel
464
- * @param channel
465
- */
466
- hangup(channel) {
467
- return __awaiter(this, void 0, void 0, function* () {
468
- const response = yield this.sendCommand((0, util_1.format)('HANGUP %s', channel || ''));
469
- if (response.code !== 200 || response.result !== 1) {
470
- throw new Error('Could not hang up call');
471
- }
472
- });
473
- }
474
- /**
475
- * Does nothing
476
- */
477
- noop() {
478
- return __awaiter(this, void 0, void 0, function* () {
479
- const response = yield this.sendCommand('NOOP');
480
- if (response.code !== 200 || response.result !== 0) {
481
- throw new Error('Could not NOOP');
482
- }
483
- });
484
- }
485
- /**
486
- * Receives one character from channels supporting it.
487
- * @param timeout
488
- */
489
- receiveChar(timeout = 5) {
490
- return __awaiter(this, void 0, void 0, function* () {
491
- const response = yield this.sendCommand((0, util_1.format)('RECEIVE CHAR %s', timeout * 1000));
492
- if (response.code !== 200 || response.result === -1) {
493
- throw new Error('Could not get data from channel');
494
- }
495
- return {
496
- char: response.arguments.char('result'),
497
- timeout: response.arguments.boolean('timeout')
498
- };
499
- });
500
- }
501
- /**
502
- * Receives text from channels supporting it.
503
- * @param timeout
504
- */
505
- receiveText(timeout = 5) {
506
- return __awaiter(this, void 0, void 0, function* () {
507
- const response = yield this.sendCommand((0, util_1.format)('RECEIVE TEXT %s', timeout * 1000));
508
- if (response.code !== 200 || response.result === -1) {
509
- throw new Error('Could not get data from channel');
510
- }
511
- return response.arguments.string('result');
512
- });
513
- }
514
- /**
515
- * Records to a given file.
516
- * @param filename
517
- * @param fileFormat
518
- * @param escapeDigits
519
- * @param timeout
520
- * @param beep
521
- * @param silence
522
- * @param offsetSamples
523
- */
524
- recordFile(filename, fileFormat = 'gsm', escapeDigits = '#', timeout = 10, beep, silence, offsetSamples) {
525
- return __awaiter(this, void 0, void 0, function* () {
526
- const response = yield this.sendCommand((0, util_1.format)('RECORD FILE %s %s "%s" %s %s %s %s', filename, fileFormat, escapeDigits, timeout * 1000, offsetSamples || '', (beep) ? 'BEEP' : '', (silence) ? (0, util_1.format)('s=%s', silence) : ''));
527
- if (response.code !== 200 || response.result === -1) {
528
- throw new Error('Could not record file');
529
- }
530
- return {
531
- digit: response.arguments.char('result'),
532
- endpos: response.arguments.number('endpos'),
533
- timeout: response.arguments.boolean('timeout')
534
- };
535
- });
536
- }
537
- /**
538
- * Says a given character string.
539
- * @param value
540
- * @param escapeDigits
541
- */
542
- sayAlpha(value, escapeDigits = '#') {
543
- return __awaiter(this, void 0, void 0, function* () {
544
- const response = yield this.sendCommand((0, util_1.format)('SAY ALPHA %s "%s"', value, escapeDigits));
545
- if (response.code !== 200 || response.result === -1) {
546
- throw new Error('Could not say alpha');
547
- }
548
- return response.arguments.char('result');
549
- });
550
- }
551
- /**
552
- * Says a given date.
553
- * @param value
554
- * @param escapeDigits
555
- */
556
- sayDate(value, escapeDigits = '#') {
557
- return __awaiter(this, void 0, void 0, function* () {
558
- const response = yield this.sendCommand((0, util_1.format)('SAY DATE %s "%s"', (typeof value === 'number') ? value : Math.floor(value.getTime() / 1000), escapeDigits));
559
- if (response.code !== 200 || response.result === -1) {
560
- throw new Error('Could not say date');
561
- }
562
- return response.arguments.char('result');
563
- });
564
- }
565
- /**
566
- * Says a given time as specified by the format given.
567
- * @param value
568
- * @param escapeDigits
569
- * @param dateFormat
570
- * @param timezone
571
- */
572
- sayDateTime(value, escapeDigits = '#', dateFormat, timezone) {
573
- return __awaiter(this, void 0, void 0, function* () {
574
- const response = yield this.sendCommand((0, util_1.format)('SAY DATETIME %s "%s" %s %s', (typeof value === 'number') ? value : Math.floor(value.getTime() / 1000), escapeDigits, dateFormat || '', timezone || ''));
575
- if (response.code !== 200 || response.result === -1) {
576
- throw new Error('Could not say date time');
577
- }
578
- return response.arguments.char('result');
579
- });
580
- }
581
- /**
582
- * Says a given digit string.
583
- * @param value
584
- * @param escapeDigits
585
- */
586
- sayDigits(value, escapeDigits = '#') {
587
- return __awaiter(this, void 0, void 0, function* () {
588
- const response = yield this.sendCommand((0, util_1.format)('SAY DIGITS %s "%s"', value, escapeDigits));
589
- if (response.code !== 200 || response.result === -1) {
590
- throw new Error('Could not say digits');
591
- }
592
- return response.arguments.char('result');
593
- });
594
- }
595
- /**
596
- * Says a given number.
597
- * @param value
598
- * @param escapeDigits
599
- */
600
- sayNumber(value, escapeDigits = '#') {
601
- return __awaiter(this, void 0, void 0, function* () {
602
- const response = yield this.sendCommand((0, util_1.format)('SAY NUMBER %s "%s"', value, escapeDigits));
603
- if (response.code !== 200 || response.result === -1) {
604
- throw new Error('Could not say number');
605
- }
606
- return response.arguments.char('result');
607
- });
608
- }
609
- /**
610
- * Says a given character string with phonetics.
611
- * @param value
612
- * @param escapeDigits
613
- */
614
- sayPhonetic(value, escapeDigits = '#') {
615
- return __awaiter(this, void 0, void 0, function* () {
616
- const response = yield this.sendCommand((0, util_1.format)('SAY PHONETIC %s "%s"', value, escapeDigits));
617
- if (response.code !== 200 || response.result === -1) {
618
- throw new Error('Could not say phonetic');
619
- }
620
- return response.arguments.char('result');
621
- });
622
- }
623
- /**
624
- * Says a given time.
625
- * @param value
626
- * @param escapeDigits
627
- */
628
- sayTime(value, escapeDigits = '#') {
629
- return __awaiter(this, void 0, void 0, function* () {
630
- const response = yield this.sendCommand((0, util_1.format)('SAY TIME %s "%s"', (typeof value === 'number') ? value : Math.floor(value.getTime() / 1000), escapeDigits));
631
- if (response.code !== 200 || response.result === -1) {
632
- throw new Error('Could not say time');
633
- }
634
- return response.arguments.char('result');
635
- });
636
- }
637
- /**
638
- * Sends images to channels supporting it.
639
- * @param image
640
- */
641
- sendImage(image) {
642
- return __awaiter(this, void 0, void 0, function* () {
643
- const response = yield this.sendCommand((0, util_1.format)('SEND IMAGE %s', image));
644
- if (response.code !== 200 || response.result !== 0) {
645
- throw new Error('Could not send image');
646
- }
647
- });
648
- }
649
- /**
650
- * Sends text to channels supporting it.
651
- * @param text
652
- */
653
- sendText(text) {
654
- return __awaiter(this, void 0, void 0, function* () {
655
- const response = yield this.sendCommand((0, util_1.format)('SEND TEXT "%s"', text));
656
- if (response.code !== 200 || response.result !== 0) {
657
- throw new Error('Could not send text');
658
- }
659
- });
660
- }
661
- /**
662
- * Autohangup channel in some time.
663
- * @param timeout
664
- */
665
- setAutoHangup(timeout = 60) {
666
- return __awaiter(this, void 0, void 0, function* () {
667
- const response = yield this.sendCommand((0, util_1.format)('SET AUTOHANGUP %s', timeout));
668
- if (response.code !== 200 || response.result !== 0) {
669
- throw new Error('Could not set auto hangup');
670
- }
671
- });
672
- }
673
- /**
674
- * Sets callerid for the current channel.
675
- * @param callerNumber
676
- * @param callerName
677
- */
678
- setCallerID(callerNumber, callerName) {
679
- return __awaiter(this, void 0, void 0, function* () {
680
- const callerid = (callerName)
681
- ? (0, util_1.format)('"%s"<%s>', callerName, callerNumber)
682
- : callerNumber;
683
- const response = yield this.sendCommand((0, util_1.format)('SET CALLERID %s', callerid));
684
- if (response.code !== 200 || response.result !== 1) {
685
- throw new Error('Could not set caller id');
686
- }
687
- });
688
- }
689
- /**
690
- * Sets channel context.
691
- * @param context
692
- */
693
- setContext(context) {
694
- return __awaiter(this, void 0, void 0, function* () {
695
- const response = yield this.sendCommand((0, util_1.format)('SET CONTEXT %s', context));
696
- if (response.code !== 200 || response.result !== 0) {
697
- throw new Error('Could not set context');
698
- }
699
- });
700
- }
701
- /**
702
- * Changes channel extension.
703
- * @param extension
704
- */
705
- setExtension(extension) {
706
- return __awaiter(this, void 0, void 0, function* () {
707
- const response = yield this.sendCommand((0, util_1.format)('SET EXTENSION %s', extension));
708
- if (response.code !== 200 || response.result !== 0) {
709
- throw new Error('Could not set extension');
710
- }
711
- });
712
- }
713
- /**
714
- * Enable/Disable Music on hold generator
715
- * @param status
716
- * @param musicClass
717
- */
718
- setMusic(status = true, musicClass) {
719
- return __awaiter(this, void 0, void 0, function* () {
720
- const response = yield this.sendCommand((0, util_1.format)('SET MUSIC %s %s', (status) ? 'ON' : 'OFF', musicClass || ''));
721
- if (response.code !== 200 || response.result !== 0) {
722
- throw new Error('Could not set priority');
723
- }
724
- });
725
- }
726
- /**
727
- * Set channel dialplan priority.
728
- * @param priority
729
- */
730
- setPriority(priority) {
731
- return __awaiter(this, void 0, void 0, function* () {
732
- const response = yield this.sendCommand((0, util_1.format)('SET PRIORITY %s', priority));
733
- if (response.code !== 200 || response.result !== 0) {
734
- throw new Error('Could not set priority');
735
- }
736
- });
737
- }
738
- /**
739
- * Set channel dialplan priority.
740
- * @param key
741
- * @param value
742
- */
743
- setVariable(key, value) {
744
- return __awaiter(this, void 0, void 0, function* () {
745
- const response = yield this.sendCommand((0, util_1.format)('SET VARIABLE %s "%s"', key.toUpperCase(), value));
746
- if (response.code !== 200 || response.result !== 1) {
747
- throw new Error('Could not set variable');
748
- }
749
- });
750
- }
751
- speechActivateGrammar(grammar) {
752
- return __awaiter(this, void 0, void 0, function* () {
753
- // TODO: Handle the response
754
- return this.sendCommand((0, util_1.format)('SPEECH ACTIVATE GRAMMAR %s', grammar));
755
- });
756
- }
757
- speechCreate(engine) {
758
- return __awaiter(this, void 0, void 0, function* () {
759
- // TODO: Handle the response
760
- return this.sendCommand((0, util_1.format)('SPEECH CREATE ENGINE %s', engine));
761
- });
762
- }
763
- speechDeactivateGrammar(grammar) {
764
- return __awaiter(this, void 0, void 0, function* () {
765
- // TODO: Handle the response
766
- return this.sendCommand((0, util_1.format)('SPEECH DEACTIVATE GRAMMAR %s', grammar));
767
- });
768
- }
769
- speechDestroy() {
770
- return __awaiter(this, void 0, void 0, function* () {
771
- // TODO: Handle the response
772
- return this.sendCommand('SPEECH DESTROY');
773
- });
774
- }
775
- speechLoadGrammar(grammar, path) {
776
- return __awaiter(this, void 0, void 0, function* () {
777
- // TODO: Handle the response
778
- return this.sendCommand((0, util_1.format)('SPEECH LOAD GRAMMAR %s %s', grammar, path));
779
- });
780
- }
781
- speechRecognize(soundFile, timeout = 5, offset) {
782
- return __awaiter(this, void 0, void 0, function* () {
783
- // TODO: Handle the response
784
- return this.sendCommand((0, util_1.format)('SPEECH RECOGNIZE %s %s %s', soundFile, timeout * 1000, offset));
785
- });
786
- }
787
- speechSet(key, value) {
788
- return __awaiter(this, void 0, void 0, function* () {
789
- // TODO: Handle the response
790
- return this.sendCommand((0, util_1.format)('SPEECH SET %s %s', key, value));
791
- });
792
- }
793
- speedUnloadGrammar(grammar) {
794
- return __awaiter(this, void 0, void 0, function* () {
795
- // TODO: Handle the response
796
- return this.sendCommand((0, util_1.format)('SPEECH UNLOAD GRAMMAR %s', grammar));
797
- });
798
- }
799
- /**
800
- * Sends audio file on channel.
801
- * @param filename
802
- * @param escapeDigits
803
- * @param offset
804
- */
805
- streamFile(filename, escapeDigits = '#', offset) {
806
- return __awaiter(this, void 0, void 0, function* () {
807
- const response = yield this.sendCommand((0, util_1.format)('STREAM FILE %s "%s" %s', filename, escapeDigits, offset || ''));
808
- if (response.code !== 200 || response.result === -1) {
809
- throw new Error('Could not stream file');
810
- }
811
- const status = yield this.getVariable('PLAYBACKSTATUS ');
812
- if (status.toUpperCase() !== 'SUCCESS') {
813
- throw new Error('Could not stream file');
814
- }
815
- return {
816
- digit: response.arguments.char('result'),
817
- endpos: response.arguments.number('endpos')
818
- };
819
- });
820
- }
821
- /**
822
- * Toggles TDD mode (for the deaf).
823
- * @param status
824
- */
825
- tddMode(status) {
826
- return __awaiter(this, void 0, void 0, function* () {
827
- const response = yield this.sendCommand((0, util_1.format)('TDD MODE %s', (status) ? 'ON' : 'OFF'));
828
- if (response.code !== 200 || response.result !== 1) {
829
- throw new Error('Could not set TDD mode');
830
- }
831
- });
832
- }
833
- /**
834
- * Logs a message to the asterisk verbose log.
835
- * @param message
836
- * @param level
837
- */
838
- verbose(message, level) {
839
- return __awaiter(this, void 0, void 0, function* () {
840
- const response = yield this.sendCommand((0, util_1.format)('VERBOSE "%s" %s', message, level || ''));
841
- if (response.code !== 200 || response.result !== 1) {
842
- throw new Error('Could not send logging message');
843
- }
844
- });
845
- }
846
- /**
847
- * Waits for a digit to be pressed.
848
- * @param timeout
849
- */
850
- waitForDigit(timeout = 5) {
851
- return __awaiter(this, void 0, void 0, function* () {
852
- const response = yield this.sendCommand((0, util_1.format)('WAIT FOR DIGIT %s', timeout * 1000));
853
- if (response.code !== 200 || response.result === -1) {
854
- throw new Error('Could not wait for digit');
855
- }
856
- return response.arguments.char('result');
857
- });
858
- }
859
- /* Internal Methods */
860
- close() {
861
- this.m_connection.destroy();
862
- }
863
- read(data) {
864
- if (data.length === 0) {
865
- return;
866
- }
867
- this.m_message += data.toString();
868
- if (this.m_state === types_1.ContextState.INIT) {
869
- if (this.m_message.indexOf('\n\n') === -1) {
870
- return;
871
- }
872
- this.readVariables(this.m_message);
873
- }
874
- else if (this.m_state === types_1.ContextState.WAITING) {
875
- if (this.m_message.indexOf('\n') === -1) {
876
- return;
877
- }
878
- this.readResponse(this.m_message);
879
- }
880
- this.m_message = '';
881
- }
882
- handleVariable(id, value) {
883
- switch (id) {
884
- case 'network':
885
- this.m_network = value;
886
- break;
887
- case 'network_script':
888
- this.m_network_script = value;
889
- break;
890
- case 'request':
891
- this.m_request = value;
892
- break;
893
- case 'channel':
894
- this.m_channel = value;
895
- break;
896
- case 'language':
897
- this.m_language = value;
898
- break;
899
- case 'type':
900
- this.m_type = value;
901
- break;
902
- case 'uniqueid':
903
- this.m_uniqueid = value;
904
- break;
905
- case 'version':
906
- this.m_version = value;
907
- break;
908
- case 'callerid':
909
- this.m_callerid = value;
910
- break;
911
- case 'calleridname':
912
- this.m_calleridname = value;
913
- break;
914
- case 'callingpres':
915
- this.m_callingpres = value;
916
- break;
917
- case 'callingani2':
918
- this.m_callingani2 = value;
919
- break;
920
- case 'callington':
921
- this.m_callington = value;
922
- break;
923
- case 'callingtns':
924
- this.m_callingtns = value;
925
- break;
926
- case 'dnid':
927
- this.m_dnid = value;
928
- break;
929
- case 'rdnis':
930
- this.m_rdnis = value;
931
- break;
932
- case 'context':
933
- this.m_context = value;
934
- break;
935
- case 'extension':
936
- this.m_extension = value;
937
- break;
938
- case 'priority':
939
- this.m_priority = value;
940
- break;
941
- case 'enhanced':
942
- this.m_enhanced = value;
943
- break;
944
- case 'accountcode':
945
- this.m_accountcode = value;
946
- break;
947
- case 'threadid':
948
- this.m_threadid = value;
949
- break;
950
- default:
951
- }
952
- }
953
- readVariables(message) {
954
- message.split('\n')
955
- .forEach(line => {
956
- const split = line.split(':');
957
- const name = (split[0] || '').trim();
958
- const value = (split[1] || '').trim();
959
- const id = name.substring(4);
960
- this.handleVariable(id, value);
961
- });
962
- this.m_state = types_1.ContextState.WAITING;
963
- this.emit('ready');
964
- }
965
- readResponse(message) {
966
- const lines = message.split('\n');
967
- lines.map((line) => this.readResponseLine(line));
968
- }
969
- readResponseLine(line) {
970
- if (!line) {
971
- return;
972
- }
973
- this.emit('recv', line);
974
- const parsed = line.split(' ');
975
- if (!parsed || parsed[0] === 'HANGUP') {
976
- return this.emit('hangup');
977
- }
978
- const code = parseInt(parsed[0], 10);
979
- parsed.shift();
980
- const args = new response_arguments_1.default();
981
- for (const value of parsed) {
982
- if (value.indexOf('=') !== -1) {
983
- const parts = value.split('=', 2);
984
- const key = parts[0].trim();
985
- const val = parts[1].trim();
986
- args.addArgument(key, val);
987
- }
988
- else if (value.indexOf('(') !== -1) {
989
- const name = value.substring(1, value.length - 1);
990
- args.addArgument(name, true);
991
- }
992
- else {
993
- args.addArgument('value', value);
994
- }
995
- }
996
- const response = {
997
- code,
998
- result: args.number('result'),
999
- arguments: args
1000
- };
1001
- this.emit('response', response);
1002
- }
1003
- send(message) {
1004
- return __awaiter(this, void 0, void 0, function* () {
1005
- return new Promise((resolve, reject) => {
1006
- this.emit('send', message);
1007
- this.m_connection.write(message, (error) => {
1008
- if (error) {
1009
- return reject(error);
1010
- }
1011
- return resolve();
1012
- });
1013
- });
1014
- });
1015
- }
1016
- sendCommand(command) {
1017
- return __awaiter(this, void 0, void 0, function* () {
1018
- return new Promise((resolve, reject) => {
1019
- const handleResponse = (response) => {
1020
- this.removeListener('response', handleResponse);
1021
- return resolve(response);
1022
- };
1023
- this.once('response', handleResponse);
1024
- this.send((0, util_1.format)('%s\n', command.trim()))
1025
- .catch(error => {
1026
- this.removeListener('response', handleResponse);
1027
- return reject(error);
1028
- });
1029
- });
1030
- });
1031
- }
1032
- }
1033
- exports.default = Channel;
1
+ "use strict";
2
+ // Copyright (c) 2016-2022, Brandon Lehmann <brandonlehmann@gmail.com>
3
+ //
4
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ // of this software and associated documentation files (the "Software"), to deal
6
+ // in the Software without restriction, including without limitation the rights
7
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ // copies of the Software, and to permit persons to whom the Software is
9
+ // furnished to do so, subject to the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included in all
12
+ // copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ // SOFTWARE.
21
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
22
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
23
+ return new (P || (P = Promise))(function (resolve, reject) {
24
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
25
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
26
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
27
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
28
+ });
29
+ };
30
+ var __importDefault = (this && this.__importDefault) || function (mod) {
31
+ return (mod && mod.__esModule) ? mod : { "default": mod };
32
+ };
33
+ Object.defineProperty(exports, "__esModule", { value: true });
34
+ const events_1 = require("events");
35
+ const util_1 = require("util");
36
+ const types_1 = require("./types");
37
+ const response_arguments_1 = __importDefault(require("./response_arguments"));
38
+ /**
39
+ * Represents an AGI Channel
40
+ */
41
+ class Channel extends events_1.EventEmitter {
42
+ /**
43
+ * Creates a new instance of a channel object
44
+ * @param connection the AGI socket connection
45
+ */
46
+ constructor(connection) {
47
+ super();
48
+ this._message = '';
49
+ this._network = '';
50
+ this._network_script = '';
51
+ this._request = '';
52
+ this._channel = '';
53
+ this._language = '';
54
+ this._type = '';
55
+ this._uniqueid = '';
56
+ this._version = '';
57
+ this._callerid = '';
58
+ this._calleridname = '';
59
+ this._callingpres = '';
60
+ this._callingani2 = '';
61
+ this._callington = '';
62
+ this._callingtns = '';
63
+ this._dnid = '';
64
+ this._rdnis = '';
65
+ this._context = '';
66
+ this._extension = '';
67
+ this._priority = '';
68
+ this._enhanced = '';
69
+ this._accountcode = '';
70
+ this._threadid = '';
71
+ this.setMaxListeners(10);
72
+ this._connection = connection;
73
+ this._state = types_1.ContextState.INIT;
74
+ this._connection.on('data', (data) => this.read(data));
75
+ this._connection.on('close', () => this.emit('close'));
76
+ this._connection.on('error', (error) => this.emit('error', error));
77
+ this._connection.on('timeout', () => this.emit('timeout'));
78
+ this.on('hangup', () => this.close());
79
+ }
80
+ on(event, listener) {
81
+ return super.on(event, listener);
82
+ }
83
+ /**
84
+ * Whether this AGI request is over the network
85
+ */
86
+ get network() {
87
+ return (this._network.toLowerCase() === 'yes');
88
+ }
89
+ /**
90
+ * The network path included in the AGI request
91
+ * ie. agi://127.0.0.1:3000/test
92
+ * This value would return 'test'
93
+ */
94
+ get network_script() {
95
+ return this._network_script;
96
+ }
97
+ /**
98
+ * The version of Asterisk
99
+ */
100
+ get version() {
101
+ return this._version;
102
+ }
103
+ /**
104
+ * The filename of your script
105
+ * ie. agi
106
+ */
107
+ get request() {
108
+ return this._request;
109
+ }
110
+ /**
111
+ * The originating channel (your phone)
112
+ */
113
+ get channel() {
114
+ return this._channel;
115
+ }
116
+ /**
117
+ * The language code (e.g. “en”)
118
+ */
119
+ get language() {
120
+ return this._language;
121
+ }
122
+ /**
123
+ * The originating channel type (e.g. “SIP” or “ZAP”)
124
+ */
125
+ get type() {
126
+ return this._type;
127
+ }
128
+ /**
129
+ * A unique ID for the call
130
+ */
131
+ get uniqueid() {
132
+ return this._uniqueid;
133
+ }
134
+ /**
135
+ * The caller ID number (or “unknown”)
136
+ */
137
+ get callerid() {
138
+ return this._callerid;
139
+ }
140
+ /**
141
+ * The caller ID name (or “unknown”)
142
+ */
143
+ get calleridname() {
144
+ return this._calleridname;
145
+ }
146
+ /**
147
+ * The presentation for the callerid in a ZAP channel
148
+ */
149
+ get callingpres() {
150
+ return this._callingpres;
151
+ }
152
+ /**
153
+ * The number which is defined in ANI2 see Asterisk Detailed Variable List (only for PRI Channels)
154
+ */
155
+ get callingani2() {
156
+ return this._callingani2;
157
+ }
158
+ /**
159
+ * The type of number used in PRI Channels see Asterisk Detailed Variable List
160
+ */
161
+ get callington() {
162
+ return this._callington;
163
+ }
164
+ /**
165
+ * An optional 4 digit number (Transit Network Selector) used in PRI Channels see Asterisk Detailed Variable List
166
+ */
167
+ get callingtns() {
168
+ return this._callingtns;
169
+ }
170
+ /**
171
+ * The dialed number id (or “unknown”)
172
+ */
173
+ get dnid() {
174
+ return this._dnid;
175
+ }
176
+ /**
177
+ * The referring DNIS number (or “unknown”)
178
+ */
179
+ get rdnis() {
180
+ return this._rdnis;
181
+ }
182
+ /**
183
+ * Origin context in extensions.conf
184
+ */
185
+ get context() {
186
+ return this._context;
187
+ }
188
+ /**
189
+ * The called number
190
+ */
191
+ get extension() {
192
+ return this._extension;
193
+ }
194
+ /**
195
+ * The priority it was executed as in the dial plan
196
+ */
197
+ get priority() {
198
+ return this._priority;
199
+ }
200
+ /**
201
+ * The flag value is 1.0 if started as an EAGI script, 0.0 otherwise
202
+ */
203
+ get enhanced() {
204
+ return this._enhanced;
205
+ }
206
+ /**
207
+ * Account code of the origin channel
208
+ */
209
+ get accountcode() {
210
+ return this._accountcode;
211
+ }
212
+ /**
213
+ * Thread ID of the AGI script
214
+ */
215
+ get threadid() {
216
+ return this._threadid;
217
+ }
218
+ /**
219
+ * Answers channel if not already in answer state.
220
+ */
221
+ answer() {
222
+ return __awaiter(this, void 0, void 0, function* () {
223
+ const response = yield this.sendCommand('ANSWER');
224
+ if (response.code !== 200 || response.result !== 0) {
225
+ throw new Error('Could not answer call');
226
+ }
227
+ });
228
+ }
229
+ /**
230
+ * Interrupts expected flow of Async AGI commands and returns control to
231
+ * previous source (typically, the PBX dialplan).
232
+ */
233
+ break() {
234
+ return __awaiter(this, void 0, void 0, function* () {
235
+ const response = yield this.sendCommand('ASYNCAGI BREAK');
236
+ if (response.code !== 200 || response.result !== 0) {
237
+ throw new Error('Could not interrupt processing');
238
+ }
239
+ return this.close();
240
+ });
241
+ }
242
+ /**
243
+ * Returns status of the connected channel.
244
+ * @param channel
245
+ */
246
+ channelStatus(channel) {
247
+ return __awaiter(this, void 0, void 0, function* () {
248
+ const response = yield this.sendCommand((0, util_1.format)('CHANNEL STATUS %s', channel || ''));
249
+ if (response.code !== 200 || response.result === -1) {
250
+ throw new Error('Could not get channel status');
251
+ }
252
+ return response.result;
253
+ });
254
+ }
255
+ /**
256
+ * Sends audio file on channel and allows the listener to control the stream.
257
+ * @param filename
258
+ * @param escapeDigits
259
+ * @param skipms
260
+ * @param fastForwardCharacter
261
+ * @param rewindCharacter
262
+ * @param pauseCharacter
263
+ */
264
+ controlStreamFile(filename, escapeDigits = '', skipms, fastForwardCharacter, rewindCharacter, pauseCharacter) {
265
+ return __awaiter(this, void 0, void 0, function* () {
266
+ const response = yield this.sendCommand((0, util_1.format)('CONTROL STREAM FILE %s "%s" %s %s %s %s', filename, escapeDigits, skipms || '', fastForwardCharacter || '', rewindCharacter || '', pauseCharacter || ''));
267
+ if (response.code !== 200 || response.result === -1) {
268
+ throw new Error('Could not control stream file');
269
+ }
270
+ const playbackStatus = yield this.getVariable('CPLAYBACKSTATUS ');
271
+ const playbackOffset = yield this.getVariable('CPLAYBACKOFFSET ');
272
+ let status = types_1.PlaybackStatus.ERROR;
273
+ switch (playbackStatus.toUpperCase()) {
274
+ case 'SUCCESS':
275
+ status = types_1.PlaybackStatus.SUCCESS;
276
+ break;
277
+ case 'USERSTOPPED':
278
+ status = types_1.PlaybackStatus.USER_STOPPED;
279
+ break;
280
+ case 'REMOTESTOPPED':
281
+ status = types_1.PlaybackStatus.REMOTE_STOPPED;
282
+ break;
283
+ }
284
+ return {
285
+ digit: response.arguments.char('result'),
286
+ playbackStatus: status,
287
+ playbackOffset: parseInt(playbackOffset, 10)
288
+ };
289
+ });
290
+ }
291
+ /**
292
+ * Attempts to establish a new outgoing connection on a channel, and then link it to the calling input channel.
293
+ * @param target
294
+ * @param timeout
295
+ * @param params
296
+ */
297
+ dial(target, timeout = 30, params) {
298
+ return __awaiter(this, void 0, void 0, function* () {
299
+ yield this.exec('Dial', (0, util_1.format)('%s,%s,%s', target, timeout, params || ''));
300
+ const dialstatus = yield this.getVariable('DIALSTATUS');
301
+ switch (dialstatus.toUpperCase()) {
302
+ case 'ANSWER':
303
+ return types_1.DialStatus.ANSWER;
304
+ case 'BUSY':
305
+ return types_1.DialStatus.BUSY;
306
+ case 'NOANSWER':
307
+ return types_1.DialStatus.NOANSWER;
308
+ case 'CANCEL':
309
+ return types_1.DialStatus.CANCEL;
310
+ case 'CONGESTION':
311
+ return types_1.DialStatus.CONGESTION;
312
+ case 'CHANUNAVAIL':
313
+ return types_1.DialStatus.CHANUNAVAIL;
314
+ case 'DONTCALL':
315
+ return types_1.DialStatus.DONTCALL;
316
+ case 'TORTURE':
317
+ return types_1.DialStatus.TORTURE;
318
+ case 'INVALIDARGS':
319
+ return types_1.DialStatus.INVALIDARGS;
320
+ default:
321
+ throw new Error('Unknown dial status');
322
+ }
323
+ });
324
+ }
325
+ /**
326
+ * Deletes an entry in the Asterisk database for a given family and key.
327
+ * @param family
328
+ * @param key
329
+ */
330
+ databaseDel(family, key) {
331
+ return __awaiter(this, void 0, void 0, function* () {
332
+ const response = yield this.sendCommand((0, util_1.format)('DATABASE DEL %s %s', family, key));
333
+ if (response.code !== 200 || response.result === 0) {
334
+ throw new Error('Could not delete from the database');
335
+ }
336
+ });
337
+ }
338
+ /**
339
+ * Deletes a family or specific keytree within a family in the Asterisk database.
340
+ * @param family
341
+ * @param keyTree
342
+ */
343
+ databaseDelTree(family, keyTree) {
344
+ return __awaiter(this, void 0, void 0, function* () {
345
+ const response = yield this.sendCommand((0, util_1.format)('DATABASE DELTREE %s %s', family, keyTree || ''));
346
+ if (response.code !== 200) {
347
+ throw new Error('Could not delete tree from database');
348
+ }
349
+ return (response.result === 0);
350
+ });
351
+ }
352
+ /**
353
+ * Retrieves an entry in the Asterisk database for a given family and key.
354
+ * @param family
355
+ * @param key
356
+ */
357
+ databaseGet(family, key) {
358
+ return __awaiter(this, void 0, void 0, function* () {
359
+ const response = yield this.sendCommand((0, util_1.format)('DATABASE GET %s %s', family, key));
360
+ if (response.code !== 200 || response.result === 0) {
361
+ throw new Error('Database key not set');
362
+ }
363
+ return response.arguments.nokey();
364
+ });
365
+ }
366
+ /**
367
+ * Adds or updates an entry in the Asterisk database for a given family, key, and value.
368
+ * @param family
369
+ * @param key
370
+ * @param value
371
+ */
372
+ databasePut(family, key, value) {
373
+ return __awaiter(this, void 0, void 0, function* () {
374
+ const response = yield this.sendCommand((0, util_1.format)('DATABASE PUT %s %s %s', family, key, value));
375
+ if (response.code !== 200 || response.result === 0) {
376
+ throw new Error('Database key not set');
377
+ }
378
+ return response.arguments.string('value');
379
+ });
380
+ }
381
+ /**
382
+ * Executes application with given options
383
+ * @param application.
384
+ * @param args
385
+ */
386
+ exec(application, ...args) {
387
+ return __awaiter(this, void 0, void 0, function* () {
388
+ const response = yield this.sendCommand((0, util_1.format)('EXEC %s %s', application, args.join(' ')));
389
+ if (response.code !== 200 || response.result === -2) {
390
+ throw new Error('Could not execute application');
391
+ }
392
+ return response.result;
393
+ });
394
+ }
395
+ /**
396
+ * Stream the given file, and receive DTMF data.
397
+ * @param soundFile
398
+ * @param timeout
399
+ * @param maxDigits
400
+ */
401
+ getData(soundFile, timeout = 5, maxDigits) {
402
+ return __awaiter(this, void 0, void 0, function* () {
403
+ const response = yield this.sendCommand((0, util_1.format)('GET DATA %s %s %s', soundFile, timeout * 1000, maxDigits || ''));
404
+ if (response.code !== 200 || response.result === -1) {
405
+ throw new Error('Could not get data from channel');
406
+ }
407
+ return {
408
+ digits: response.arguments.string('result'),
409
+ timeout: (response.arguments.string('value') === '(timeout)')
410
+ };
411
+ });
412
+ }
413
+ /**
414
+ * Evaluates a channel expression
415
+ * Understands complex variable names and builtin variables, unlike GET VARIABLE.
416
+ * @param key
417
+ * @param channel
418
+ */
419
+ getFullVariable(key, channel) {
420
+ return __awaiter(this, void 0, void 0, function* () {
421
+ const response = yield this.sendCommand((0, util_1.format)('GET FULL VARIABLE %s %s', key.toUpperCase(), channel || ''));
422
+ if (response.code !== 200 || response.result === 0) {
423
+ throw new Error('Variable not set');
424
+ }
425
+ return response.arguments.nokey();
426
+ });
427
+ }
428
+ /**
429
+ * Stream file, prompt for DTMF, with timeout.
430
+ * Behaves similar to STREAM FILE but used with a timeout option.
431
+ * @param soundFile
432
+ * @param escapeDigits
433
+ * @param timeout
434
+ */
435
+ getOption(soundFile, escapeDigits = '#', timeout = 5) {
436
+ return __awaiter(this, void 0, void 0, function* () {
437
+ const response = yield this.sendCommand((0, util_1.format)('GET OPTION %s "%s" %s', soundFile, escapeDigits, timeout * 1000));
438
+ if (response.code !== 200 || response.result === -1) {
439
+ throw new Error('Could not get option');
440
+ }
441
+ if (response.arguments.number('endpos') === 0) {
442
+ throw new Error('Could Not play file');
443
+ }
444
+ return {
445
+ digit: response.arguments.char('result'),
446
+ endpos: response.arguments.number('endpos')
447
+ };
448
+ });
449
+ }
450
+ /**
451
+ * Gets a channel variable.
452
+ * @param key
453
+ */
454
+ getVariable(key) {
455
+ return __awaiter(this, void 0, void 0, function* () {
456
+ const response = yield this.sendCommand((0, util_1.format)('GET VARIABLE %s', key.toUpperCase()));
457
+ if (response.code !== 200 || response.result === 0) {
458
+ throw new Error('Variable not set');
459
+ }
460
+ return response.arguments.nokey();
461
+ });
462
+ }
463
+ /**
464
+ * Cause the channel to execute the specified dialplan subroutine.
465
+ * @param context
466
+ * @param extension
467
+ * @param priority
468
+ * @param argument
469
+ */
470
+ goSub(context, extension, priority, argument) {
471
+ return __awaiter(this, void 0, void 0, function* () {
472
+ const response = yield this.sendCommand((0, util_1.format)('GOSUB %s %s %s %s', context, extension, priority, argument || ''));
473
+ if (response.code !== 200 || response.result !== 0) {
474
+ throw new Error('Could not execute gosub');
475
+ }
476
+ });
477
+ }
478
+ /**
479
+ * Hangs up the specified channel. If no channel name is given, hangs up the current channel
480
+ * @param channel
481
+ */
482
+ hangup(channel) {
483
+ return __awaiter(this, void 0, void 0, function* () {
484
+ const response = yield this.sendCommand((0, util_1.format)('HANGUP %s', channel || ''));
485
+ if (response.code !== 200 || response.result !== 1) {
486
+ throw new Error('Could not hang up call');
487
+ }
488
+ });
489
+ }
490
+ /**
491
+ * Does nothing
492
+ */
493
+ noop() {
494
+ return __awaiter(this, void 0, void 0, function* () {
495
+ const response = yield this.sendCommand('NOOP');
496
+ if (response.code !== 200 || response.result !== 0) {
497
+ throw new Error('Could not NOOP');
498
+ }
499
+ });
500
+ }
501
+ /**
502
+ * Receives one character from channels supporting it.
503
+ * @param timeout
504
+ */
505
+ receiveChar(timeout = 5) {
506
+ return __awaiter(this, void 0, void 0, function* () {
507
+ const response = yield this.sendCommand((0, util_1.format)('RECEIVE CHAR %s', timeout * 1000));
508
+ if (response.code !== 200 || response.result === -1) {
509
+ throw new Error('Could not get data from channel');
510
+ }
511
+ return {
512
+ char: response.arguments.char('result'),
513
+ timeout: response.arguments.boolean('timeout')
514
+ };
515
+ });
516
+ }
517
+ /**
518
+ * Receives text from channels supporting it.
519
+ * @param timeout
520
+ */
521
+ receiveText(timeout = 5) {
522
+ return __awaiter(this, void 0, void 0, function* () {
523
+ const response = yield this.sendCommand((0, util_1.format)('RECEIVE TEXT %s', timeout * 1000));
524
+ if (response.code !== 200 || response.result === -1) {
525
+ throw new Error('Could not get data from channel');
526
+ }
527
+ return response.arguments.string('result');
528
+ });
529
+ }
530
+ /**
531
+ * Records to a given file.
532
+ * @param filename
533
+ * @param fileFormat
534
+ * @param escapeDigits
535
+ * @param timeout
536
+ * @param beep
537
+ * @param silence
538
+ * @param offsetSamples
539
+ */
540
+ recordFile(filename, fileFormat = 'gsm', escapeDigits = '#', timeout = 10, beep, silence, offsetSamples) {
541
+ return __awaiter(this, void 0, void 0, function* () {
542
+ const response = yield this.sendCommand((0, util_1.format)('RECORD FILE %s %s "%s" %s %s %s %s', filename, fileFormat, escapeDigits, timeout * 1000, offsetSamples || '', (beep) ? 'BEEP' : '', (silence) ? (0, util_1.format)('s=%s', silence) : ''));
543
+ if (response.code !== 200 || response.result === -1) {
544
+ throw new Error('Could not record file');
545
+ }
546
+ return {
547
+ digit: response.arguments.char('result'),
548
+ endpos: response.arguments.number('endpos'),
549
+ timeout: response.arguments.boolean('timeout')
550
+ };
551
+ });
552
+ }
553
+ /**
554
+ * Says a given character string.
555
+ * @param value
556
+ * @param escapeDigits
557
+ */
558
+ sayAlpha(value, escapeDigits = '#') {
559
+ return __awaiter(this, void 0, void 0, function* () {
560
+ const response = yield this.sendCommand((0, util_1.format)('SAY ALPHA %s "%s"', value, escapeDigits));
561
+ if (response.code !== 200 || response.result === -1) {
562
+ throw new Error('Could not say alpha');
563
+ }
564
+ return response.arguments.char('result');
565
+ });
566
+ }
567
+ /**
568
+ * Says a given date.
569
+ * @param value
570
+ * @param escapeDigits
571
+ */
572
+ sayDate(value, escapeDigits = '#') {
573
+ return __awaiter(this, void 0, void 0, function* () {
574
+ const response = yield this.sendCommand((0, util_1.format)('SAY DATE %s "%s"', (typeof value === 'number') ? value : Math.floor(value.getTime() / 1000), escapeDigits));
575
+ if (response.code !== 200 || response.result === -1) {
576
+ throw new Error('Could not say date');
577
+ }
578
+ return response.arguments.char('result');
579
+ });
580
+ }
581
+ /**
582
+ * Says a given time as specified by the format given.
583
+ * @param value
584
+ * @param escapeDigits
585
+ * @param dateFormat
586
+ * @param timezone
587
+ */
588
+ sayDateTime(value, escapeDigits = '#', dateFormat, timezone) {
589
+ return __awaiter(this, void 0, void 0, function* () {
590
+ const response = yield this.sendCommand((0, util_1.format)('SAY DATETIME %s "%s" %s %s', (typeof value === 'number') ? value : Math.floor(value.getTime() / 1000), escapeDigits, dateFormat || '', timezone || ''));
591
+ if (response.code !== 200 || response.result === -1) {
592
+ throw new Error('Could not say date time');
593
+ }
594
+ return response.arguments.char('result');
595
+ });
596
+ }
597
+ /**
598
+ * Says a given digit string.
599
+ * @param value
600
+ * @param escapeDigits
601
+ */
602
+ sayDigits(value, escapeDigits = '#') {
603
+ return __awaiter(this, void 0, void 0, function* () {
604
+ const response = yield this.sendCommand((0, util_1.format)('SAY DIGITS %s "%s"', value, escapeDigits));
605
+ if (response.code !== 200 || response.result === -1) {
606
+ throw new Error('Could not say digits');
607
+ }
608
+ return response.arguments.char('result');
609
+ });
610
+ }
611
+ /**
612
+ * Says a given number.
613
+ * @param value
614
+ * @param escapeDigits
615
+ */
616
+ sayNumber(value, escapeDigits = '#') {
617
+ return __awaiter(this, void 0, void 0, function* () {
618
+ const response = yield this.sendCommand((0, util_1.format)('SAY NUMBER %s "%s"', value, escapeDigits));
619
+ if (response.code !== 200 || response.result === -1) {
620
+ throw new Error('Could not say number');
621
+ }
622
+ return response.arguments.char('result');
623
+ });
624
+ }
625
+ /**
626
+ * Says a given character string with phonetics.
627
+ * @param value
628
+ * @param escapeDigits
629
+ */
630
+ sayPhonetic(value, escapeDigits = '#') {
631
+ return __awaiter(this, void 0, void 0, function* () {
632
+ const response = yield this.sendCommand((0, util_1.format)('SAY PHONETIC %s "%s"', value, escapeDigits));
633
+ if (response.code !== 200 || response.result === -1) {
634
+ throw new Error('Could not say phonetic');
635
+ }
636
+ return response.arguments.char('result');
637
+ });
638
+ }
639
+ /**
640
+ * Says a given time.
641
+ * @param value
642
+ * @param escapeDigits
643
+ */
644
+ sayTime(value, escapeDigits = '#') {
645
+ return __awaiter(this, void 0, void 0, function* () {
646
+ const response = yield this.sendCommand((0, util_1.format)('SAY TIME %s "%s"', (typeof value === 'number') ? value : Math.floor(value.getTime() / 1000), escapeDigits));
647
+ if (response.code !== 200 || response.result === -1) {
648
+ throw new Error('Could not say time');
649
+ }
650
+ return response.arguments.char('result');
651
+ });
652
+ }
653
+ /**
654
+ * Sends images to channels supporting it.
655
+ * @param image
656
+ */
657
+ sendImage(image) {
658
+ return __awaiter(this, void 0, void 0, function* () {
659
+ const response = yield this.sendCommand((0, util_1.format)('SEND IMAGE %s', image));
660
+ if (response.code !== 200 || response.result !== 0) {
661
+ throw new Error('Could not send image');
662
+ }
663
+ });
664
+ }
665
+ /**
666
+ * Sends text to channels supporting it.
667
+ * @param text
668
+ */
669
+ sendText(text) {
670
+ return __awaiter(this, void 0, void 0, function* () {
671
+ const response = yield this.sendCommand((0, util_1.format)('SEND TEXT "%s"', text));
672
+ if (response.code !== 200 || response.result !== 0) {
673
+ throw new Error('Could not send text');
674
+ }
675
+ });
676
+ }
677
+ /**
678
+ * Autohangup channel in some time.
679
+ * @param timeout
680
+ */
681
+ setAutoHangup(timeout = 60) {
682
+ return __awaiter(this, void 0, void 0, function* () {
683
+ const response = yield this.sendCommand((0, util_1.format)('SET AUTOHANGUP %s', timeout));
684
+ if (response.code !== 200 || response.result !== 0) {
685
+ throw new Error('Could not set auto hangup');
686
+ }
687
+ });
688
+ }
689
+ /**
690
+ * Sets callerid for the current channel.
691
+ * @param callerNumber
692
+ * @param callerName
693
+ */
694
+ setCallerID(callerNumber, callerName) {
695
+ return __awaiter(this, void 0, void 0, function* () {
696
+ const callerid = (callerName)
697
+ ? (0, util_1.format)('"%s"<%s>', callerName, callerNumber)
698
+ : callerNumber;
699
+ const response = yield this.sendCommand((0, util_1.format)('SET CALLERID %s', callerid));
700
+ if (response.code !== 200 || response.result !== 1) {
701
+ throw new Error('Could not set caller id');
702
+ }
703
+ });
704
+ }
705
+ /**
706
+ * Sets channel context.
707
+ * @param context
708
+ */
709
+ setContext(context) {
710
+ return __awaiter(this, void 0, void 0, function* () {
711
+ const response = yield this.sendCommand((0, util_1.format)('SET CONTEXT %s', context));
712
+ if (response.code !== 200 || response.result !== 0) {
713
+ throw new Error('Could not set context');
714
+ }
715
+ });
716
+ }
717
+ /**
718
+ * Changes channel extension.
719
+ * @param extension
720
+ */
721
+ setExtension(extension) {
722
+ return __awaiter(this, void 0, void 0, function* () {
723
+ const response = yield this.sendCommand((0, util_1.format)('SET EXTENSION %s', extension));
724
+ if (response.code !== 200 || response.result !== 0) {
725
+ throw new Error('Could not set extension');
726
+ }
727
+ });
728
+ }
729
+ /**
730
+ * Enable/Disable Music on hold generator
731
+ * @param status
732
+ * @param musicClass
733
+ */
734
+ setMusic(status = true, musicClass) {
735
+ return __awaiter(this, void 0, void 0, function* () {
736
+ const response = yield this.sendCommand((0, util_1.format)('SET MUSIC %s %s', (status) ? 'ON' : 'OFF', musicClass || ''));
737
+ if (response.code !== 200 || response.result !== 0) {
738
+ throw new Error('Could not set priority');
739
+ }
740
+ });
741
+ }
742
+ /**
743
+ * Set channel dialplan priority.
744
+ * @param priority
745
+ */
746
+ setPriority(priority) {
747
+ return __awaiter(this, void 0, void 0, function* () {
748
+ const response = yield this.sendCommand((0, util_1.format)('SET PRIORITY %s', priority));
749
+ if (response.code !== 200 || response.result !== 0) {
750
+ throw new Error('Could not set priority');
751
+ }
752
+ });
753
+ }
754
+ /**
755
+ * Set channel dialplan priority.
756
+ * @param key
757
+ * @param value
758
+ */
759
+ setVariable(key, value) {
760
+ return __awaiter(this, void 0, void 0, function* () {
761
+ const response = yield this.sendCommand((0, util_1.format)('SET VARIABLE %s "%s"', key.toUpperCase(), value));
762
+ if (response.code !== 200 || response.result !== 1) {
763
+ throw new Error('Could not set variable');
764
+ }
765
+ });
766
+ }
767
+ speechActivateGrammar(grammar) {
768
+ return __awaiter(this, void 0, void 0, function* () {
769
+ // TODO: Handle the response
770
+ return this.sendCommand((0, util_1.format)('SPEECH ACTIVATE GRAMMAR %s', grammar));
771
+ });
772
+ }
773
+ speechCreate(engine) {
774
+ return __awaiter(this, void 0, void 0, function* () {
775
+ // TODO: Handle the response
776
+ return this.sendCommand((0, util_1.format)('SPEECH CREATE ENGINE %s', engine));
777
+ });
778
+ }
779
+ speechDeactivateGrammar(grammar) {
780
+ return __awaiter(this, void 0, void 0, function* () {
781
+ // TODO: Handle the response
782
+ return this.sendCommand((0, util_1.format)('SPEECH DEACTIVATE GRAMMAR %s', grammar));
783
+ });
784
+ }
785
+ speechDestroy() {
786
+ return __awaiter(this, void 0, void 0, function* () {
787
+ // TODO: Handle the response
788
+ return this.sendCommand('SPEECH DESTROY');
789
+ });
790
+ }
791
+ speechLoadGrammar(grammar, path) {
792
+ return __awaiter(this, void 0, void 0, function* () {
793
+ // TODO: Handle the response
794
+ return this.sendCommand((0, util_1.format)('SPEECH LOAD GRAMMAR %s %s', grammar, path));
795
+ });
796
+ }
797
+ speechRecognize(soundFile, timeout = 5, offset) {
798
+ return __awaiter(this, void 0, void 0, function* () {
799
+ // TODO: Handle the response
800
+ return this.sendCommand((0, util_1.format)('SPEECH RECOGNIZE %s %s %s', soundFile, timeout * 1000, offset));
801
+ });
802
+ }
803
+ speechSet(key, value) {
804
+ return __awaiter(this, void 0, void 0, function* () {
805
+ // TODO: Handle the response
806
+ return this.sendCommand((0, util_1.format)('SPEECH SET %s %s', key, value));
807
+ });
808
+ }
809
+ speedUnloadGrammar(grammar) {
810
+ return __awaiter(this, void 0, void 0, function* () {
811
+ // TODO: Handle the response
812
+ return this.sendCommand((0, util_1.format)('SPEECH UNLOAD GRAMMAR %s', grammar));
813
+ });
814
+ }
815
+ /**
816
+ * Sends audio file on channel.
817
+ * @param filename
818
+ * @param escapeDigits
819
+ * @param offset
820
+ */
821
+ streamFile(filename, escapeDigits = '#', offset) {
822
+ return __awaiter(this, void 0, void 0, function* () {
823
+ const response = yield this.sendCommand((0, util_1.format)('STREAM FILE %s "%s" %s', filename, escapeDigits, offset || ''));
824
+ if (response.code !== 200 || response.result === -1) {
825
+ throw new Error('Could not stream file');
826
+ }
827
+ const status = yield this.getVariable('PLAYBACKSTATUS ');
828
+ if (status.toUpperCase() !== 'SUCCESS') {
829
+ throw new Error('Could not stream file');
830
+ }
831
+ return {
832
+ digit: response.arguments.char('result'),
833
+ endpos: response.arguments.number('endpos')
834
+ };
835
+ });
836
+ }
837
+ /**
838
+ * Toggles TDD mode (for the deaf).
839
+ * @param status
840
+ */
841
+ tddMode(status) {
842
+ return __awaiter(this, void 0, void 0, function* () {
843
+ const response = yield this.sendCommand((0, util_1.format)('TDD MODE %s', (status) ? 'ON' : 'OFF'));
844
+ if (response.code !== 200 || response.result !== 1) {
845
+ throw new Error('Could not set TDD mode');
846
+ }
847
+ });
848
+ }
849
+ /**
850
+ * Logs a message to the asterisk verbose log.
851
+ * @param message
852
+ * @param level
853
+ */
854
+ verbose(message, level) {
855
+ return __awaiter(this, void 0, void 0, function* () {
856
+ const response = yield this.sendCommand((0, util_1.format)('VERBOSE "%s" %s', message, level || ''));
857
+ if (response.code !== 200 || response.result !== 1) {
858
+ throw new Error('Could not send logging message');
859
+ }
860
+ });
861
+ }
862
+ /**
863
+ * Waits for a digit to be pressed.
864
+ * @param timeout
865
+ */
866
+ waitForDigit(timeout = 5) {
867
+ return __awaiter(this, void 0, void 0, function* () {
868
+ const response = yield this.sendCommand((0, util_1.format)('WAIT FOR DIGIT %s', timeout * 1000));
869
+ if (response.code !== 200 || response.result === -1) {
870
+ throw new Error('Could not wait for digit');
871
+ }
872
+ return response.arguments.char('result');
873
+ });
874
+ }
875
+ /* Internal Methods */
876
+ /**
877
+ * Closes the connection
878
+ *
879
+ * @private
880
+ */
881
+ close() {
882
+ this._connection.destroy();
883
+ }
884
+ /**
885
+ * Reads data from the socket
886
+ *
887
+ * @param data
888
+ * @private
889
+ */
890
+ read(data) {
891
+ if (data.length === 0) {
892
+ return;
893
+ }
894
+ this._message += data.toString();
895
+ if (this._state === types_1.ContextState.INIT) {
896
+ if (this._message.indexOf('\n\n') === -1) {
897
+ return;
898
+ }
899
+ this.readVariables(this._message);
900
+ }
901
+ else if (this._state === types_1.ContextState.WAITING) {
902
+ if (this._message.indexOf('\n') === -1) {
903
+ return;
904
+ }
905
+ this.readResponse(this._message);
906
+ }
907
+ this._message = '';
908
+ }
909
+ /**
910
+ * Parses variables
911
+ *
912
+ * @param id
913
+ * @param value
914
+ * @private
915
+ */
916
+ handleVariable(id, value) {
917
+ switch (id) {
918
+ case 'network':
919
+ this._network = value;
920
+ break;
921
+ case 'network_script':
922
+ this._network_script = value;
923
+ break;
924
+ case 'request':
925
+ this._request = value;
926
+ break;
927
+ case 'channel':
928
+ this._channel = value;
929
+ break;
930
+ case 'language':
931
+ this._language = value;
932
+ break;
933
+ case 'type':
934
+ this._type = value;
935
+ break;
936
+ case 'uniqueid':
937
+ this._uniqueid = value;
938
+ break;
939
+ case 'version':
940
+ this._version = value;
941
+ break;
942
+ case 'callerid':
943
+ this._callerid = value;
944
+ break;
945
+ case 'calleridname':
946
+ this._calleridname = value;
947
+ break;
948
+ case 'callingpres':
949
+ this._callingpres = value;
950
+ break;
951
+ case 'callingani2':
952
+ this._callingani2 = value;
953
+ break;
954
+ case 'callington':
955
+ this._callington = value;
956
+ break;
957
+ case 'callingtns':
958
+ this._callingtns = value;
959
+ break;
960
+ case 'dnid':
961
+ this._dnid = value;
962
+ break;
963
+ case 'rdnis':
964
+ this._rdnis = value;
965
+ break;
966
+ case 'context':
967
+ this._context = value;
968
+ break;
969
+ case 'extension':
970
+ this._extension = value;
971
+ break;
972
+ case 'priority':
973
+ this._priority = value;
974
+ break;
975
+ case 'enhanced':
976
+ this._enhanced = value;
977
+ break;
978
+ case 'accountcode':
979
+ this._accountcode = value;
980
+ break;
981
+ case 'threadid':
982
+ this._threadid = value;
983
+ break;
984
+ default:
985
+ }
986
+ }
987
+ /**
988
+ * Reads variables
989
+ *
990
+ * @param message
991
+ * @private
992
+ */
993
+ readVariables(message) {
994
+ message.split('\n')
995
+ .forEach(line => {
996
+ const split = line.split(':');
997
+ const name = (split[0] || '').trim();
998
+ const value = (split[1] || '').trim();
999
+ const id = name.substring(4);
1000
+ this.handleVariable(id, value);
1001
+ });
1002
+ this._state = types_1.ContextState.WAITING;
1003
+ this.emit('ready');
1004
+ }
1005
+ /**
1006
+ * Reads a response
1007
+ *
1008
+ * @param message
1009
+ * @private
1010
+ */
1011
+ readResponse(message) {
1012
+ const lines = message.split('\n');
1013
+ lines.map((line) => this.readResponseLine(line));
1014
+ }
1015
+ /**
1016
+ * Reads a response line
1017
+ *
1018
+ * @param line
1019
+ * @private
1020
+ */
1021
+ readResponseLine(line) {
1022
+ if (!line) {
1023
+ return;
1024
+ }
1025
+ this.emit('recv', line);
1026
+ const parsed = line.split(' ');
1027
+ if (!parsed || parsed[0] === 'HANGUP') {
1028
+ return this.emit('hangup');
1029
+ }
1030
+ const code = parseInt(parsed[0], 10);
1031
+ parsed.shift();
1032
+ const args = new response_arguments_1.default();
1033
+ for (const value of parsed) {
1034
+ if (value.indexOf('=') !== -1) {
1035
+ const parts = value.split('=', 2);
1036
+ const key = parts[0].trim();
1037
+ const val = parts[1].trim();
1038
+ args.addArgument(key, val);
1039
+ }
1040
+ else if (value.indexOf('(') !== -1) {
1041
+ const name = value.substring(1, value.length - 1);
1042
+ args.addArgument(name, true);
1043
+ }
1044
+ else {
1045
+ args.addArgument('value', value);
1046
+ }
1047
+ }
1048
+ const response = {
1049
+ code,
1050
+ result: args.number('result'),
1051
+ arguments: args
1052
+ };
1053
+ this.emit('response', response);
1054
+ }
1055
+ /**
1056
+ * Writes data to the socket
1057
+ *
1058
+ * @param message
1059
+ * @private
1060
+ */
1061
+ send(message) {
1062
+ return __awaiter(this, void 0, void 0, function* () {
1063
+ return new Promise((resolve, reject) => {
1064
+ this.emit('send', message);
1065
+ this._connection.write(message, (error) => {
1066
+ if (error) {
1067
+ return reject(error);
1068
+ }
1069
+ return resolve();
1070
+ });
1071
+ });
1072
+ });
1073
+ }
1074
+ /**
1075
+ * Sends a command to the socket and awaits the response
1076
+ *
1077
+ * @param command
1078
+ * @private
1079
+ */
1080
+ sendCommand(command) {
1081
+ return __awaiter(this, void 0, void 0, function* () {
1082
+ return new Promise((resolve, reject) => {
1083
+ const handleResponse = (response) => {
1084
+ this.removeListener('response', handleResponse);
1085
+ return resolve(response);
1086
+ };
1087
+ this.once('response', handleResponse);
1088
+ this.send((0, util_1.format)('%s\n', command.trim()))
1089
+ .catch(error => {
1090
+ this.removeListener('response', handleResponse);
1091
+ return reject(error);
1092
+ });
1093
+ });
1094
+ });
1095
+ }
1096
+ }
1097
+ exports.default = Channel;
1098
+ //# sourceMappingURL=channel.js.map