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