@ipcom/asterisk-ari 0.0.139 → 0.0.141
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 +311 -0
- package/dist/cjs/index.cjs +1032 -269
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/esm/index.js +1035 -270
- package/dist/esm/index.js.map +3 -3
- package/dist/types/ari-client/ariClient.d.ts +64 -15
- package/dist/types/ari-client/ariClient.d.ts.map +1 -1
- package/dist/types/ari-client/baseClient.d.ts +55 -22
- package/dist/types/ari-client/baseClient.d.ts.map +1 -1
- package/dist/types/ari-client/resources/channels.d.ts +351 -48
- package/dist/types/ari-client/resources/channels.d.ts.map +1 -1
- package/dist/types/ari-client/resources/playbacks.d.ts +93 -20
- package/dist/types/ari-client/resources/playbacks.d.ts.map +1 -1
- package/dist/types/ari-client/utils.d.ts.map +1 -1
- package/dist/types/ari-client/websocketClient.d.ts +44 -13
- package/dist/types/ari-client/websocketClient.d.ts.map +1 -1
- package/dist/types/index.d.ts +26 -2
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -571,30 +571,55 @@ var require_backoff = __commonJS({
|
|
|
571
571
|
});
|
|
572
572
|
|
|
573
573
|
// src/ari-client/baseClient.ts
|
|
574
|
-
import axios
|
|
574
|
+
import axios, {
|
|
575
|
+
isAxiosError
|
|
576
|
+
} from "axios";
|
|
577
|
+
var HTTPError = class extends Error {
|
|
578
|
+
constructor(message, status, method, url) {
|
|
579
|
+
super(message);
|
|
580
|
+
this.status = status;
|
|
581
|
+
this.method = method;
|
|
582
|
+
this.url = url;
|
|
583
|
+
this.name = "HTTPError";
|
|
584
|
+
}
|
|
585
|
+
};
|
|
575
586
|
var BaseClient = class {
|
|
587
|
+
/**
|
|
588
|
+
* Creates a new BaseClient instance.
|
|
589
|
+
*
|
|
590
|
+
* @param {string} baseUrl - The base URL for the API
|
|
591
|
+
* @param {string} username - Username for authentication
|
|
592
|
+
* @param {string} password - Password for authentication
|
|
593
|
+
* @param {number} [timeout=5000] - Request timeout in milliseconds
|
|
594
|
+
* @throws {Error} If the base URL format is invalid
|
|
595
|
+
*/
|
|
576
596
|
constructor(baseUrl, username, password, timeout = 5e3) {
|
|
577
597
|
this.baseUrl = baseUrl;
|
|
578
598
|
this.username = username;
|
|
579
599
|
this.password = password;
|
|
580
600
|
if (!/^https?:\/\/.+/.test(baseUrl)) {
|
|
581
|
-
throw new Error(
|
|
582
|
-
"Invalid base URL. It must start with http:// or https://"
|
|
583
|
-
);
|
|
601
|
+
throw new Error("Invalid base URL. It must start with http:// or https://");
|
|
584
602
|
}
|
|
585
603
|
this.client = axios.create({
|
|
586
604
|
baseURL: baseUrl,
|
|
587
605
|
auth: { username, password },
|
|
588
|
-
timeout
|
|
606
|
+
timeout,
|
|
607
|
+
headers: {
|
|
608
|
+
"Content-Type": "application/json"
|
|
609
|
+
}
|
|
589
610
|
});
|
|
590
611
|
this.addInterceptors();
|
|
612
|
+
console.log(`BaseClient initialized for ${baseUrl}`);
|
|
591
613
|
}
|
|
592
614
|
client;
|
|
615
|
+
/**
|
|
616
|
+
* Gets the base URL of the client.
|
|
617
|
+
*/
|
|
593
618
|
getBaseUrl() {
|
|
594
619
|
return this.baseUrl;
|
|
595
620
|
}
|
|
596
621
|
/**
|
|
597
|
-
*
|
|
622
|
+
* Gets the configured credentials.
|
|
598
623
|
*/
|
|
599
624
|
getCredentials() {
|
|
600
625
|
return {
|
|
@@ -604,123 +629,159 @@ var BaseClient = class {
|
|
|
604
629
|
};
|
|
605
630
|
}
|
|
606
631
|
/**
|
|
607
|
-
* Adds interceptors to the Axios instance.
|
|
632
|
+
* Adds request and response interceptors to the Axios instance.
|
|
608
633
|
*/
|
|
609
634
|
addInterceptors() {
|
|
610
635
|
this.client.interceptors.request.use(
|
|
611
636
|
(config) => {
|
|
637
|
+
console.log(`[Request] ${config.method?.toUpperCase()} ${config.url}`);
|
|
612
638
|
return config;
|
|
613
639
|
},
|
|
614
640
|
(error) => {
|
|
615
|
-
|
|
616
|
-
|
|
641
|
+
const message = this.getErrorMessage(error);
|
|
642
|
+
console.error("[Request Error]", message);
|
|
643
|
+
return Promise.reject(new HTTPError(message));
|
|
617
644
|
}
|
|
618
645
|
);
|
|
619
646
|
this.client.interceptors.response.use(
|
|
620
|
-
(response) =>
|
|
647
|
+
(response) => {
|
|
648
|
+
console.log(`[Response] ${response.status} ${response.config.url}`);
|
|
649
|
+
return response;
|
|
650
|
+
},
|
|
621
651
|
(error) => {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
message
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
);
|
|
652
|
+
if (isAxiosError(error)) {
|
|
653
|
+
const status = error.response?.status ?? 0;
|
|
654
|
+
const method = error.config?.method?.toUpperCase() ?? "UNKNOWN";
|
|
655
|
+
const url = error.config?.url ?? "unknown-url";
|
|
656
|
+
const message2 = error.response?.data?.message || error.message || "Unknown error";
|
|
657
|
+
if (status === 404) {
|
|
658
|
+
console.warn(`[404] Not Found: ${url}`);
|
|
659
|
+
} else if (status >= 500) {
|
|
660
|
+
console.error(`[${status}] Server Error: ${url}`);
|
|
661
|
+
} else if (status > 0) {
|
|
662
|
+
console.warn(`[${status}] ${method} ${url}: ${message2}`);
|
|
663
|
+
} else {
|
|
664
|
+
console.error(`[Network] Request failed: ${message2}`);
|
|
665
|
+
}
|
|
666
|
+
throw new HTTPError(message2, status || void 0, method, url);
|
|
638
667
|
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
)
|
|
643
|
-
);
|
|
668
|
+
const message = this.getErrorMessage(error);
|
|
669
|
+
console.error("[Unexpected Error]", message);
|
|
670
|
+
throw new Error(message);
|
|
644
671
|
}
|
|
645
672
|
);
|
|
646
673
|
}
|
|
647
674
|
/**
|
|
648
675
|
* Executes a GET request.
|
|
649
|
-
*
|
|
650
|
-
* @param
|
|
676
|
+
*
|
|
677
|
+
* @param path - API endpoint path
|
|
678
|
+
* @param config - Optional Axios request configuration
|
|
679
|
+
* @returns Promise with the response data
|
|
651
680
|
*/
|
|
652
681
|
async get(path, config) {
|
|
653
682
|
try {
|
|
654
683
|
const response = await this.client.get(path, config);
|
|
655
684
|
return response.data;
|
|
656
685
|
} catch (error) {
|
|
657
|
-
this.handleRequestError(error);
|
|
686
|
+
throw this.handleRequestError(error);
|
|
658
687
|
}
|
|
659
688
|
}
|
|
660
689
|
/**
|
|
661
690
|
* Executes a POST request.
|
|
662
|
-
*
|
|
663
|
-
* @param
|
|
664
|
-
* @param
|
|
691
|
+
*
|
|
692
|
+
* @param path - API endpoint path
|
|
693
|
+
* @param data - Request payload
|
|
694
|
+
* @param config - Optional Axios request configuration
|
|
695
|
+
* @returns Promise with the response data
|
|
665
696
|
*/
|
|
666
697
|
async post(path, data, config) {
|
|
667
698
|
try {
|
|
668
699
|
const response = await this.client.post(path, data, config);
|
|
669
700
|
return response.data;
|
|
670
701
|
} catch (error) {
|
|
671
|
-
this.handleRequestError(error);
|
|
702
|
+
throw this.handleRequestError(error);
|
|
672
703
|
}
|
|
673
704
|
}
|
|
674
705
|
/**
|
|
675
706
|
* Executes a PUT request.
|
|
676
|
-
*
|
|
677
|
-
* @param
|
|
678
|
-
* @param
|
|
707
|
+
*
|
|
708
|
+
* @param path - API endpoint path
|
|
709
|
+
* @param data - Request payload
|
|
710
|
+
* @param config - Optional Axios request configuration
|
|
711
|
+
* @returns Promise with the response data
|
|
679
712
|
*/
|
|
680
713
|
async put(path, data, config) {
|
|
681
714
|
try {
|
|
682
715
|
const response = await this.client.put(path, data, config);
|
|
683
716
|
return response.data;
|
|
684
717
|
} catch (error) {
|
|
685
|
-
this.handleRequestError(error);
|
|
718
|
+
throw this.handleRequestError(error);
|
|
686
719
|
}
|
|
687
720
|
}
|
|
688
721
|
/**
|
|
689
722
|
* Executes a DELETE request.
|
|
690
|
-
*
|
|
691
|
-
* @param
|
|
723
|
+
*
|
|
724
|
+
* @param path - API endpoint path
|
|
725
|
+
* @param config - Optional Axios request configuration
|
|
726
|
+
* @returns Promise with the response data
|
|
692
727
|
*/
|
|
693
728
|
async delete(path, config) {
|
|
694
729
|
try {
|
|
695
730
|
const response = await this.client.delete(path, config);
|
|
696
731
|
return response.data;
|
|
697
732
|
} catch (error) {
|
|
698
|
-
this.handleRequestError(error);
|
|
733
|
+
throw this.handleRequestError(error);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Handles and formats error messages from various error types.
|
|
738
|
+
*/
|
|
739
|
+
getErrorMessage(error) {
|
|
740
|
+
if (isAxiosError(error)) {
|
|
741
|
+
return error.response?.data?.message || error.message || "HTTP Error";
|
|
699
742
|
}
|
|
743
|
+
if (error instanceof Error) {
|
|
744
|
+
return error.message;
|
|
745
|
+
}
|
|
746
|
+
return "An unknown error occurred";
|
|
700
747
|
}
|
|
701
748
|
/**
|
|
702
|
-
* Handles errors
|
|
703
|
-
* @param error - The error to handle.
|
|
749
|
+
* Handles errors from HTTP requests.
|
|
704
750
|
*/
|
|
705
751
|
handleRequestError(error) {
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
throw new
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
752
|
+
const message = this.getErrorMessage(error);
|
|
753
|
+
if (isAxiosError(error)) {
|
|
754
|
+
throw new HTTPError(
|
|
755
|
+
message,
|
|
756
|
+
error.response?.status,
|
|
757
|
+
error.config?.method?.toUpperCase(),
|
|
758
|
+
error.config?.url
|
|
759
|
+
);
|
|
712
760
|
}
|
|
761
|
+
throw new Error(message);
|
|
713
762
|
}
|
|
714
763
|
/**
|
|
715
764
|
* Sets custom headers for the client instance.
|
|
716
|
-
* Useful for adding dynamic tokens or specific API headers.
|
|
717
|
-
* @param headers - Headers to merge with existing configuration.
|
|
718
765
|
*/
|
|
719
766
|
setHeaders(headers) {
|
|
720
767
|
this.client.defaults.headers.common = {
|
|
721
768
|
...this.client.defaults.headers.common,
|
|
722
769
|
...headers
|
|
723
770
|
};
|
|
771
|
+
console.log("Updated client headers");
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Gets the current request timeout setting.
|
|
775
|
+
*/
|
|
776
|
+
getTimeout() {
|
|
777
|
+
return this.client.defaults.timeout || 5e3;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Updates the request timeout setting.
|
|
781
|
+
*/
|
|
782
|
+
setTimeout(timeout) {
|
|
783
|
+
this.client.defaults.timeout = timeout;
|
|
784
|
+
console.log(`Updated timeout to ${timeout}ms`);
|
|
724
785
|
}
|
|
725
786
|
};
|
|
726
787
|
|
|
@@ -944,6 +1005,7 @@ var Bridges = class {
|
|
|
944
1005
|
|
|
945
1006
|
// src/ari-client/resources/channels.ts
|
|
946
1007
|
import { EventEmitter } from "events";
|
|
1008
|
+
import { isAxiosError as isAxiosError2 } from "axios";
|
|
947
1009
|
|
|
948
1010
|
// node_modules/uuid/dist/esm/stringify.js
|
|
949
1011
|
var byteToHex = [];
|
|
@@ -998,102 +1060,212 @@ function toQueryParams2(options) {
|
|
|
998
1060
|
}
|
|
999
1061
|
|
|
1000
1062
|
// src/ari-client/resources/channels.ts
|
|
1063
|
+
var getErrorMessage = (error) => {
|
|
1064
|
+
if (isAxiosError2(error)) {
|
|
1065
|
+
return error.response?.data?.message || error.message || "An axios error occurred";
|
|
1066
|
+
}
|
|
1067
|
+
if (error instanceof Error) {
|
|
1068
|
+
return error.message;
|
|
1069
|
+
}
|
|
1070
|
+
return "An unknown error occurred";
|
|
1071
|
+
};
|
|
1001
1072
|
var ChannelInstance = class {
|
|
1002
|
-
|
|
1003
|
-
constructor(client, baseClient, channelId = `channel-${Date.now()}`) {
|
|
1073
|
+
constructor(client, baseClient, channelId) {
|
|
1004
1074
|
this.client = client;
|
|
1005
1075
|
this.baseClient = baseClient;
|
|
1006
|
-
this.channelId = channelId;
|
|
1007
1076
|
this.id = channelId || `channel-${Date.now()}`;
|
|
1077
|
+
console.log(`Channel instance initialized with ID: ${this.id}`);
|
|
1008
1078
|
}
|
|
1009
1079
|
eventEmitter = new EventEmitter();
|
|
1010
1080
|
channelData = null;
|
|
1011
1081
|
id;
|
|
1012
1082
|
/**
|
|
1013
|
-
*
|
|
1083
|
+
* Registers an event listener for specific channel events
|
|
1014
1084
|
*/
|
|
1015
1085
|
on(event, listener) {
|
|
1086
|
+
if (!event) {
|
|
1087
|
+
throw new Error("Event type is required");
|
|
1088
|
+
}
|
|
1016
1089
|
const wrappedListener = (data) => {
|
|
1017
1090
|
if ("channel" in data && data.channel?.id === this.id) {
|
|
1018
1091
|
listener(data);
|
|
1019
1092
|
}
|
|
1020
1093
|
};
|
|
1021
1094
|
this.eventEmitter.on(event, wrappedListener);
|
|
1095
|
+
console.log(`Event listener registered for ${event} on channel ${this.id}`);
|
|
1022
1096
|
}
|
|
1023
1097
|
/**
|
|
1024
|
-
*
|
|
1098
|
+
* Registers a one-time event listener
|
|
1025
1099
|
*/
|
|
1026
1100
|
once(event, listener) {
|
|
1101
|
+
if (!event) {
|
|
1102
|
+
throw new Error("Event type is required");
|
|
1103
|
+
}
|
|
1027
1104
|
const wrappedListener = (data) => {
|
|
1028
1105
|
if ("channel" in data && data.channel?.id === this.id) {
|
|
1029
1106
|
listener(data);
|
|
1030
1107
|
}
|
|
1031
1108
|
};
|
|
1032
1109
|
this.eventEmitter.once(event, wrappedListener);
|
|
1110
|
+
console.log(
|
|
1111
|
+
`One-time event listener registered for ${event} on channel ${this.id}`
|
|
1112
|
+
);
|
|
1033
1113
|
}
|
|
1034
1114
|
/**
|
|
1035
|
-
*
|
|
1115
|
+
* Removes event listener(s) for a specific WebSocket event type.
|
|
1116
|
+
* If a specific listener is provided, only that listener is removed.
|
|
1117
|
+
* Otherwise, all listeners for the given event type are removed.
|
|
1118
|
+
*
|
|
1119
|
+
* @param {T} event - The type of WebSocket event to remove listener(s) for
|
|
1120
|
+
* @param {Function} [listener] - Optional specific listener to remove
|
|
1121
|
+
* @throws {Error} If no event type is provided
|
|
1036
1122
|
*/
|
|
1037
1123
|
off(event, listener) {
|
|
1124
|
+
if (!event) {
|
|
1125
|
+
throw new Error("Event type is required");
|
|
1126
|
+
}
|
|
1038
1127
|
if (listener) {
|
|
1039
1128
|
this.eventEmitter.off(event, listener);
|
|
1129
|
+
console.log(
|
|
1130
|
+
`Specific listener removed for ${event} on channel ${this.id}`
|
|
1131
|
+
);
|
|
1040
1132
|
} else {
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
this.eventEmitter.off(event, fn);
|
|
1044
|
-
});
|
|
1133
|
+
this.eventEmitter.removeAllListeners(event);
|
|
1134
|
+
console.log(`All listeners removed for ${event} on channel ${this.id}`);
|
|
1045
1135
|
}
|
|
1046
1136
|
}
|
|
1047
1137
|
/**
|
|
1048
|
-
*
|
|
1049
|
-
*/
|
|
1050
|
-
getListenerCount(event) {
|
|
1051
|
-
return this.eventEmitter.listenerCount(event);
|
|
1052
|
-
}
|
|
1053
|
-
/**
|
|
1054
|
-
* Emite eventos internamente para o canal.
|
|
1055
|
-
* Verifica o ID do canal antes de emitir.
|
|
1138
|
+
* Emits an event if it matches the current channel
|
|
1056
1139
|
*/
|
|
1057
1140
|
emitEvent(event) {
|
|
1141
|
+
if (!event) {
|
|
1142
|
+
console.warn("Received invalid event");
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1058
1145
|
if ("channel" in event && event.channel?.id === this.id) {
|
|
1059
1146
|
this.eventEmitter.emit(event.type, event);
|
|
1147
|
+
console.log(`Event ${event.type} emitted for channel ${this.id}`);
|
|
1060
1148
|
}
|
|
1061
1149
|
}
|
|
1062
1150
|
/**
|
|
1063
|
-
*
|
|
1151
|
+
* Removes all event listeners associated with the current instance.
|
|
1152
|
+
* This ensures that there are no lingering event handlers for the channel.
|
|
1153
|
+
*
|
|
1154
|
+
* @return {void} This method does not return a value.
|
|
1064
1155
|
*/
|
|
1065
1156
|
removeAllListeners() {
|
|
1066
1157
|
console.log(`Removendo todos os listeners para o canal ${this.id}`);
|
|
1067
1158
|
this.eventEmitter.removeAllListeners();
|
|
1068
1159
|
}
|
|
1160
|
+
/**
|
|
1161
|
+
* Answers the channel
|
|
1162
|
+
*/
|
|
1069
1163
|
async answer() {
|
|
1070
|
-
|
|
1164
|
+
try {
|
|
1165
|
+
await this.baseClient.post(`/channels/${this.id}/answer`);
|
|
1166
|
+
console.log(`Channel ${this.id} answered`);
|
|
1167
|
+
} catch (error) {
|
|
1168
|
+
const message = getErrorMessage(error);
|
|
1169
|
+
console.error(`Error answering channel ${this.id}:`, message);
|
|
1170
|
+
throw new Error(`Failed to answer channel: ${message}`);
|
|
1171
|
+
}
|
|
1071
1172
|
}
|
|
1072
1173
|
/**
|
|
1073
|
-
*
|
|
1174
|
+
* Originates a new channel
|
|
1175
|
+
*
|
|
1176
|
+
* @param data - Channel origination configuration
|
|
1177
|
+
* @returns Promise resolving to the created channel
|
|
1178
|
+
* @throws Error if channel already exists or origination fails
|
|
1074
1179
|
*/
|
|
1075
1180
|
async originate(data) {
|
|
1076
1181
|
if (this.channelData) {
|
|
1077
|
-
throw new Error("
|
|
1182
|
+
throw new Error("Channel has already been created");
|
|
1183
|
+
}
|
|
1184
|
+
try {
|
|
1185
|
+
this.channelData = await this.baseClient.post(
|
|
1186
|
+
"/channels",
|
|
1187
|
+
data
|
|
1188
|
+
);
|
|
1189
|
+
console.log(
|
|
1190
|
+
`Channel originated successfully with ID: ${this.channelData.id}`
|
|
1191
|
+
);
|
|
1192
|
+
return this.channelData;
|
|
1193
|
+
} catch (error) {
|
|
1194
|
+
const message = getErrorMessage(error);
|
|
1195
|
+
console.error(`Error originating channel:`, message);
|
|
1196
|
+
throw new Error(`Failed to originate channel: ${message}`);
|
|
1078
1197
|
}
|
|
1079
|
-
const channel = await this.baseClient.post("/channels", data);
|
|
1080
|
-
this.channelData = channel;
|
|
1081
|
-
return channel;
|
|
1082
1198
|
}
|
|
1083
1199
|
/**
|
|
1084
|
-
*
|
|
1200
|
+
* Plays media on the channel
|
|
1085
1201
|
*/
|
|
1086
|
-
async
|
|
1087
|
-
if (
|
|
1088
|
-
|
|
1202
|
+
async play(options, playbackId) {
|
|
1203
|
+
if (!options.media) {
|
|
1204
|
+
throw new Error("Media URL is required");
|
|
1089
1205
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1206
|
+
try {
|
|
1207
|
+
if (!this.channelData) {
|
|
1208
|
+
console.log("Initializing channel details...");
|
|
1209
|
+
this.channelData = await this.getDetails();
|
|
1210
|
+
}
|
|
1211
|
+
const playback = this.client.Playback(playbackId || v4_default());
|
|
1212
|
+
await this.baseClient.post(
|
|
1213
|
+
`/channels/${this.id}/play/${playback.id}`,
|
|
1214
|
+
options
|
|
1215
|
+
);
|
|
1216
|
+
console.log(`Media playback started on channel ${this.id}`);
|
|
1217
|
+
return playback;
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
const message = getErrorMessage(error);
|
|
1220
|
+
console.error(`Error playing media on channel ${this.id}:`, message);
|
|
1221
|
+
throw new Error(`Failed to play media: ${message}`);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Gets the current channel details
|
|
1226
|
+
*/
|
|
1227
|
+
async getDetails() {
|
|
1228
|
+
try {
|
|
1229
|
+
if (this.channelData) {
|
|
1230
|
+
return this.channelData;
|
|
1231
|
+
}
|
|
1232
|
+
if (!this.id) {
|
|
1233
|
+
throw new Error("No channel ID associated with this instance");
|
|
1234
|
+
}
|
|
1235
|
+
const details = await this.baseClient.get(
|
|
1236
|
+
`/channels/${this.id}`
|
|
1237
|
+
);
|
|
1238
|
+
this.channelData = details;
|
|
1239
|
+
console.log(`Retrieved channel details for ${this.id}`);
|
|
1240
|
+
return details;
|
|
1241
|
+
} catch (error) {
|
|
1242
|
+
const message = getErrorMessage(error);
|
|
1243
|
+
console.error(
|
|
1244
|
+
`Error retrieving channel details for ${this.id}:`,
|
|
1245
|
+
message
|
|
1246
|
+
);
|
|
1247
|
+
throw new Error(`Failed to get channel details: ${message}`);
|
|
1092
1248
|
}
|
|
1093
|
-
const details = await this.baseClient.get(`/channels/${this.id}`);
|
|
1094
|
-
this.channelData = details;
|
|
1095
|
-
return details;
|
|
1096
1249
|
}
|
|
1250
|
+
/**
|
|
1251
|
+
* Checks if the channel has any listeners for a specific event
|
|
1252
|
+
*/
|
|
1253
|
+
hasListeners(event) {
|
|
1254
|
+
return this.eventEmitter.listenerCount(event) > 0;
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Gets the count of listeners for a specific event
|
|
1258
|
+
*/
|
|
1259
|
+
getListenerCount(event) {
|
|
1260
|
+
return this.eventEmitter.listenerCount(event);
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Fetches a specific channel variable.
|
|
1264
|
+
*
|
|
1265
|
+
* @param {string} variable - The name of the variable to retrieve. This parameter is required.
|
|
1266
|
+
* @return {Promise<ChannelVar>} A promise that resolves with the value of the requested channel variable.
|
|
1267
|
+
* @throws {Error} If the 'variable' parameter is not provided.
|
|
1268
|
+
*/
|
|
1097
1269
|
async getVariable(variable) {
|
|
1098
1270
|
if (!variable) {
|
|
1099
1271
|
throw new Error("The 'variable' parameter is required.");
|
|
@@ -1103,7 +1275,11 @@ var ChannelInstance = class {
|
|
|
1103
1275
|
);
|
|
1104
1276
|
}
|
|
1105
1277
|
/**
|
|
1106
|
-
*
|
|
1278
|
+
* Terminates the active call associated with the current channel.
|
|
1279
|
+
* This method ensures that channel details are initialized before attempting to hang up.
|
|
1280
|
+
* If the channel ID is invalid or cannot be determined, an error is thrown.
|
|
1281
|
+
*
|
|
1282
|
+
* @return {Promise<void>} A promise that resolves when the call is successfully terminated.
|
|
1107
1283
|
*/
|
|
1108
1284
|
async hangup() {
|
|
1109
1285
|
if (!this.channelData) {
|
|
@@ -1116,25 +1292,12 @@ var ChannelInstance = class {
|
|
|
1116
1292
|
await this.baseClient.delete(`/channels/${this.channelData.id}`);
|
|
1117
1293
|
}
|
|
1118
1294
|
/**
|
|
1119
|
-
*
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
}
|
|
1126
|
-
const playback = this.client.Playback(playbackId || v4_default());
|
|
1127
|
-
if (!this.channelData?.id) {
|
|
1128
|
-
throw new Error("N\xE3o foi poss\xEDvel inicializar o canal. ID inv\xE1lido.");
|
|
1129
|
-
}
|
|
1130
|
-
await this.baseClient.post(
|
|
1131
|
-
`/channels/${this.channelData.id}/play/${playback.id}`,
|
|
1132
|
-
options
|
|
1133
|
-
);
|
|
1134
|
-
return playback;
|
|
1135
|
-
}
|
|
1136
|
-
/**
|
|
1137
|
-
* Reproduz mídia em um canal.
|
|
1295
|
+
* Plays media on the specified channel using the provided media URL and optional playback options.
|
|
1296
|
+
*
|
|
1297
|
+
* @param {string} media - The URL or identifier of the media to be played.
|
|
1298
|
+
* @param {PlaybackOptions} [options] - Optional playback settings such as volume, playback speed, etc.
|
|
1299
|
+
* @return {Promise<ChannelPlayback>} A promise that resolves with the playback details for the channel.
|
|
1300
|
+
* @throws {Error} Throws an error if the channel has not been created.
|
|
1138
1301
|
*/
|
|
1139
1302
|
async playMedia(media, options) {
|
|
1140
1303
|
if (!this.channelData) {
|
|
@@ -1147,7 +1310,11 @@ var ChannelInstance = class {
|
|
|
1147
1310
|
);
|
|
1148
1311
|
}
|
|
1149
1312
|
/**
|
|
1150
|
-
*
|
|
1313
|
+
* Stops the playback for the given playback ID.
|
|
1314
|
+
*
|
|
1315
|
+
* @param {string} playbackId - The unique identifier for the playback to be stopped.
|
|
1316
|
+
* @return {Promise<void>} A promise that resolves when the playback is successfully stopped.
|
|
1317
|
+
* @throws {Error} Throws an error if the instance is not associated with a channel.
|
|
1151
1318
|
*/
|
|
1152
1319
|
async stopPlayback(playbackId) {
|
|
1153
1320
|
if (!this.channelData?.id) {
|
|
@@ -1158,7 +1325,11 @@ var ChannelInstance = class {
|
|
|
1158
1325
|
);
|
|
1159
1326
|
}
|
|
1160
1327
|
/**
|
|
1161
|
-
*
|
|
1328
|
+
* Pauses the playback of the specified media on a channel.
|
|
1329
|
+
*
|
|
1330
|
+
* @param {string} playbackId - The unique identifier of the playback to be paused.
|
|
1331
|
+
* @return {Promise<void>} A promise that resolves when the playback has been successfully paused.
|
|
1332
|
+
* @throws {Error} Throws an error if the channel is not associated with the current instance.
|
|
1162
1333
|
*/
|
|
1163
1334
|
async pausePlayback(playbackId) {
|
|
1164
1335
|
if (!this.channelData?.id) {
|
|
@@ -1169,7 +1340,11 @@ var ChannelInstance = class {
|
|
|
1169
1340
|
);
|
|
1170
1341
|
}
|
|
1171
1342
|
/**
|
|
1172
|
-
*
|
|
1343
|
+
* Resumes playback of the specified playback session on the associated channel.
|
|
1344
|
+
*
|
|
1345
|
+
* @param {string} playbackId - The unique identifier of the playback session to be resumed.
|
|
1346
|
+
* @return {Promise<void>} A promise that resolves when the playback has been successfully resumed.
|
|
1347
|
+
* @throws {Error} Throws an error if the channel is not associated with this instance.
|
|
1173
1348
|
*/
|
|
1174
1349
|
async resumePlayback(playbackId) {
|
|
1175
1350
|
if (!this.channelData?.id) {
|
|
@@ -1180,7 +1355,11 @@ var ChannelInstance = class {
|
|
|
1180
1355
|
);
|
|
1181
1356
|
}
|
|
1182
1357
|
/**
|
|
1183
|
-
*
|
|
1358
|
+
* Rewinds the playback of a media by a specified amount of milliseconds.
|
|
1359
|
+
*
|
|
1360
|
+
* @param {string} playbackId - The unique identifier for the playback session to be rewound.
|
|
1361
|
+
* @param {number} skipMs - The number of milliseconds to rewind the playback.
|
|
1362
|
+
* @return {Promise<void>} A promise that resolves when the rewind operation is complete.
|
|
1184
1363
|
*/
|
|
1185
1364
|
async rewindPlayback(playbackId, skipMs) {
|
|
1186
1365
|
if (!this.channelData?.id) {
|
|
@@ -1192,7 +1371,12 @@ var ChannelInstance = class {
|
|
|
1192
1371
|
);
|
|
1193
1372
|
}
|
|
1194
1373
|
/**
|
|
1195
|
-
*
|
|
1374
|
+
* Fast forwards the playback by a specific duration in milliseconds.
|
|
1375
|
+
*
|
|
1376
|
+
* @param {string} playbackId - The unique identifier of the playback to be fast-forwarded.
|
|
1377
|
+
* @param {number} skipMs - The number of milliseconds to fast forward the playback.
|
|
1378
|
+
* @return {Promise<void>} A Promise that resolves when the fast-forward operation is complete.
|
|
1379
|
+
* @throws {Error} If no channel is associated with this instance.
|
|
1196
1380
|
*/
|
|
1197
1381
|
async fastForwardPlayback(playbackId, skipMs) {
|
|
1198
1382
|
if (!this.channelData?.id) {
|
|
@@ -1204,7 +1388,11 @@ var ChannelInstance = class {
|
|
|
1204
1388
|
);
|
|
1205
1389
|
}
|
|
1206
1390
|
/**
|
|
1207
|
-
*
|
|
1391
|
+
* Mutes the specified channel for the given direction.
|
|
1392
|
+
*
|
|
1393
|
+
* @param {("both" | "in" | "out")} [direction="both"] - The direction to mute the channel. It can be "both" to mute incoming and outgoing, "in" to mute incoming, or "out" to mute outgoing.
|
|
1394
|
+
* @return {Promise<void>} A promise that resolves when the channel is successfully muted.
|
|
1395
|
+
* @throws {Error} If the channel is not associated with this instance.
|
|
1208
1396
|
*/
|
|
1209
1397
|
async muteChannel(direction = "both") {
|
|
1210
1398
|
if (!this.channelData?.id) {
|
|
@@ -1215,7 +1403,12 @@ var ChannelInstance = class {
|
|
|
1215
1403
|
);
|
|
1216
1404
|
}
|
|
1217
1405
|
/**
|
|
1218
|
-
*
|
|
1406
|
+
* Unmutes a previously muted channel in the specified direction.
|
|
1407
|
+
*
|
|
1408
|
+
* @param {"both" | "in" | "out"} direction - The direction in which to unmute the channel.
|
|
1409
|
+
* Defaults to "both", which unmutes both incoming and outgoing communication.
|
|
1410
|
+
* @return {Promise<void>} A promise that resolves once the channel has been successfully unmuted.
|
|
1411
|
+
* @throws {Error} If the channel is not associated with the current instance.
|
|
1219
1412
|
*/
|
|
1220
1413
|
async unmuteChannel(direction = "both") {
|
|
1221
1414
|
if (!this.channelData?.id) {
|
|
@@ -1226,7 +1419,10 @@ var ChannelInstance = class {
|
|
|
1226
1419
|
);
|
|
1227
1420
|
}
|
|
1228
1421
|
/**
|
|
1229
|
-
*
|
|
1422
|
+
* Places the associated channel on hold if the channel is valid and linked to this instance.
|
|
1423
|
+
*
|
|
1424
|
+
* @return {Promise<void>} A promise that resolves when the hold action is successfully executed.
|
|
1425
|
+
* @throws {Error} Throws an error if the channel is not associated with this instance.
|
|
1230
1426
|
*/
|
|
1231
1427
|
async holdChannel() {
|
|
1232
1428
|
if (!this.channelData?.id) {
|
|
@@ -1235,7 +1431,12 @@ var ChannelInstance = class {
|
|
|
1235
1431
|
await this.baseClient.post(`/channels/${this.channelData.id}/hold`);
|
|
1236
1432
|
}
|
|
1237
1433
|
/**
|
|
1238
|
-
*
|
|
1434
|
+
* Removes the hold status from a specific channel associated with this instance.
|
|
1435
|
+
* The method sends a delete request to the server to release the hold on the channel.
|
|
1436
|
+
* If no channel is associated with this instance, an error will be thrown.
|
|
1437
|
+
*
|
|
1438
|
+
* @return {Promise<void>} A promise that resolves when the channel hold has been successfully removed.
|
|
1439
|
+
* @throws {Error} If no channel is associated with this instance.
|
|
1239
1440
|
*/
|
|
1240
1441
|
async unholdChannel() {
|
|
1241
1442
|
if (!this.channelData?.id) {
|
|
@@ -1250,73 +1451,140 @@ var Channels = class {
|
|
|
1250
1451
|
this.client = client;
|
|
1251
1452
|
}
|
|
1252
1453
|
channelInstances = /* @__PURE__ */ new Map();
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1454
|
+
/**
|
|
1455
|
+
* Creates or retrieves a ChannelInstance.
|
|
1456
|
+
*
|
|
1457
|
+
* @param {Object} [params] - Optional parameters for getting/creating a channel instance
|
|
1458
|
+
* @param {string} [params.id] - Optional ID of an existing channel
|
|
1459
|
+
* @returns {ChannelInstance} The requested or new channel instance
|
|
1460
|
+
* @throws {Error} If channel creation/retrieval fails
|
|
1461
|
+
*
|
|
1462
|
+
* @example
|
|
1463
|
+
* // Create new channel without ID
|
|
1464
|
+
* const channel1 = client.channels.Channel();
|
|
1465
|
+
*
|
|
1466
|
+
* // Create/retrieve channel with specific ID
|
|
1467
|
+
* const channel2 = client.channels.Channel({ id: 'some-id' });
|
|
1468
|
+
*/
|
|
1469
|
+
Channel(params) {
|
|
1470
|
+
try {
|
|
1471
|
+
const id = params?.id;
|
|
1472
|
+
if (!id) {
|
|
1473
|
+
const instance = new ChannelInstance(this.client, this.baseClient);
|
|
1474
|
+
this.channelInstances.set(instance.id, instance);
|
|
1475
|
+
console.log(`New channel instance created with ID: ${instance.id}`);
|
|
1476
|
+
return instance;
|
|
1477
|
+
}
|
|
1478
|
+
if (!this.channelInstances.has(id)) {
|
|
1479
|
+
const instance = new ChannelInstance(this.client, this.baseClient, id);
|
|
1480
|
+
this.channelInstances.set(id, instance);
|
|
1481
|
+
console.log(`New channel instance created with provided ID: ${id}`);
|
|
1482
|
+
return instance;
|
|
1483
|
+
}
|
|
1484
|
+
console.log(`Returning existing channel instance: ${id}`);
|
|
1485
|
+
return this.channelInstances.get(id);
|
|
1486
|
+
} catch (error) {
|
|
1487
|
+
const message = getErrorMessage(error);
|
|
1488
|
+
console.error(`Error creating/retrieving channel instance:`, message);
|
|
1489
|
+
throw new Error(`Failed to manage channel instance: ${message}`);
|
|
1263
1490
|
}
|
|
1264
|
-
return this.channelInstances.get(id);
|
|
1265
1491
|
}
|
|
1266
1492
|
/**
|
|
1267
|
-
*
|
|
1493
|
+
* Removes a channel instance from the collection.
|
|
1268
1494
|
*/
|
|
1269
1495
|
removeChannelInstance(channelId) {
|
|
1496
|
+
if (!channelId) {
|
|
1497
|
+
throw new Error("Channel ID is required");
|
|
1498
|
+
}
|
|
1270
1499
|
if (this.channelInstances.has(channelId)) {
|
|
1271
1500
|
const instance = this.channelInstances.get(channelId);
|
|
1272
1501
|
instance?.removeAllListeners();
|
|
1273
1502
|
this.channelInstances.delete(channelId);
|
|
1274
|
-
console.log(`
|
|
1503
|
+
console.log(`Channel instance removed: ${channelId}`);
|
|
1275
1504
|
} else {
|
|
1276
|
-
console.warn(
|
|
1277
|
-
`Tentativa de remover uma inst\xE2ncia inexistente: ${channelId}`
|
|
1278
|
-
);
|
|
1505
|
+
console.warn(`Attempt to remove non-existent instance: ${channelId}`);
|
|
1279
1506
|
}
|
|
1280
1507
|
}
|
|
1281
1508
|
/**
|
|
1282
|
-
*
|
|
1509
|
+
* Propagates a WebSocket event to a specific channel.
|
|
1283
1510
|
*/
|
|
1284
1511
|
propagateEventToChannel(event) {
|
|
1512
|
+
if (!event) {
|
|
1513
|
+
console.warn("Invalid WebSocket event received");
|
|
1514
|
+
return;
|
|
1515
|
+
}
|
|
1285
1516
|
if ("channel" in event && event.channel?.id) {
|
|
1286
1517
|
const instance = this.channelInstances.get(event.channel.id);
|
|
1287
1518
|
if (instance) {
|
|
1288
1519
|
instance.emitEvent(event);
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
`Nenhuma inst\xE2ncia encontrada para o canal ${event.channel.id}`
|
|
1520
|
+
console.log(
|
|
1521
|
+
`Event propagated to channel ${event.channel.id}: ${event.type}`
|
|
1292
1522
|
);
|
|
1523
|
+
} else {
|
|
1524
|
+
console.warn(`No instance found for channel ${event.channel.id}`);
|
|
1293
1525
|
}
|
|
1294
1526
|
}
|
|
1295
1527
|
}
|
|
1296
1528
|
/**
|
|
1297
|
-
*
|
|
1529
|
+
* Initiates a new channel.
|
|
1298
1530
|
*/
|
|
1299
1531
|
async originate(data) {
|
|
1300
|
-
|
|
1532
|
+
if (!data.endpoint) {
|
|
1533
|
+
throw new Error("Endpoint is required for channel origination");
|
|
1534
|
+
}
|
|
1535
|
+
try {
|
|
1536
|
+
const channel = await this.baseClient.post("/channels", data);
|
|
1537
|
+
console.log(`Channel originated successfully with ID: ${channel.id}`);
|
|
1538
|
+
return channel;
|
|
1539
|
+
} catch (error) {
|
|
1540
|
+
const message = getErrorMessage(error);
|
|
1541
|
+
console.error(`Error originating channel:`, message);
|
|
1542
|
+
throw new Error(`Failed to originate channel: ${message}`);
|
|
1543
|
+
}
|
|
1301
1544
|
}
|
|
1302
1545
|
/**
|
|
1303
|
-
*
|
|
1546
|
+
* Lists all active channels.
|
|
1304
1547
|
*/
|
|
1305
|
-
async
|
|
1306
|
-
|
|
1548
|
+
async list() {
|
|
1549
|
+
try {
|
|
1550
|
+
const channels = await this.baseClient.get("/channels");
|
|
1551
|
+
if (!Array.isArray(channels)) {
|
|
1552
|
+
throw new Error("API response for /channels is not an array");
|
|
1553
|
+
}
|
|
1554
|
+
console.log(`Retrieved ${channels.length} active channels`);
|
|
1555
|
+
return channels;
|
|
1556
|
+
} catch (error) {
|
|
1557
|
+
const message = getErrorMessage(error);
|
|
1558
|
+
console.error(`Error listing channels:`, message);
|
|
1559
|
+
throw new Error(`Failed to list channels: ${message}`);
|
|
1560
|
+
}
|
|
1307
1561
|
}
|
|
1308
1562
|
/**
|
|
1309
|
-
*
|
|
1563
|
+
* Gets the count of active channel instances.
|
|
1310
1564
|
*/
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1565
|
+
getInstanceCount() {
|
|
1566
|
+
return this.channelInstances.size;
|
|
1567
|
+
}
|
|
1568
|
+
/**
|
|
1569
|
+
* Checks if a channel instance exists.
|
|
1570
|
+
*/
|
|
1571
|
+
hasInstance(channelId) {
|
|
1572
|
+
return this.channelInstances.has(channelId);
|
|
1573
|
+
}
|
|
1574
|
+
/**
|
|
1575
|
+
* Gets all active channel instances.
|
|
1576
|
+
*/
|
|
1577
|
+
getAllInstances() {
|
|
1578
|
+
return new Map(this.channelInstances);
|
|
1317
1579
|
}
|
|
1318
1580
|
/**
|
|
1319
|
-
*
|
|
1581
|
+
* Terminates an active call on the specified channel.
|
|
1582
|
+
*
|
|
1583
|
+
* @param {string} channelId - The unique identifier of the channel to hang up.
|
|
1584
|
+
* @param {Object} [options] - Optional parameters for the hangup request.
|
|
1585
|
+
* @param {string} [options.reason_code] - A code indicating the reason for the hangup.
|
|
1586
|
+
* @param {string} [options.reason] - A descriptive reason for the hangup.
|
|
1587
|
+
* @return {Promise<void>} A promise that resolves when the call has been successfully terminated.
|
|
1320
1588
|
*/
|
|
1321
1589
|
async hangup(channelId, options) {
|
|
1322
1590
|
const queryParams = new URLSearchParams({
|
|
@@ -1328,7 +1596,11 @@ var Channels = class {
|
|
|
1328
1596
|
);
|
|
1329
1597
|
}
|
|
1330
1598
|
/**
|
|
1331
|
-
*
|
|
1599
|
+
* Initiates snooping on a specified channel with the provided options.
|
|
1600
|
+
*
|
|
1601
|
+
* @param {string} channelId - The unique identifier of the channel to snoop on.
|
|
1602
|
+
* @param {SnoopOptions} options - Configuration options for the snooping operation.
|
|
1603
|
+
* @return {Promise<Channel>} A promise that resolves to the snooped channel data.
|
|
1332
1604
|
*/
|
|
1333
1605
|
async snoopChannel(channelId, options) {
|
|
1334
1606
|
const queryParams = toQueryParams2(options);
|
|
@@ -1336,23 +1608,56 @@ var Channels = class {
|
|
|
1336
1608
|
`/channels/${channelId}/snoop?${queryParams}`
|
|
1337
1609
|
);
|
|
1338
1610
|
}
|
|
1611
|
+
/**
|
|
1612
|
+
* Starts a silence mode for the specified channel.
|
|
1613
|
+
*
|
|
1614
|
+
* @param {string} channelId - The unique identifier of the channel where silence mode should be started.
|
|
1615
|
+
* @return {Promise<void>} A promise that resolves when the silence mode is successfully started.
|
|
1616
|
+
*/
|
|
1339
1617
|
async startSilence(channelId) {
|
|
1340
1618
|
return this.baseClient.post(`/channels/${channelId}/silence`);
|
|
1341
1619
|
}
|
|
1620
|
+
/**
|
|
1621
|
+
* Stops the silence mode for a specific channel.
|
|
1622
|
+
*
|
|
1623
|
+
* @param {string} channelId - The unique identifier of the channel for which silence mode should be stopped.
|
|
1624
|
+
* @return {Promise<void>} A promise that resolves when the operation is complete.
|
|
1625
|
+
*/
|
|
1342
1626
|
async stopSilence(channelId) {
|
|
1343
1627
|
return this.baseClient.delete(`/channels/${channelId}/silence`);
|
|
1344
1628
|
}
|
|
1629
|
+
/**
|
|
1630
|
+
* Retrieves the Real-Time Protocol (RTP) statistics for a specific channel.
|
|
1631
|
+
*
|
|
1632
|
+
* @param {string} channelId - The unique identifier of the channel for which RTP statistics are fetched.
|
|
1633
|
+
* @return {Promise<RTPStats>} A promise that resolves to the RTP statistics for the specified channel.
|
|
1634
|
+
*/
|
|
1345
1635
|
async getRTPStatistics(channelId) {
|
|
1346
1636
|
return this.baseClient.get(
|
|
1347
1637
|
`/channels/${channelId}/rtp_statistics`
|
|
1348
1638
|
);
|
|
1349
1639
|
}
|
|
1640
|
+
/**
|
|
1641
|
+
* Creates an external media channel with the given options.
|
|
1642
|
+
*
|
|
1643
|
+
* @param {ExternalMediaOptions} options - The configuration options for creating the external media channel.
|
|
1644
|
+
* @return {Promise<Channel>} A promise that resolves with the created external media channel.
|
|
1645
|
+
*/
|
|
1350
1646
|
async createExternalMedia(options) {
|
|
1351
1647
|
const queryParams = toQueryParams2(options);
|
|
1352
1648
|
return this.baseClient.post(
|
|
1353
1649
|
`/channels/externalMedia?${queryParams}`
|
|
1354
1650
|
);
|
|
1355
1651
|
}
|
|
1652
|
+
/**
|
|
1653
|
+
* Initiates playback of a specific media item on a channel using the provided playback ID.
|
|
1654
|
+
*
|
|
1655
|
+
* @param {string} channelId - The unique identifier of the channel where playback will occur.
|
|
1656
|
+
* @param {string} playbackId - The unique identifier for the specific playback session.
|
|
1657
|
+
* @param {string} media - The media content to be played.
|
|
1658
|
+
* @param {PlaybackOptions} [options] - Optional playback configuration parameters.
|
|
1659
|
+
* @return {Promise<ChannelPlayback>} A promise that resolves with the playback details for the channel.
|
|
1660
|
+
*/
|
|
1356
1661
|
async playWithId(channelId, playbackId, media, options) {
|
|
1357
1662
|
const queryParams = options ? `?${toQueryParams2(options)}` : "";
|
|
1358
1663
|
return this.baseClient.post(
|
|
@@ -1360,18 +1665,41 @@ var Channels = class {
|
|
|
1360
1665
|
{ media }
|
|
1361
1666
|
);
|
|
1362
1667
|
}
|
|
1668
|
+
/**
|
|
1669
|
+
* Initiates a snoop operation on a specific channel using the provided channel ID and snoop ID.
|
|
1670
|
+
*
|
|
1671
|
+
* @param {string} channelId - The unique identifier of the channel to snoop on.
|
|
1672
|
+
* @param {string} snoopId - The unique identifier for the snoop operation.
|
|
1673
|
+
* @param {SnoopOptions} options - Additional options and parameters for the snoop operation.
|
|
1674
|
+
* @return {Promise<Channel>} A promise that resolves to the channel details after the snoop operation is initiated.
|
|
1675
|
+
*/
|
|
1363
1676
|
async snoopChannelWithId(channelId, snoopId, options) {
|
|
1364
1677
|
const queryParams = toQueryParams2(options);
|
|
1365
1678
|
return this.baseClient.post(
|
|
1366
1679
|
`/channels/${channelId}/snoop/${snoopId}?${queryParams}`
|
|
1367
1680
|
);
|
|
1368
1681
|
}
|
|
1682
|
+
/**
|
|
1683
|
+
* Starts Music on Hold for the specified channel with the provided Music on Hold class.
|
|
1684
|
+
*
|
|
1685
|
+
* @param {string} channelId - The unique identifier of the channel.
|
|
1686
|
+
* @param {string} mohClass - The Music on Hold class to be applied.
|
|
1687
|
+
* @return {Promise<void>} A promise that resolves when the operation is complete.
|
|
1688
|
+
*/
|
|
1369
1689
|
async startMohWithClass(channelId, mohClass) {
|
|
1370
1690
|
const queryParams = `mohClass=${encodeURIComponent(mohClass)}`;
|
|
1371
1691
|
await this.baseClient.post(
|
|
1372
1692
|
`/channels/${channelId}/moh?${queryParams}`
|
|
1373
1693
|
);
|
|
1374
1694
|
}
|
|
1695
|
+
/**
|
|
1696
|
+
* Retrieves the value of a specified variable for a given channel.
|
|
1697
|
+
*
|
|
1698
|
+
* @param {string} channelId - The unique identifier of the channel.
|
|
1699
|
+
* @param {string} variable - The name of the variable to retrieve.
|
|
1700
|
+
* @return {Promise<ChannelVar>} A promise that resolves to the value of the channel variable.
|
|
1701
|
+
* @throws {Error} Throws an error if the 'variable' parameter is not provided.
|
|
1702
|
+
*/
|
|
1375
1703
|
async getChannelVariable(channelId, variable) {
|
|
1376
1704
|
if (!variable) {
|
|
1377
1705
|
throw new Error("The 'variable' parameter is required.");
|
|
@@ -1380,6 +1708,15 @@ var Channels = class {
|
|
|
1380
1708
|
`/channels/${channelId}/variable?variable=${encodeURIComponent(variable)}`
|
|
1381
1709
|
);
|
|
1382
1710
|
}
|
|
1711
|
+
/**
|
|
1712
|
+
* Sets a variable for a specific channel.
|
|
1713
|
+
*
|
|
1714
|
+
* @param {string} channelId - The unique identifier of the channel.
|
|
1715
|
+
* @param {string} variable - The name of the variable to be set. This parameter is required.
|
|
1716
|
+
* @param {string} [value] - The value of the variable to be set. This parameter is optional.
|
|
1717
|
+
* @return {Promise<void>} A promise that resolves when the variable is successfully set.
|
|
1718
|
+
* @throws {Error} Throws an error if the `variable` parameter is not provided.
|
|
1719
|
+
*/
|
|
1383
1720
|
async setChannelVariable(channelId, variable, value) {
|
|
1384
1721
|
if (!variable) {
|
|
1385
1722
|
throw new Error("The 'variable' parameter is required.");
|
|
@@ -1392,12 +1729,30 @@ var Channels = class {
|
|
|
1392
1729
|
`/channels/${channelId}/variable?${queryParams}`
|
|
1393
1730
|
);
|
|
1394
1731
|
}
|
|
1732
|
+
/**
|
|
1733
|
+
* Moves a specified channel to the given application with optional arguments.
|
|
1734
|
+
*
|
|
1735
|
+
* @param {string} channelId - The unique identifier of the channel to be moved.
|
|
1736
|
+
* @param {string} app - The target application to which the channel will be moved.
|
|
1737
|
+
* @param {string} [appArgs] - Optional arguments to be passed to the target application.
|
|
1738
|
+
* @return {Promise<void>} A promise that resolves when the operation is completed.
|
|
1739
|
+
*/
|
|
1395
1740
|
async moveToApplication(channelId, app, appArgs) {
|
|
1396
1741
|
await this.baseClient.post(`/channels/${channelId}/move`, {
|
|
1397
1742
|
app,
|
|
1398
1743
|
appArgs
|
|
1399
1744
|
});
|
|
1400
1745
|
}
|
|
1746
|
+
/**
|
|
1747
|
+
* Continues the execution of a dialplan for a specific channel.
|
|
1748
|
+
*
|
|
1749
|
+
* @param {string} channelId - The unique identifier of the channel.
|
|
1750
|
+
* @param {string} [context] - The dialplan context to continue execution in, if specified.
|
|
1751
|
+
* @param {string} [extension] - The dialplan extension to proceed with, if provided.
|
|
1752
|
+
* @param {number} [priority] - The priority within the dialplan extension to resume at, if specified.
|
|
1753
|
+
* @param {string} [label] - The label to start from within the dialplan, if given.
|
|
1754
|
+
* @return {Promise<void>} Resolves when the dialplan is successfully continued.
|
|
1755
|
+
*/
|
|
1401
1756
|
async continueDialplan(channelId, context, extension, priority, label) {
|
|
1402
1757
|
await this.baseClient.post(`/channels/${channelId}/continue`, {
|
|
1403
1758
|
context,
|
|
@@ -1406,18 +1761,45 @@ var Channels = class {
|
|
|
1406
1761
|
label
|
|
1407
1762
|
});
|
|
1408
1763
|
}
|
|
1764
|
+
/**
|
|
1765
|
+
* Stops the music on hold for the specified channel.
|
|
1766
|
+
*
|
|
1767
|
+
* @param {string} channelId - The unique identifier of the channel where music on hold should be stopped.
|
|
1768
|
+
* @return {Promise<void>} Resolves when the music on hold is successfully stopped.
|
|
1769
|
+
*/
|
|
1409
1770
|
async stopMusicOnHold(channelId) {
|
|
1410
1771
|
await this.baseClient.delete(`/channels/${channelId}/moh`);
|
|
1411
1772
|
}
|
|
1773
|
+
/**
|
|
1774
|
+
* Initiates the music on hold for the specified channel.
|
|
1775
|
+
*
|
|
1776
|
+
* @param {string} channelId - The unique identifier of the channel where the music on hold will be started.
|
|
1777
|
+
* @return {Promise<void>} A promise that resolves when the operation has been successfully invoked.
|
|
1778
|
+
*/
|
|
1412
1779
|
async startMusicOnHold(channelId) {
|
|
1413
1780
|
await this.baseClient.post(`/channels/${channelId}/moh`);
|
|
1414
1781
|
}
|
|
1782
|
+
/**
|
|
1783
|
+
* Starts recording for a specific channel based on the provided options.
|
|
1784
|
+
*
|
|
1785
|
+
* @param {string} channelId - The unique identifier of the channel to start recording.
|
|
1786
|
+
* @param {RecordingOptions} options - The recording options to configure the recording process.
|
|
1787
|
+
* @return {Promise<Channel>} A promise that resolves to the channel object with updated recording state.
|
|
1788
|
+
*/
|
|
1415
1789
|
async record(channelId, options) {
|
|
1416
1790
|
const queryParams = toQueryParams2(options);
|
|
1417
1791
|
return this.baseClient.post(
|
|
1418
1792
|
`/channels/${channelId}/record?${queryParams}`
|
|
1419
1793
|
);
|
|
1420
1794
|
}
|
|
1795
|
+
/**
|
|
1796
|
+
* Initiates a call on the specified channel with optional parameters for caller identification and timeout duration.
|
|
1797
|
+
*
|
|
1798
|
+
* @param {string} channelId - The ID of the channel where the call will be initiated.
|
|
1799
|
+
* @param {string} [caller] - Optional parameter specifying the name or identifier of the caller.
|
|
1800
|
+
* @param {number} [timeout] - Optional parameter defining the timeout duration for the call in seconds.
|
|
1801
|
+
* @return {Promise<void>} A promise that resolves when the call has been successfully initiated.
|
|
1802
|
+
*/
|
|
1421
1803
|
async dial(channelId, caller, timeout) {
|
|
1422
1804
|
const queryParams = new URLSearchParams({
|
|
1423
1805
|
...caller && { caller },
|
|
@@ -1427,45 +1809,126 @@ var Channels = class {
|
|
|
1427
1809
|
`/channels/${channelId}/dial?${queryParams}`
|
|
1428
1810
|
);
|
|
1429
1811
|
}
|
|
1812
|
+
/**
|
|
1813
|
+
* Redirects a channel to the specified endpoint.
|
|
1814
|
+
*
|
|
1815
|
+
* This method sends a POST request to update the redirect endpoint for the given channel.
|
|
1816
|
+
*
|
|
1817
|
+
* @param {string} channelId - The unique identifier of the channel to be redirected.
|
|
1818
|
+
* @param {string} endpoint - The new endpoint to redirect the channel to.
|
|
1819
|
+
* @return {Promise<void>} A promise that resolves when the operation is complete.
|
|
1820
|
+
*/
|
|
1430
1821
|
async redirectChannel(channelId, endpoint) {
|
|
1431
1822
|
await this.baseClient.post(
|
|
1432
1823
|
`/channels/${channelId}/redirect?endpoint=${encodeURIComponent(endpoint)}`
|
|
1433
1824
|
);
|
|
1434
1825
|
}
|
|
1826
|
+
/**
|
|
1827
|
+
* Answers a specified channel by sending a POST request to the corresponding endpoint.
|
|
1828
|
+
*
|
|
1829
|
+
* @param {string} channelId - The unique identifier of the channel to be answered.
|
|
1830
|
+
* @return {Promise<void>} A promise that resolves when the channel has been successfully answered.
|
|
1831
|
+
*/
|
|
1435
1832
|
async answerChannel(channelId) {
|
|
1436
1833
|
await this.baseClient.post(`/channels/${channelId}/answer`);
|
|
1437
1834
|
}
|
|
1835
|
+
/**
|
|
1836
|
+
* Rings the specified channel by sending a POST request to the appropriate endpoint.
|
|
1837
|
+
*
|
|
1838
|
+
* @param {string} channelId - The unique identifier of the channel to be rung.
|
|
1839
|
+
* @return {Promise<void>} A promise that resolves when the operation completes successfully.
|
|
1840
|
+
*/
|
|
1438
1841
|
async ringChannel(channelId) {
|
|
1439
1842
|
await this.baseClient.post(`/channels/${channelId}/ring`);
|
|
1440
1843
|
}
|
|
1844
|
+
/**
|
|
1845
|
+
* Stops the ring channel for the specified channel ID.
|
|
1846
|
+
*
|
|
1847
|
+
* This method sends a DELETE request to the server to stop the ring action
|
|
1848
|
+
* associated with the provided channel ID.
|
|
1849
|
+
*
|
|
1850
|
+
* @param {string} channelId - The unique identifier of the channel for which the ring action should be stopped.
|
|
1851
|
+
* @return {Promise<void>} A promise that resolves when the ring channel is successfully stopped.
|
|
1852
|
+
*/
|
|
1441
1853
|
async stopRingChannel(channelId) {
|
|
1442
1854
|
await this.baseClient.delete(`/channels/${channelId}/ring`);
|
|
1443
1855
|
}
|
|
1856
|
+
/**
|
|
1857
|
+
* Sends DTMF (Dual-Tone Multi-Frequency) signals to a specified channel.
|
|
1858
|
+
*
|
|
1859
|
+
* @param {string} channelId - The ID of the channel to which the DTMF signals should be sent.
|
|
1860
|
+
* @param {string} dtmf - The DTMF tones to be sent, represented as a string. Each character corresponds to a specific tone.
|
|
1861
|
+
* @param {Object} [options] - Optional configuration for the DTMF signal timing.
|
|
1862
|
+
* @param {number} [options.before] - Time in milliseconds to wait before sending the first DTMF tone.
|
|
1863
|
+
* @param {number} [options.between] - Time in milliseconds to wait between sending successive DTMF tones.
|
|
1864
|
+
* @param {number} [options.duration] - Duration in milliseconds for each DTMF tone.
|
|
1865
|
+
* @param {number} [options.after] - Time in milliseconds to wait after sending the last DTMF tone.
|
|
1866
|
+
* @return {Promise<void>} A promise that resolves when the DTMF signals are successfully sent.
|
|
1867
|
+
*/
|
|
1444
1868
|
async sendDTMF(channelId, dtmf, options) {
|
|
1445
1869
|
const queryParams = toQueryParams2({ dtmf, ...options });
|
|
1446
1870
|
await this.baseClient.post(
|
|
1447
1871
|
`/channels/${channelId}/dtmf?${queryParams}`
|
|
1448
1872
|
);
|
|
1449
1873
|
}
|
|
1874
|
+
/**
|
|
1875
|
+
* Mutes a specified channel in the given direction.
|
|
1876
|
+
*
|
|
1877
|
+
* @param {string} channelId - The unique identifier of the channel to be muted.
|
|
1878
|
+
* @param {"both" | "in" | "out"} [direction="both"] - The direction for muting, can be "both", "in", or "out". Default is "both".
|
|
1879
|
+
* @return {Promise<void>} A promise that resolves when the channel is successfully muted.
|
|
1880
|
+
*/
|
|
1450
1881
|
async muteChannel(channelId, direction = "both") {
|
|
1451
1882
|
await this.baseClient.post(
|
|
1452
1883
|
`/channels/${channelId}/mute?direction=${direction}`
|
|
1453
1884
|
);
|
|
1454
1885
|
}
|
|
1886
|
+
/**
|
|
1887
|
+
* Unmutes a previously muted channel, allowing communication in the specified direction(s).
|
|
1888
|
+
*
|
|
1889
|
+
* @param {string} channelId - The unique identifier of the channel to be unmuted.
|
|
1890
|
+
* @param {"both" | "in" | "out"} [direction="both"] - The direction of communication to unmute. Valid options are "both", "in" (incoming messages), or "out" (outgoing messages). Defaults to "both".
|
|
1891
|
+
* @return {Promise<void>} A promise that resolves when the channel is successfully unmuted.
|
|
1892
|
+
*/
|
|
1455
1893
|
async unmuteChannel(channelId, direction = "both") {
|
|
1456
1894
|
await this.baseClient.delete(
|
|
1457
1895
|
`/channels/${channelId}/mute?direction=${direction}`
|
|
1458
1896
|
);
|
|
1459
1897
|
}
|
|
1898
|
+
/**
|
|
1899
|
+
* Places a specific channel on hold by sending a POST request to the server.
|
|
1900
|
+
*
|
|
1901
|
+
* @param {string} channelId - The unique identifier of the channel to be placed on hold.
|
|
1902
|
+
* @return {Promise<void>} A promise that resolves when the channel hold operation is completed.
|
|
1903
|
+
*/
|
|
1460
1904
|
async holdChannel(channelId) {
|
|
1461
1905
|
await this.baseClient.post(`/channels/${channelId}/hold`);
|
|
1462
1906
|
}
|
|
1907
|
+
/**
|
|
1908
|
+
* Removes the hold status from a specific channel by its ID.
|
|
1909
|
+
*
|
|
1910
|
+
* @param {string} channelId - The unique identifier of the channel to unhold.
|
|
1911
|
+
* @return {Promise<void>} A promise that resolves when the channel hold is successfully removed.
|
|
1912
|
+
*/
|
|
1463
1913
|
async unholdChannel(channelId) {
|
|
1464
1914
|
await this.baseClient.delete(`/channels/${channelId}/hold`);
|
|
1465
1915
|
}
|
|
1916
|
+
/**
|
|
1917
|
+
* Creates a new communication channel with the specified configuration.
|
|
1918
|
+
*
|
|
1919
|
+
* @param {OriginateRequest} data - The configuration data required to create the channel, including relevant details such as endpoint and channel variables.
|
|
1920
|
+
* @return {Promise<Channel>} A promise that resolves with the details of the created channel.
|
|
1921
|
+
*/
|
|
1466
1922
|
async createChannel(data) {
|
|
1467
1923
|
return this.baseClient.post("/channels/create", data);
|
|
1468
1924
|
}
|
|
1925
|
+
/**
|
|
1926
|
+
* Initiates a new channel with the specified channel ID and originates a call using the provided data.
|
|
1927
|
+
*
|
|
1928
|
+
* @param {string} channelId - The unique identifier of the channel to be created.
|
|
1929
|
+
* @param {OriginateRequest} data - The data required to originate the call, including details such as endpoint and caller information.
|
|
1930
|
+
* @return {Promise<Channel>} A promise that resolves to the created Channel object.
|
|
1931
|
+
*/
|
|
1469
1932
|
async originateWithId(channelId, data) {
|
|
1470
1933
|
return this.baseClient.post(`/channels/${channelId}`, data);
|
|
1471
1934
|
}
|
|
@@ -1519,93 +1982,195 @@ var Endpoints = class {
|
|
|
1519
1982
|
|
|
1520
1983
|
// src/ari-client/resources/playbacks.ts
|
|
1521
1984
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
1985
|
+
import { isAxiosError as isAxiosError3 } from "axios";
|
|
1986
|
+
var getErrorMessage2 = (error) => {
|
|
1987
|
+
if (isAxiosError3(error)) {
|
|
1988
|
+
return error.response?.data?.message || error.message || "An axios error occurred";
|
|
1989
|
+
}
|
|
1990
|
+
if (error instanceof Error) {
|
|
1991
|
+
return error.message;
|
|
1992
|
+
}
|
|
1993
|
+
return "An unknown error occurred";
|
|
1994
|
+
};
|
|
1522
1995
|
var PlaybackInstance = class {
|
|
1996
|
+
/**
|
|
1997
|
+
* Creates a new PlaybackInstance.
|
|
1998
|
+
*
|
|
1999
|
+
* @param {AriClient} client - ARI client for communication
|
|
2000
|
+
* @param {BaseClient} baseClient - Base client for HTTP requests
|
|
2001
|
+
* @param {string} [playbackId] - Optional playback ID, generates timestamp-based ID if not provided
|
|
2002
|
+
*/
|
|
1523
2003
|
constructor(client, baseClient, playbackId = `playback-${Date.now()}`) {
|
|
1524
2004
|
this.client = client;
|
|
1525
2005
|
this.baseClient = baseClient;
|
|
1526
2006
|
this.playbackId = playbackId;
|
|
1527
2007
|
this.id = playbackId;
|
|
2008
|
+
console.log(`PlaybackInstance initialized with ID: ${this.id}`);
|
|
1528
2009
|
}
|
|
1529
2010
|
eventEmitter = new EventEmitter2();
|
|
1530
2011
|
playbackData = null;
|
|
1531
2012
|
id;
|
|
1532
2013
|
/**
|
|
1533
|
-
*
|
|
2014
|
+
* Registers an event listener for a specific WebSocket event type.
|
|
2015
|
+
*
|
|
2016
|
+
* @param {T} event - Event type to listen for
|
|
2017
|
+
* @param {Function} listener - Callback function for the event
|
|
1534
2018
|
*/
|
|
1535
2019
|
on(event, listener) {
|
|
2020
|
+
if (!event) {
|
|
2021
|
+
throw new Error("Event type is required");
|
|
2022
|
+
}
|
|
1536
2023
|
const wrappedListener = (data) => {
|
|
1537
2024
|
if ("playback" in data && data.playback?.id === this.id) {
|
|
1538
2025
|
listener(data);
|
|
1539
2026
|
}
|
|
1540
2027
|
};
|
|
1541
2028
|
this.eventEmitter.on(event, wrappedListener);
|
|
2029
|
+
console.log(
|
|
2030
|
+
`Event listener registered for ${event} on playback ${this.id}`
|
|
2031
|
+
);
|
|
1542
2032
|
}
|
|
1543
2033
|
/**
|
|
1544
|
-
*
|
|
2034
|
+
* Registers a one-time event listener for a specific WebSocket event type.
|
|
2035
|
+
*
|
|
2036
|
+
* @param {T} event - Event type to listen for
|
|
2037
|
+
* @param {Function} listener - Callback function for the event
|
|
1545
2038
|
*/
|
|
1546
2039
|
once(event, listener) {
|
|
2040
|
+
if (!event) {
|
|
2041
|
+
throw new Error("Event type is required");
|
|
2042
|
+
}
|
|
1547
2043
|
const wrappedListener = (data) => {
|
|
1548
2044
|
if ("playback" in data && data.playback?.id === this.id) {
|
|
1549
2045
|
listener(data);
|
|
1550
2046
|
}
|
|
1551
2047
|
};
|
|
1552
2048
|
this.eventEmitter.once(event, wrappedListener);
|
|
2049
|
+
console.log(
|
|
2050
|
+
`One-time event listener registered for ${event} on playback ${this.id}`
|
|
2051
|
+
);
|
|
1553
2052
|
}
|
|
1554
2053
|
/**
|
|
1555
|
-
*
|
|
2054
|
+
* Removes event listener(s) for a specific WebSocket event type.
|
|
2055
|
+
*
|
|
2056
|
+
* @param {T} event - Event type to remove listener(s) for
|
|
2057
|
+
* @param {Function} [listener] - Optional specific listener to remove
|
|
1556
2058
|
*/
|
|
1557
2059
|
off(event, listener) {
|
|
2060
|
+
if (!event) {
|
|
2061
|
+
throw new Error("Event type is required");
|
|
2062
|
+
}
|
|
1558
2063
|
if (listener) {
|
|
1559
2064
|
this.eventEmitter.off(event, listener);
|
|
2065
|
+
console.log(
|
|
2066
|
+
`Specific listener removed for ${event} on playback ${this.id}`
|
|
2067
|
+
);
|
|
1560
2068
|
} else {
|
|
1561
2069
|
this.eventEmitter.removeAllListeners(event);
|
|
2070
|
+
console.log(`All listeners removed for ${event} on playback ${this.id}`);
|
|
1562
2071
|
}
|
|
1563
2072
|
}
|
|
1564
2073
|
/**
|
|
1565
|
-
*
|
|
2074
|
+
* Emits a WebSocket event if it matches the current playback instance.
|
|
2075
|
+
*
|
|
2076
|
+
* @param {WebSocketEvent} event - Event to emit
|
|
1566
2077
|
*/
|
|
1567
2078
|
emitEvent(event) {
|
|
2079
|
+
if (!event) {
|
|
2080
|
+
console.warn("Received invalid event");
|
|
2081
|
+
return;
|
|
2082
|
+
}
|
|
1568
2083
|
if ("playback" in event && event.playback?.id === this.id) {
|
|
1569
2084
|
this.eventEmitter.emit(event.type, event);
|
|
2085
|
+
console.log(`Event ${event.type} emitted for playback ${this.id}`);
|
|
1570
2086
|
}
|
|
1571
2087
|
}
|
|
1572
2088
|
/**
|
|
1573
|
-
*
|
|
2089
|
+
* Retrieves current playback data.
|
|
2090
|
+
*
|
|
2091
|
+
* @returns {Promise<Playback>} Current playback data
|
|
2092
|
+
* @throws {Error} If playback is not properly initialized
|
|
1574
2093
|
*/
|
|
1575
2094
|
async get() {
|
|
1576
2095
|
if (!this.id) {
|
|
1577
|
-
throw new Error("
|
|
2096
|
+
throw new Error("No playback associated with this instance");
|
|
2097
|
+
}
|
|
2098
|
+
try {
|
|
2099
|
+
this.playbackData = await this.baseClient.get(
|
|
2100
|
+
`/playbacks/${this.id}`
|
|
2101
|
+
);
|
|
2102
|
+
console.log(`Retrieved playback data for ${this.id}`);
|
|
2103
|
+
return this.playbackData;
|
|
2104
|
+
} catch (error) {
|
|
2105
|
+
const message = getErrorMessage2(error);
|
|
2106
|
+
console.error(`Error retrieving playback data for ${this.id}:`, message);
|
|
2107
|
+
throw new Error(`Failed to get playback data: ${message}`);
|
|
1578
2108
|
}
|
|
1579
|
-
this.playbackData = await this.baseClient.get(
|
|
1580
|
-
`/playbacks/${this.id}`
|
|
1581
|
-
);
|
|
1582
|
-
return this.playbackData;
|
|
1583
2109
|
}
|
|
1584
2110
|
/**
|
|
1585
|
-
*
|
|
2111
|
+
* Controls playback with specified operation.
|
|
2112
|
+
*
|
|
2113
|
+
* @param {"pause" | "unpause" | "reverse" | "forward"} operation - Control operation to perform
|
|
2114
|
+
* @throws {Error} If playback is not properly initialized or operation fails
|
|
1586
2115
|
*/
|
|
1587
2116
|
async control(operation) {
|
|
1588
2117
|
if (!this.id) {
|
|
1589
|
-
throw new Error("
|
|
2118
|
+
throw new Error("No playback associated with this instance");
|
|
2119
|
+
}
|
|
2120
|
+
try {
|
|
2121
|
+
await this.baseClient.post(
|
|
2122
|
+
`/playbacks/${this.id}/control?operation=${operation}`
|
|
2123
|
+
);
|
|
2124
|
+
console.log(
|
|
2125
|
+
`Operation ${operation} executed successfully on playback ${this.id}`
|
|
2126
|
+
);
|
|
2127
|
+
} catch (error) {
|
|
2128
|
+
const message = getErrorMessage2(error);
|
|
2129
|
+
console.error(`Error controlling playback ${this.id}:`, message);
|
|
2130
|
+
throw new Error(`Failed to control playback: ${message}`);
|
|
1590
2131
|
}
|
|
1591
|
-
await this.baseClient.post(
|
|
1592
|
-
`/playbacks/${this.id}/control?operation=${operation}`
|
|
1593
|
-
);
|
|
1594
2132
|
}
|
|
1595
2133
|
/**
|
|
1596
|
-
*
|
|
2134
|
+
* Stops the current playback.
|
|
2135
|
+
*
|
|
2136
|
+
* @throws {Error} If playback is not properly initialized or stop operation fails
|
|
1597
2137
|
*/
|
|
1598
2138
|
async stop() {
|
|
1599
2139
|
if (!this.id) {
|
|
1600
|
-
throw new Error("
|
|
2140
|
+
throw new Error("No playback associated with this instance");
|
|
2141
|
+
}
|
|
2142
|
+
try {
|
|
2143
|
+
await this.baseClient.delete(`/playbacks/${this.id}`);
|
|
2144
|
+
console.log(`Playback ${this.id} stopped successfully`);
|
|
2145
|
+
} catch (error) {
|
|
2146
|
+
const message = getErrorMessage2(error);
|
|
2147
|
+
console.error(`Error stopping playback ${this.id}:`, message);
|
|
2148
|
+
throw new Error(`Failed to stop playback: ${message}`);
|
|
1601
2149
|
}
|
|
1602
|
-
await this.baseClient.delete(`/playbacks/${this.id}`);
|
|
1603
2150
|
}
|
|
1604
2151
|
/**
|
|
1605
|
-
*
|
|
2152
|
+
* Removes all event listeners from this playback instance.
|
|
1606
2153
|
*/
|
|
1607
2154
|
removeAllListeners() {
|
|
1608
2155
|
this.eventEmitter.removeAllListeners();
|
|
2156
|
+
console.log(`All listeners removed from playback ${this.id}`);
|
|
2157
|
+
}
|
|
2158
|
+
/**
|
|
2159
|
+
* Checks if the playback instance has any listeners for a specific event.
|
|
2160
|
+
*
|
|
2161
|
+
* @param {string} event - Event type to check
|
|
2162
|
+
* @returns {boolean} True if there are listeners for the event
|
|
2163
|
+
*/
|
|
2164
|
+
hasListeners(event) {
|
|
2165
|
+
return this.eventEmitter.listenerCount(event) > 0;
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* Gets the current playback data without making an API call.
|
|
2169
|
+
*
|
|
2170
|
+
* @returns {Playback | null} Current playback data or null if not available
|
|
2171
|
+
*/
|
|
2172
|
+
getCurrentData() {
|
|
2173
|
+
return this.playbackData;
|
|
1609
2174
|
}
|
|
1610
2175
|
};
|
|
1611
2176
|
var Playbacks = class {
|
|
@@ -1615,61 +2180,144 @@ var Playbacks = class {
|
|
|
1615
2180
|
}
|
|
1616
2181
|
playbackInstances = /* @__PURE__ */ new Map();
|
|
1617
2182
|
/**
|
|
1618
|
-
*
|
|
2183
|
+
* Gets or creates a playback instance
|
|
2184
|
+
* @param {Object} [params] - Optional parameters for getting/creating a playback instance
|
|
2185
|
+
* @param {string} [params.id] - Optional ID of an existing playback
|
|
2186
|
+
* @returns {PlaybackInstance} The requested or new playback instance
|
|
1619
2187
|
*/
|
|
1620
|
-
Playback(
|
|
1621
|
-
|
|
1622
|
-
const
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
2188
|
+
Playback(params) {
|
|
2189
|
+
try {
|
|
2190
|
+
const id = params?.id;
|
|
2191
|
+
if (!id) {
|
|
2192
|
+
const instance = new PlaybackInstance(this.client, this.baseClient);
|
|
2193
|
+
this.playbackInstances.set(instance.id, instance);
|
|
2194
|
+
console.log(`New playback instance created with ID: ${instance.id}`);
|
|
2195
|
+
return instance;
|
|
2196
|
+
}
|
|
2197
|
+
if (!this.playbackInstances.has(id)) {
|
|
2198
|
+
const instance = new PlaybackInstance(this.client, this.baseClient, id);
|
|
2199
|
+
this.playbackInstances.set(id, instance);
|
|
2200
|
+
console.log(`New playback instance created with provided ID: ${id}`);
|
|
2201
|
+
return instance;
|
|
2202
|
+
}
|
|
2203
|
+
console.log(`Returning existing playback instance: ${id}`);
|
|
2204
|
+
return this.playbackInstances.get(id);
|
|
2205
|
+
} catch (error) {
|
|
2206
|
+
const message = getErrorMessage2(error);
|
|
2207
|
+
console.error(`Error creating/retrieving playback instance:`, message);
|
|
2208
|
+
throw new Error(`Failed to manage playback instance: ${message}`);
|
|
1630
2209
|
}
|
|
1631
|
-
return this.playbackInstances.get(id);
|
|
1632
2210
|
}
|
|
1633
2211
|
/**
|
|
1634
|
-
*
|
|
2212
|
+
* Removes a playback instance and cleans up its resources
|
|
2213
|
+
* @param {string} playbackId - ID of the playback instance to remove
|
|
2214
|
+
* @throws {Error} If the playback instance doesn't exist
|
|
1635
2215
|
*/
|
|
1636
2216
|
removePlaybackInstance(playbackId) {
|
|
2217
|
+
if (!playbackId) {
|
|
2218
|
+
throw new Error("Playback ID is required");
|
|
2219
|
+
}
|
|
1637
2220
|
if (this.playbackInstances.has(playbackId)) {
|
|
1638
2221
|
const instance = this.playbackInstances.get(playbackId);
|
|
1639
2222
|
instance?.removeAllListeners();
|
|
1640
2223
|
this.playbackInstances.delete(playbackId);
|
|
2224
|
+
console.log(`Playback instance removed: ${playbackId}`);
|
|
2225
|
+
} else {
|
|
2226
|
+
console.warn(`Attempt to remove non-existent instance: ${playbackId}`);
|
|
1641
2227
|
}
|
|
1642
2228
|
}
|
|
1643
2229
|
/**
|
|
1644
|
-
*
|
|
2230
|
+
* Propagates WebSocket events to the corresponding playback instance
|
|
2231
|
+
* @param {WebSocketEvent} event - The WebSocket event to propagate
|
|
1645
2232
|
*/
|
|
1646
2233
|
propagateEventToPlayback(event) {
|
|
2234
|
+
if (!event) {
|
|
2235
|
+
console.warn("Invalid WebSocket event received");
|
|
2236
|
+
return;
|
|
2237
|
+
}
|
|
1647
2238
|
if ("playback" in event && event.playback?.id) {
|
|
1648
2239
|
const instance = this.playbackInstances.get(event.playback.id);
|
|
1649
2240
|
if (instance) {
|
|
1650
2241
|
instance.emitEvent(event);
|
|
2242
|
+
console.log(
|
|
2243
|
+
`Event propagated to playback ${event.playback.id}: ${event.type}`
|
|
2244
|
+
);
|
|
2245
|
+
} else {
|
|
2246
|
+
console.warn(`No instance found for playback ${event.playback.id}`);
|
|
1651
2247
|
}
|
|
1652
2248
|
}
|
|
1653
2249
|
}
|
|
1654
2250
|
/**
|
|
1655
|
-
*
|
|
2251
|
+
* Retrieves details of a specific playback
|
|
2252
|
+
* @param {string} playbackId - ID of the playback to get details for
|
|
2253
|
+
* @returns {Promise<Playback>} Promise resolving to playback details
|
|
2254
|
+
* @throws {Error} If the playback ID is invalid or the request fails
|
|
1656
2255
|
*/
|
|
1657
2256
|
async getDetails(playbackId) {
|
|
1658
|
-
|
|
2257
|
+
if (!playbackId) {
|
|
2258
|
+
throw new Error("Playback ID is required");
|
|
2259
|
+
}
|
|
2260
|
+
try {
|
|
2261
|
+
return await this.baseClient.get(`/playbacks/${playbackId}`);
|
|
2262
|
+
} catch (error) {
|
|
2263
|
+
const message = getErrorMessage2(error);
|
|
2264
|
+
console.error(`Error getting playback details ${playbackId}:`, message);
|
|
2265
|
+
throw new Error(`Failed to get playback details: ${message}`);
|
|
2266
|
+
}
|
|
1659
2267
|
}
|
|
1660
2268
|
/**
|
|
1661
|
-
*
|
|
2269
|
+
* Controls a specific playback instance
|
|
2270
|
+
* @param {string} playbackId - ID of the playback to control
|
|
2271
|
+
* @param {"pause" | "unpause" | "reverse" | "forward"} operation - Operation to perform
|
|
2272
|
+
* @throws {Error} If the playback ID is invalid or the operation fails
|
|
1662
2273
|
*/
|
|
1663
2274
|
async control(playbackId, operation) {
|
|
1664
|
-
|
|
1665
|
-
|
|
2275
|
+
if (!playbackId) {
|
|
2276
|
+
throw new Error("Playback ID is required");
|
|
2277
|
+
}
|
|
2278
|
+
try {
|
|
2279
|
+
const playback = this.Playback({ id: playbackId });
|
|
2280
|
+
await playback.control(operation);
|
|
2281
|
+
console.log(`Operation ${operation} executed on playback ${playbackId}`);
|
|
2282
|
+
} catch (error) {
|
|
2283
|
+
const message = getErrorMessage2(error);
|
|
2284
|
+
console.error(`Error controlling playback ${playbackId}:`, message);
|
|
2285
|
+
throw new Error(`Failed to control playback: ${message}`);
|
|
2286
|
+
}
|
|
1666
2287
|
}
|
|
1667
2288
|
/**
|
|
1668
|
-
*
|
|
2289
|
+
* Stops a specific playback instance
|
|
2290
|
+
* @param {string} playbackId - ID of the playback to stop
|
|
2291
|
+
* @throws {Error} If the playback ID is invalid or the stop operation fails
|
|
1669
2292
|
*/
|
|
1670
2293
|
async stop(playbackId) {
|
|
1671
|
-
|
|
1672
|
-
|
|
2294
|
+
if (!playbackId) {
|
|
2295
|
+
throw new Error("Playback ID is required");
|
|
2296
|
+
}
|
|
2297
|
+
try {
|
|
2298
|
+
const playback = this.Playback({ id: playbackId });
|
|
2299
|
+
await playback.stop();
|
|
2300
|
+
console.log(`Playback ${playbackId} stopped`);
|
|
2301
|
+
} catch (error) {
|
|
2302
|
+
const message = getErrorMessage2(error);
|
|
2303
|
+
console.error(`Error stopping playback ${playbackId}:`, message);
|
|
2304
|
+
throw new Error(`Failed to stop playback: ${message}`);
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
/**
|
|
2308
|
+
* Gets the count of active playback instances
|
|
2309
|
+
* @returns {number} Number of active playback instances
|
|
2310
|
+
*/
|
|
2311
|
+
getInstanceCount() {
|
|
2312
|
+
return this.playbackInstances.size;
|
|
2313
|
+
}
|
|
2314
|
+
/**
|
|
2315
|
+
* Checks if a playback instance exists
|
|
2316
|
+
* @param {string} playbackId - ID of the playback to check
|
|
2317
|
+
* @returns {boolean} True if the playback instance exists
|
|
2318
|
+
*/
|
|
2319
|
+
hasInstance(playbackId) {
|
|
2320
|
+
return this.playbackInstances.has(playbackId);
|
|
1673
2321
|
}
|
|
1674
2322
|
};
|
|
1675
2323
|
|
|
@@ -1708,40 +2356,51 @@ var Sounds = class {
|
|
|
1708
2356
|
var import_exponential_backoff = __toESM(require_backoff(), 1);
|
|
1709
2357
|
import { EventEmitter as EventEmitter3 } from "events";
|
|
1710
2358
|
import WebSocket from "ws";
|
|
2359
|
+
var DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;
|
|
2360
|
+
var DEFAULT_STARTING_DELAY = 500;
|
|
2361
|
+
var DEFAULT_MAX_DELAY = 1e4;
|
|
1711
2362
|
var WebSocketClient = class extends EventEmitter3 {
|
|
2363
|
+
/**
|
|
2364
|
+
* Creates a new WebSocket client instance.
|
|
2365
|
+
*
|
|
2366
|
+
* @param {BaseClient} baseClient - The base client containing connection details
|
|
2367
|
+
* @param {string[]} apps - List of applications to connect to
|
|
2368
|
+
* @param {WebSocketEventType[]} [subscribedEvents] - Optional list of events to subscribe to
|
|
2369
|
+
* @param {AriClient} [ariClient] - Optional ARI client for handling channel and playback events
|
|
2370
|
+
*/
|
|
1712
2371
|
constructor(baseClient, apps, subscribedEvents, ariClient) {
|
|
1713
2372
|
super();
|
|
1714
2373
|
this.baseClient = baseClient;
|
|
1715
2374
|
this.apps = apps;
|
|
1716
2375
|
this.subscribedEvents = subscribedEvents;
|
|
1717
2376
|
this.ariClient = ariClient;
|
|
2377
|
+
if (!apps.length) {
|
|
2378
|
+
throw new Error("At least one application name is required");
|
|
2379
|
+
}
|
|
1718
2380
|
}
|
|
1719
2381
|
ws;
|
|
1720
2382
|
isReconnecting = false;
|
|
1721
|
-
maxReconnectAttempts =
|
|
2383
|
+
maxReconnectAttempts = DEFAULT_MAX_RECONNECT_ATTEMPTS;
|
|
1722
2384
|
backOffOptions = {
|
|
1723
|
-
numOfAttempts:
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
// Início com 500ms de atraso
|
|
1727
|
-
maxDelay: 1e4,
|
|
1728
|
-
// Limite máximo de atraso de 10s
|
|
2385
|
+
numOfAttempts: DEFAULT_MAX_RECONNECT_ATTEMPTS,
|
|
2386
|
+
startingDelay: DEFAULT_STARTING_DELAY,
|
|
2387
|
+
maxDelay: DEFAULT_MAX_DELAY,
|
|
1729
2388
|
timeMultiple: 2,
|
|
1730
|
-
// Atraso aumenta exponencialmente
|
|
1731
2389
|
jitter: "full",
|
|
1732
|
-
// Randomização para evitar colisões
|
|
1733
2390
|
delayFirstAttempt: false,
|
|
1734
|
-
// Não atrase a primeira tentativa
|
|
1735
2391
|
retry: (error, attemptNumber) => {
|
|
1736
2392
|
console.warn(
|
|
1737
|
-
`
|
|
1738
|
-
error.message || error
|
|
2393
|
+
`Connection attempt #${attemptNumber} failed:`,
|
|
2394
|
+
error.message || "Unknown error"
|
|
1739
2395
|
);
|
|
1740
|
-
return
|
|
2396
|
+
return attemptNumber < this.maxReconnectAttempts;
|
|
1741
2397
|
}
|
|
1742
2398
|
};
|
|
1743
2399
|
/**
|
|
1744
|
-
*
|
|
2400
|
+
* Establishes a WebSocket connection.
|
|
2401
|
+
*
|
|
2402
|
+
* @returns {Promise<void>} Resolves when connection is established
|
|
2403
|
+
* @throws {Error} If connection fails
|
|
1745
2404
|
*/
|
|
1746
2405
|
async connect() {
|
|
1747
2406
|
const { baseUrl, username, password } = this.baseClient.getCredentials();
|
|
@@ -1749,7 +2408,7 @@ var WebSocketClient = class extends EventEmitter3 {
|
|
|
1749
2408
|
const normalizedHost = baseUrl.replace(/^https?:\/\//, "").replace(/\/ari$/, "");
|
|
1750
2409
|
const queryParams = new URLSearchParams();
|
|
1751
2410
|
queryParams.append("app", this.apps.join(","));
|
|
1752
|
-
if (this.subscribedEvents
|
|
2411
|
+
if (this.subscribedEvents?.length) {
|
|
1753
2412
|
this.subscribedEvents.forEach(
|
|
1754
2413
|
(event) => queryParams.append("event", event)
|
|
1755
2414
|
);
|
|
@@ -1757,48 +2416,57 @@ var WebSocketClient = class extends EventEmitter3 {
|
|
|
1757
2416
|
queryParams.append("subscribeAll", "true");
|
|
1758
2417
|
}
|
|
1759
2418
|
const wsUrl = `${protocol}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${normalizedHost}/ari/events?${queryParams.toString()}`;
|
|
1760
|
-
console.log("
|
|
2419
|
+
console.log("Connecting to WebSocket...");
|
|
1761
2420
|
return this.initializeWebSocket(wsUrl);
|
|
1762
2421
|
}
|
|
1763
2422
|
/**
|
|
1764
|
-
*
|
|
2423
|
+
* Initializes WebSocket connection with reconnection logic.
|
|
2424
|
+
*
|
|
2425
|
+
* @param {string} wsUrl - The WebSocket URL to connect to
|
|
2426
|
+
* @returns {Promise<void>} Resolves when connection is established
|
|
1765
2427
|
*/
|
|
1766
2428
|
async initializeWebSocket(wsUrl) {
|
|
1767
2429
|
return (0, import_exponential_backoff.backOff)(async () => {
|
|
1768
2430
|
return new Promise((resolve, reject) => {
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
this.
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
this.
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
2431
|
+
try {
|
|
2432
|
+
this.ws = new WebSocket(wsUrl);
|
|
2433
|
+
this.ws.on("open", () => {
|
|
2434
|
+
console.log("WebSocket connection established successfully");
|
|
2435
|
+
this.isReconnecting = false;
|
|
2436
|
+
this.emit("connected");
|
|
2437
|
+
resolve();
|
|
2438
|
+
});
|
|
2439
|
+
this.ws.on("message", (data) => this.handleMessage(data.toString()));
|
|
2440
|
+
this.ws.on("close", (code) => {
|
|
2441
|
+
console.warn(
|
|
2442
|
+
`WebSocket disconnected with code ${code}. Attempting to reconnect...`
|
|
2443
|
+
);
|
|
2444
|
+
if (!this.isReconnecting) {
|
|
2445
|
+
this.reconnect(wsUrl);
|
|
2446
|
+
}
|
|
2447
|
+
});
|
|
2448
|
+
this.ws.on("error", (err) => {
|
|
2449
|
+
console.error("WebSocket error:", err.message);
|
|
2450
|
+
if (!this.isReconnecting) {
|
|
2451
|
+
this.reconnect(wsUrl);
|
|
2452
|
+
}
|
|
2453
|
+
reject(err);
|
|
2454
|
+
});
|
|
2455
|
+
} catch (error) {
|
|
2456
|
+
reject(error);
|
|
2457
|
+
}
|
|
1792
2458
|
});
|
|
1793
2459
|
}, this.backOffOptions);
|
|
1794
2460
|
}
|
|
1795
2461
|
/**
|
|
1796
|
-
*
|
|
2462
|
+
* Processes incoming WebSocket messages.
|
|
2463
|
+
*
|
|
2464
|
+
* @param {string} rawMessage - The raw message received from WebSocket
|
|
1797
2465
|
*/
|
|
1798
2466
|
handleMessage(rawMessage) {
|
|
1799
2467
|
try {
|
|
1800
2468
|
const event = JSON.parse(rawMessage);
|
|
1801
|
-
if (this.subscribedEvents && !this.subscribedEvents.includes(event.type)) {
|
|
2469
|
+
if (this.subscribedEvents?.length && !this.subscribedEvents.includes(event.type)) {
|
|
1802
2470
|
return;
|
|
1803
2471
|
}
|
|
1804
2472
|
if ("channel" in event && event.channel?.id && this.ariClient) {
|
|
@@ -1812,40 +2480,77 @@ var WebSocketClient = class extends EventEmitter3 {
|
|
|
1812
2480
|
event.instancePlayback = instancePlayback;
|
|
1813
2481
|
}
|
|
1814
2482
|
this.emit(event.type, event);
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
2483
|
+
console.log(`Event processed: ${event.type}`);
|
|
2484
|
+
} catch (error) {
|
|
2485
|
+
console.error("Error processing WebSocket message:", error instanceof Error ? error.message : "Unknown error");
|
|
2486
|
+
this.emit("error", new Error("Failed to decode WebSocket message"));
|
|
1818
2487
|
}
|
|
1819
2488
|
}
|
|
1820
2489
|
/**
|
|
1821
|
-
*
|
|
2490
|
+
* Attempts to reconnect to the WebSocket.
|
|
2491
|
+
*
|
|
2492
|
+
* @param {string} wsUrl - The WebSocket URL to reconnect to
|
|
1822
2493
|
*/
|
|
1823
2494
|
reconnect(wsUrl) {
|
|
1824
2495
|
this.isReconnecting = true;
|
|
1825
|
-
console.log("
|
|
2496
|
+
console.log("Initiating reconnection attempt...");
|
|
1826
2497
|
this.removeAllListeners();
|
|
1827
|
-
(0, import_exponential_backoff.backOff)(() => this.initializeWebSocket(wsUrl), this.backOffOptions).catch(
|
|
1828
|
-
(
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
);
|
|
2498
|
+
(0, import_exponential_backoff.backOff)(() => this.initializeWebSocket(wsUrl), this.backOffOptions).catch((error) => {
|
|
2499
|
+
console.error(
|
|
2500
|
+
"Failed to reconnect after multiple attempts:",
|
|
2501
|
+
error instanceof Error ? error.message : "Unknown error"
|
|
2502
|
+
);
|
|
2503
|
+
this.emit("reconnectFailed", error);
|
|
2504
|
+
});
|
|
1835
2505
|
}
|
|
1836
2506
|
/**
|
|
1837
|
-
*
|
|
2507
|
+
* Manually closes the WebSocket connection.
|
|
1838
2508
|
*/
|
|
1839
2509
|
close() {
|
|
1840
|
-
|
|
1841
|
-
|
|
2510
|
+
try {
|
|
2511
|
+
if (this.ws) {
|
|
2512
|
+
this.ws.close();
|
|
2513
|
+
this.ws = void 0;
|
|
2514
|
+
console.log("WebSocket connection closed");
|
|
2515
|
+
}
|
|
2516
|
+
} catch (error) {
|
|
2517
|
+
console.error(
|
|
2518
|
+
"Error closing WebSocket:",
|
|
2519
|
+
error instanceof Error ? error.message : "Unknown error"
|
|
2520
|
+
);
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
/**
|
|
2524
|
+
* Checks if the WebSocket is currently connected.
|
|
2525
|
+
*
|
|
2526
|
+
* @returns {boolean} True if connected, false otherwise
|
|
2527
|
+
*/
|
|
2528
|
+
isConnected() {
|
|
2529
|
+
return this.ws?.readyState === WebSocket.OPEN;
|
|
2530
|
+
}
|
|
2531
|
+
/**
|
|
2532
|
+
* Gets the current connection state.
|
|
2533
|
+
*
|
|
2534
|
+
* @returns {number} The WebSocket ready state
|
|
2535
|
+
*/
|
|
2536
|
+
getState() {
|
|
2537
|
+
return this.ws?.readyState ?? WebSocket.CLOSED;
|
|
1842
2538
|
}
|
|
1843
2539
|
};
|
|
1844
2540
|
|
|
1845
2541
|
// src/ari-client/ariClient.ts
|
|
1846
2542
|
var AriClient = class {
|
|
2543
|
+
/**
|
|
2544
|
+
* Creates a new instance of the ARI client.
|
|
2545
|
+
*
|
|
2546
|
+
* @param {AriClientConfig} config - Configuration options for the ARI client
|
|
2547
|
+
* @throws {Error} If required configuration parameters are missing
|
|
2548
|
+
*/
|
|
1847
2549
|
constructor(config) {
|
|
1848
2550
|
this.config = config;
|
|
2551
|
+
if (!config.host || !config.port || !config.username || !config.password) {
|
|
2552
|
+
throw new Error("Missing required configuration parameters");
|
|
2553
|
+
}
|
|
1849
2554
|
const httpProtocol = config.secure ? "https" : "http";
|
|
1850
2555
|
const normalizedHost = config.host.replace(/^https?:\/\//, "");
|
|
1851
2556
|
const baseUrl = `${httpProtocol}://${normalizedHost}:${config.port}/ari`;
|
|
@@ -1857,6 +2562,7 @@ var AriClient = class {
|
|
|
1857
2562
|
this.sounds = new Sounds(this.baseClient);
|
|
1858
2563
|
this.asterisk = new Asterisk(this.baseClient);
|
|
1859
2564
|
this.bridges = new Bridges(this.baseClient);
|
|
2565
|
+
console.log(`ARI Client initialized with base URL: ${baseUrl}`);
|
|
1860
2566
|
}
|
|
1861
2567
|
baseClient;
|
|
1862
2568
|
webSocketClient;
|
|
@@ -1868,58 +2574,117 @@ var AriClient = class {
|
|
|
1868
2574
|
asterisk;
|
|
1869
2575
|
bridges;
|
|
1870
2576
|
/**
|
|
1871
|
-
*
|
|
2577
|
+
* Initializes a WebSocket connection for receiving events.
|
|
2578
|
+
*
|
|
2579
|
+
* @param {string[]} apps - List of application names to subscribe to
|
|
2580
|
+
* @param {WebSocketEventType[]} [subscribedEvents] - Optional list of specific event types to subscribe to
|
|
2581
|
+
* @returns {Promise<void>} Resolves when connection is established
|
|
2582
|
+
* @throws {Error} If connection fails or if WebSocket is already connected
|
|
1872
2583
|
*/
|
|
1873
2584
|
async connectWebSocket(apps, subscribedEvents) {
|
|
2585
|
+
if (!apps.length) {
|
|
2586
|
+
throw new Error("At least one application name is required");
|
|
2587
|
+
}
|
|
1874
2588
|
if (this.webSocketClient) {
|
|
1875
|
-
console.warn("WebSocket
|
|
2589
|
+
console.warn("WebSocket is already connected");
|
|
1876
2590
|
return;
|
|
1877
2591
|
}
|
|
1878
|
-
|
|
1879
|
-
this.
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
2592
|
+
try {
|
|
2593
|
+
this.webSocketClient = new WebSocketClient(
|
|
2594
|
+
this.baseClient,
|
|
2595
|
+
apps,
|
|
2596
|
+
subscribedEvents,
|
|
2597
|
+
this
|
|
2598
|
+
);
|
|
2599
|
+
await this.webSocketClient.connect();
|
|
2600
|
+
console.log("WebSocket connection established successfully");
|
|
2601
|
+
} catch (error) {
|
|
2602
|
+
console.error("Failed to establish WebSocket connection:", error);
|
|
2603
|
+
this.webSocketClient = void 0;
|
|
2604
|
+
throw error;
|
|
2605
|
+
}
|
|
1885
2606
|
}
|
|
1886
2607
|
/**
|
|
1887
|
-
*
|
|
2608
|
+
* Registers an event listener for WebSocket events.
|
|
2609
|
+
*
|
|
2610
|
+
* @param {T} event - The event type to listen for
|
|
2611
|
+
* @param {Function} listener - Callback function for handling the event
|
|
2612
|
+
* @throws {Error} If WebSocket is not connected
|
|
1888
2613
|
*/
|
|
1889
2614
|
on(event, listener) {
|
|
1890
|
-
this.webSocketClient
|
|
2615
|
+
if (!this.webSocketClient) {
|
|
2616
|
+
throw new Error("WebSocket is not connected");
|
|
2617
|
+
}
|
|
2618
|
+
this.webSocketClient.on(event, listener);
|
|
2619
|
+
console.log(`Event listener registered for ${event}`);
|
|
1891
2620
|
}
|
|
1892
2621
|
/**
|
|
1893
|
-
*
|
|
2622
|
+
* Registers a one-time event listener for WebSocket events.
|
|
2623
|
+
*
|
|
2624
|
+
* @param {T} event - The event type to listen for
|
|
2625
|
+
* @param {Function} listener - Callback function for handling the event
|
|
2626
|
+
* @throws {Error} If WebSocket is not connected
|
|
1894
2627
|
*/
|
|
1895
2628
|
once(event, listener) {
|
|
1896
|
-
this.webSocketClient
|
|
2629
|
+
if (!this.webSocketClient) {
|
|
2630
|
+
throw new Error("WebSocket is not connected");
|
|
2631
|
+
}
|
|
2632
|
+
this.webSocketClient.once(event, listener);
|
|
2633
|
+
console.log(`One-time event listener registered for ${event}`);
|
|
1897
2634
|
}
|
|
1898
2635
|
/**
|
|
1899
|
-
*
|
|
2636
|
+
* Removes an event listener for WebSocket events.
|
|
2637
|
+
*
|
|
2638
|
+
* @param {T} event - The event type to remove listener for
|
|
2639
|
+
* @param {Function} listener - The listener function to remove
|
|
1900
2640
|
*/
|
|
1901
2641
|
off(event, listener) {
|
|
1902
|
-
this.webSocketClient
|
|
2642
|
+
if (!this.webSocketClient) {
|
|
2643
|
+
console.warn("No WebSocket connection to remove listener from");
|
|
2644
|
+
return;
|
|
2645
|
+
}
|
|
2646
|
+
this.webSocketClient.off(event, listener);
|
|
2647
|
+
console.log(`Event listener removed for ${event}`);
|
|
1903
2648
|
}
|
|
1904
2649
|
/**
|
|
1905
|
-
*
|
|
2650
|
+
* Closes the WebSocket connection if one exists.
|
|
1906
2651
|
*/
|
|
1907
2652
|
closeWebSocket() {
|
|
1908
|
-
this.webSocketClient
|
|
2653
|
+
if (!this.webSocketClient) {
|
|
2654
|
+
console.warn("No WebSocket connection to close");
|
|
2655
|
+
return;
|
|
2656
|
+
}
|
|
2657
|
+
this.webSocketClient.close();
|
|
1909
2658
|
this.webSocketClient = void 0;
|
|
2659
|
+
console.log("WebSocket connection closed");
|
|
1910
2660
|
}
|
|
1911
2661
|
/**
|
|
1912
|
-
*
|
|
2662
|
+
* Creates or retrieves a Channel instance.
|
|
2663
|
+
*
|
|
2664
|
+
* @param {string} [channelId] - Optional ID of an existing channel
|
|
2665
|
+
* @returns {ChannelInstance} A new or existing channel instance
|
|
1913
2666
|
*/
|
|
1914
2667
|
Channel(channelId) {
|
|
1915
2668
|
return this.channels.Channel({ id: channelId });
|
|
1916
2669
|
}
|
|
1917
2670
|
/**
|
|
1918
|
-
*
|
|
2671
|
+
* Creates or retrieves a Playback instance.
|
|
2672
|
+
*
|
|
2673
|
+
* @param {string} [playbackId] - Optional ID of an existing playback
|
|
2674
|
+
* @param {string} [_app] - Optional application name (deprecated)
|
|
2675
|
+
* @returns {PlaybackInstance} A new or existing playback instance
|
|
1919
2676
|
*/
|
|
1920
2677
|
Playback(playbackId, _app) {
|
|
1921
2678
|
return this.playbacks.Playback({ id: playbackId });
|
|
1922
2679
|
}
|
|
2680
|
+
/**
|
|
2681
|
+
* Gets the current WebSocket connection status.
|
|
2682
|
+
*
|
|
2683
|
+
* @returns {boolean} True if WebSocket is connected, false otherwise
|
|
2684
|
+
*/
|
|
2685
|
+
isWebSocketConnected() {
|
|
2686
|
+
return !!this.webSocketClient;
|
|
2687
|
+
}
|
|
1923
2688
|
};
|
|
1924
2689
|
export {
|
|
1925
2690
|
Applications,
|