@koi-design/callkit 1.0.22
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 +272 -0
- package/dist/index.d.ts +436 -0
- package/dist/index.global.js +19209 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +1691 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1662 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +50 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,1662 @@
|
|
|
1
|
+
// package/index.ts
|
|
2
|
+
import md5 from "blueimp-md5";
|
|
3
|
+
|
|
4
|
+
// package/axios.ts
|
|
5
|
+
import axios from "axios";
|
|
6
|
+
var instance = axios.create({
|
|
7
|
+
headers: {
|
|
8
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
instance.interceptors.request.use((config) => config);
|
|
12
|
+
instance.interceptors.response.use(
|
|
13
|
+
(response) => response.data,
|
|
14
|
+
(error) => Promise.reject(error)
|
|
15
|
+
);
|
|
16
|
+
var request = (config) => instance.request(config);
|
|
17
|
+
var axios_default = request;
|
|
18
|
+
|
|
19
|
+
// package/api.ts
|
|
20
|
+
var Api = class {
|
|
21
|
+
callKit;
|
|
22
|
+
constructor(callKit) {
|
|
23
|
+
this.callKit = callKit;
|
|
24
|
+
}
|
|
25
|
+
async login(params) {
|
|
26
|
+
return this.post({
|
|
27
|
+
url: "/auth/agentUser/login",
|
|
28
|
+
method: "post",
|
|
29
|
+
data: params
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async loginOut(params) {
|
|
33
|
+
return this.post({
|
|
34
|
+
url: "/auth/agentUser/loginOut",
|
|
35
|
+
method: "post",
|
|
36
|
+
data: params
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @param params agentId userStatus
|
|
42
|
+
* @description userStatus: Logout(1, "unregistered"), Free(2, "free"), Break(3, "nap"), Busy(4, "busy")
|
|
43
|
+
* @returns
|
|
44
|
+
*/
|
|
45
|
+
async setUserStatus(params) {
|
|
46
|
+
return this.post({
|
|
47
|
+
url: "/agent/user/changeStatus",
|
|
48
|
+
method: "post",
|
|
49
|
+
data: params
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async post(config) {
|
|
53
|
+
this.callKit.logger.debug(`Request ${config.url}:`, config.data);
|
|
54
|
+
const { userInfo, host } = this.callKit.config.getConfig();
|
|
55
|
+
const { sessionId } = userInfo;
|
|
56
|
+
config.url = `${host}${config.url}`;
|
|
57
|
+
config.headers = {
|
|
58
|
+
...config.headers,
|
|
59
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
60
|
+
};
|
|
61
|
+
if (config.headers["Content-Type"] === "application/x-www-form-urlencoded") {
|
|
62
|
+
config.data = new URLSearchParams(config.data).toString();
|
|
63
|
+
}
|
|
64
|
+
if (sessionId) {
|
|
65
|
+
config.headers.sessionId = sessionId;
|
|
66
|
+
}
|
|
67
|
+
const res = await axios_default(config).catch(() => {
|
|
68
|
+
this.callKit.config.reset();
|
|
69
|
+
});
|
|
70
|
+
if (!res) {
|
|
71
|
+
this.callKit.config.reset();
|
|
72
|
+
throw new Error("Network error");
|
|
73
|
+
}
|
|
74
|
+
const { code, data, message } = res;
|
|
75
|
+
if (code === "000000") {
|
|
76
|
+
return data;
|
|
77
|
+
}
|
|
78
|
+
if (code === "100013") {
|
|
79
|
+
this.callKit.config.reset();
|
|
80
|
+
}
|
|
81
|
+
throw new Error(message ?? "Request failed");
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// package/const.ts
|
|
86
|
+
var UserStatus = {
|
|
87
|
+
/**
|
|
88
|
+
* Offline
|
|
89
|
+
*/
|
|
90
|
+
offline: 1,
|
|
91
|
+
/**
|
|
92
|
+
* Online & Idle
|
|
93
|
+
*/
|
|
94
|
+
online: 2,
|
|
95
|
+
/**
|
|
96
|
+
* Nap
|
|
97
|
+
*/
|
|
98
|
+
catNap: 3,
|
|
99
|
+
/**
|
|
100
|
+
* Busy
|
|
101
|
+
*/
|
|
102
|
+
busy: 4,
|
|
103
|
+
/**
|
|
104
|
+
* Training
|
|
105
|
+
*/
|
|
106
|
+
training: 5,
|
|
107
|
+
/**
|
|
108
|
+
* Processing
|
|
109
|
+
*/
|
|
110
|
+
processing: 6
|
|
111
|
+
};
|
|
112
|
+
var CallStatus = {
|
|
113
|
+
/**
|
|
114
|
+
* Initial state/Hang up
|
|
115
|
+
*/
|
|
116
|
+
init: 0,
|
|
117
|
+
/**
|
|
118
|
+
* Registered
|
|
119
|
+
*/
|
|
120
|
+
registered: 1,
|
|
121
|
+
/**
|
|
122
|
+
* Connecting
|
|
123
|
+
*/
|
|
124
|
+
connecting: 2,
|
|
125
|
+
/**
|
|
126
|
+
* Call on hold
|
|
127
|
+
*/
|
|
128
|
+
holding: 3,
|
|
129
|
+
/**
|
|
130
|
+
* Ringing
|
|
131
|
+
*/
|
|
132
|
+
ringing: 4,
|
|
133
|
+
/**
|
|
134
|
+
* In call
|
|
135
|
+
*/
|
|
136
|
+
calling: 5
|
|
137
|
+
};
|
|
138
|
+
var KitEvent = {
|
|
139
|
+
/**
|
|
140
|
+
* User status change
|
|
141
|
+
*/
|
|
142
|
+
KIT_USER_STATUS_CHANGE: "userStatusChange",
|
|
143
|
+
/**
|
|
144
|
+
* User login status change
|
|
145
|
+
*/
|
|
146
|
+
KIT_LOGIN_CHANGE: "loginChange",
|
|
147
|
+
/**
|
|
148
|
+
* Registration status change
|
|
149
|
+
*/
|
|
150
|
+
KIT_REGISTER_CHANGE: "registerChange",
|
|
151
|
+
/**
|
|
152
|
+
* Call status change
|
|
153
|
+
*/
|
|
154
|
+
KIT_CALL_STATUS_CHANGE: "callStatusChange",
|
|
155
|
+
/**
|
|
156
|
+
* Hold status change
|
|
157
|
+
*/
|
|
158
|
+
KIT_SET_HOLD: "holdChange",
|
|
159
|
+
/**
|
|
160
|
+
* Mute status change
|
|
161
|
+
*/
|
|
162
|
+
KIT_SET_MUTE: "muteChange",
|
|
163
|
+
/**
|
|
164
|
+
* Error
|
|
165
|
+
*/
|
|
166
|
+
KIT_ERROR: "error",
|
|
167
|
+
/**
|
|
168
|
+
* Server initiated call
|
|
169
|
+
*/
|
|
170
|
+
KIT_INVITE: "invite",
|
|
171
|
+
/**
|
|
172
|
+
* Connecting
|
|
173
|
+
*/
|
|
174
|
+
CALL_CONNECTING: "connecting",
|
|
175
|
+
/**
|
|
176
|
+
* Customer ringing
|
|
177
|
+
*/
|
|
178
|
+
CALL_RINGING: "ringing",
|
|
179
|
+
/**
|
|
180
|
+
* Agent pick up
|
|
181
|
+
*/
|
|
182
|
+
AGENT_PICK_UP: "agentPickUp",
|
|
183
|
+
/**
|
|
184
|
+
* Customer answer
|
|
185
|
+
*/
|
|
186
|
+
CALL_PICK_UP: "pickUp",
|
|
187
|
+
/**
|
|
188
|
+
* Customer no response
|
|
189
|
+
*/
|
|
190
|
+
CALL_NO_ANSWER: "noAnswer",
|
|
191
|
+
/**
|
|
192
|
+
* Customer hang up
|
|
193
|
+
*/
|
|
194
|
+
CALL_HANG_UP: "hangUp",
|
|
195
|
+
/**
|
|
196
|
+
* Call end
|
|
197
|
+
*/
|
|
198
|
+
CALL_END: "callEnd",
|
|
199
|
+
/**
|
|
200
|
+
* Call detail record push
|
|
201
|
+
*/
|
|
202
|
+
CALL_CDR: "callCdr",
|
|
203
|
+
/**
|
|
204
|
+
* Forward all socket events
|
|
205
|
+
*/
|
|
206
|
+
SERVER_SOCKET_EVENT: "socketEvent",
|
|
207
|
+
/**
|
|
208
|
+
* User status change
|
|
209
|
+
*/
|
|
210
|
+
USER_STATUS_CHANGE: "userStatusChange"
|
|
211
|
+
};
|
|
212
|
+
var ErrorCode = {
|
|
213
|
+
/**
|
|
214
|
+
* Unknown error
|
|
215
|
+
*/
|
|
216
|
+
UNKNOWN_ERROR: -1,
|
|
217
|
+
/**
|
|
218
|
+
* API user login failed
|
|
219
|
+
*/
|
|
220
|
+
API_USER_LOGIN_ERROR: 1000001,
|
|
221
|
+
/**
|
|
222
|
+
* API user status update failed
|
|
223
|
+
*/
|
|
224
|
+
API_USER_STATUS_UPDATE_ERROR: 1000002,
|
|
225
|
+
/**
|
|
226
|
+
* API user logout failed
|
|
227
|
+
*/
|
|
228
|
+
API_USER_LOGOUT_ERROR: 1000003,
|
|
229
|
+
/**
|
|
230
|
+
* connectStatus call status error
|
|
231
|
+
*/
|
|
232
|
+
CONNECT_CALL_STATUS_ERROR: 2000001,
|
|
233
|
+
/**
|
|
234
|
+
* User not logged in
|
|
235
|
+
*/
|
|
236
|
+
USER_NOT_LOGIN: 2000002,
|
|
237
|
+
/**
|
|
238
|
+
* Browser version too low, does not support webrtc getUserMedia
|
|
239
|
+
*/
|
|
240
|
+
WEBRTC_USER_MEDIA_ERROR: 2000003,
|
|
241
|
+
/**
|
|
242
|
+
* Call hold failed
|
|
243
|
+
*/
|
|
244
|
+
WEBRTC_HOLE_STATUS_ERROR: 2000004,
|
|
245
|
+
/**
|
|
246
|
+
* Audio player does not exist
|
|
247
|
+
*/
|
|
248
|
+
WEBRTC_AUDIO_PLAYER_ERROR: 2000005,
|
|
249
|
+
/**
|
|
250
|
+
* Audio playback failed
|
|
251
|
+
*/
|
|
252
|
+
WEBRTC_AUDIO_PLAY_ERROR: 2000006,
|
|
253
|
+
/**
|
|
254
|
+
* User agent startup failed
|
|
255
|
+
*/
|
|
256
|
+
WEBRTC_USER_AGENT_ERROR: 2000007,
|
|
257
|
+
/**
|
|
258
|
+
* Call request failed
|
|
259
|
+
*/
|
|
260
|
+
WEBRTC_CALL_INVITE_ERROR: 2000008,
|
|
261
|
+
/**
|
|
262
|
+
* Register request failed
|
|
263
|
+
*/
|
|
264
|
+
WEBRTC_REGISTER_ERROR: 2000009,
|
|
265
|
+
/**
|
|
266
|
+
* Mute failed
|
|
267
|
+
*/
|
|
268
|
+
WEBRTC_MUTE_STATUS_ERROR: 2000010,
|
|
269
|
+
/**
|
|
270
|
+
* Unregister failed
|
|
271
|
+
*/
|
|
272
|
+
WEBRTC_CANCEL_REGISTER_ERROR: 2000011,
|
|
273
|
+
/**
|
|
274
|
+
* Mute failed
|
|
275
|
+
*/
|
|
276
|
+
WEBRTC_MUTE_ERROR: 2000012,
|
|
277
|
+
/**
|
|
278
|
+
* Socket connection error
|
|
279
|
+
*/
|
|
280
|
+
SOCKET_CONNECT_ERROR: 3000001,
|
|
281
|
+
/**
|
|
282
|
+
* Ping timeout
|
|
283
|
+
*/
|
|
284
|
+
SOCKET_PING_TIMEOUT: 3000002,
|
|
285
|
+
/**
|
|
286
|
+
* Server error
|
|
287
|
+
*/
|
|
288
|
+
SOKET_SERVER_ERROR: 3000003,
|
|
289
|
+
/**
|
|
290
|
+
* API call failed
|
|
291
|
+
*/
|
|
292
|
+
SOCKET_CALL_ERROR: 3000004,
|
|
293
|
+
/**
|
|
294
|
+
* Reconnection limit exceeded
|
|
295
|
+
*/
|
|
296
|
+
SOCKET_RECONNECT_FAILED: 3000005
|
|
297
|
+
};
|
|
298
|
+
var LoggerLevelMap = {
|
|
299
|
+
debug: 9,
|
|
300
|
+
log: 4,
|
|
301
|
+
warn: 3,
|
|
302
|
+
error: 2,
|
|
303
|
+
silent: 1
|
|
304
|
+
};
|
|
305
|
+
var SocketSendEvent = {
|
|
306
|
+
/**
|
|
307
|
+
* ping
|
|
308
|
+
*/
|
|
309
|
+
PING: "PING",
|
|
310
|
+
/**
|
|
311
|
+
* Start
|
|
312
|
+
*/
|
|
313
|
+
START: "START",
|
|
314
|
+
/**
|
|
315
|
+
* Hang up
|
|
316
|
+
*/
|
|
317
|
+
AGENT_HANGUP: "AGENT_HANG_UP",
|
|
318
|
+
/**
|
|
319
|
+
* Cancel
|
|
320
|
+
*/
|
|
321
|
+
CALL_CANCEL: "AGENT_CANCEL",
|
|
322
|
+
/**
|
|
323
|
+
* Hold
|
|
324
|
+
*/
|
|
325
|
+
HOLD: "AGENT_HOLD",
|
|
326
|
+
/**
|
|
327
|
+
* Unhold
|
|
328
|
+
*/
|
|
329
|
+
UNHOLD: "AGENT_UN_HOLD",
|
|
330
|
+
/**
|
|
331
|
+
* Call
|
|
332
|
+
*/
|
|
333
|
+
CALL: "CALL",
|
|
334
|
+
/**
|
|
335
|
+
* End
|
|
336
|
+
*/
|
|
337
|
+
END: "STOP"
|
|
338
|
+
};
|
|
339
|
+
var SocketReceiveEvent = {
|
|
340
|
+
/**
|
|
341
|
+
* Response
|
|
342
|
+
*/
|
|
343
|
+
PONG: "PONG",
|
|
344
|
+
/**
|
|
345
|
+
* Start confirmation
|
|
346
|
+
*/
|
|
347
|
+
START_CONFIRM: "START_CONFIRM",
|
|
348
|
+
/**
|
|
349
|
+
* Call success
|
|
350
|
+
*/
|
|
351
|
+
CALL_SUCCESS: "CALL_SUCCESS",
|
|
352
|
+
/**
|
|
353
|
+
* Call failed
|
|
354
|
+
*/
|
|
355
|
+
CALL_FAILED: "CALL_FAILED",
|
|
356
|
+
/**
|
|
357
|
+
* Customer ringing
|
|
358
|
+
*/
|
|
359
|
+
CUSTOMER_RINGING: "CUSTOMER_RINGING",
|
|
360
|
+
/**
|
|
361
|
+
* Agent pick up
|
|
362
|
+
*/
|
|
363
|
+
AGENT_PICK_UP: "AGENT_PICK_UP",
|
|
364
|
+
/**
|
|
365
|
+
* Customer pick up
|
|
366
|
+
*/
|
|
367
|
+
CUSTOMER_PICK_UP: "CUSTOMER_PICK_UP",
|
|
368
|
+
/**
|
|
369
|
+
* Customer no answer
|
|
370
|
+
*/
|
|
371
|
+
CUSTOMER_NO_ANSWER: "CUSTOMER_NO_ANSWER",
|
|
372
|
+
/**
|
|
373
|
+
* Customer hang up
|
|
374
|
+
*/
|
|
375
|
+
CUSTOMER_HANG_UP: "CUSTOMER_HANG_UP",
|
|
376
|
+
/**
|
|
377
|
+
* Agent no answer
|
|
378
|
+
*/
|
|
379
|
+
AGENT_NO_ANSWER: "AGENT_NO_ANSWER",
|
|
380
|
+
/**
|
|
381
|
+
* Call detail record push
|
|
382
|
+
*/
|
|
383
|
+
CALL_CDR: "CALL_CDR",
|
|
384
|
+
/**
|
|
385
|
+
* Stop confirmation
|
|
386
|
+
*/
|
|
387
|
+
STOP_CONFIRM: "STOP_CONFIRM",
|
|
388
|
+
/**
|
|
389
|
+
* Close
|
|
390
|
+
*/
|
|
391
|
+
CLOSE: "CLOSE",
|
|
392
|
+
/**
|
|
393
|
+
* Error
|
|
394
|
+
*/
|
|
395
|
+
ERROR: "ERROR"
|
|
396
|
+
};
|
|
397
|
+
var constrainsDefault = {
|
|
398
|
+
audio: {
|
|
399
|
+
autoGainControl: true,
|
|
400
|
+
// Noise suppression
|
|
401
|
+
noiseSuppression: true,
|
|
402
|
+
// Set echo cancellation
|
|
403
|
+
echoCancellation: true
|
|
404
|
+
},
|
|
405
|
+
video: false
|
|
406
|
+
};
|
|
407
|
+
var isAutoUpdateUserStatusDefault = true;
|
|
408
|
+
|
|
409
|
+
// package/call.ts
|
|
410
|
+
var Call = class {
|
|
411
|
+
callKit;
|
|
412
|
+
constructor(callKit) {
|
|
413
|
+
this.callKit = callKit;
|
|
414
|
+
}
|
|
415
|
+
async callStart() {
|
|
416
|
+
if (!this.callKit.config.check())
|
|
417
|
+
return;
|
|
418
|
+
this.callKit.logger.debug("callStart");
|
|
419
|
+
if (!this.callKit.socket.satrtConfirm) {
|
|
420
|
+
this.callKit.logger.warn("server not confirm start");
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
this.callKit.connect.call(async (user) => {
|
|
424
|
+
const queryTrain = {
|
|
425
|
+
agentId: user.agentId,
|
|
426
|
+
phoneNum: user.extno
|
|
427
|
+
};
|
|
428
|
+
this.callKit.socket.send(SocketSendEvent.CALL, queryTrain);
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Hang up
|
|
433
|
+
* @param isUnprompted Whether to actively hang up
|
|
434
|
+
* @param isError Whether an error occurred
|
|
435
|
+
* @returns
|
|
436
|
+
*/
|
|
437
|
+
async callEnd(isUnprompted = false, isError = false) {
|
|
438
|
+
if (this.callKit.connect.connectStatus === CallStatus.init || this.callKit.connect.connectStatus === CallStatus.registered)
|
|
439
|
+
return;
|
|
440
|
+
if (!this.callKit.config.check())
|
|
441
|
+
return;
|
|
442
|
+
this.callKit.connect.hangup(isUnprompted, isError);
|
|
443
|
+
}
|
|
444
|
+
async callHold() {
|
|
445
|
+
if (!this.callKit.config.check())
|
|
446
|
+
return;
|
|
447
|
+
if (!this.callKit.connect.isCalling()) {
|
|
448
|
+
this.callKit.logger.warn("Current state cannot be held");
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
this.callKit.connect.hold();
|
|
452
|
+
this.callKit.socket.send(SocketSendEvent.HOLD);
|
|
453
|
+
this.callKit.connect.setConnectStatus(CallStatus.holding);
|
|
454
|
+
}
|
|
455
|
+
async callUnhold() {
|
|
456
|
+
if (!this.callKit.config.check())
|
|
457
|
+
return;
|
|
458
|
+
if (!this.callKit.connect.isHolding()) {
|
|
459
|
+
this.callKit.logger.warn("Current state cannot unhold");
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
this.callKit.connect.unhold();
|
|
463
|
+
this.callKit.socket.send(SocketSendEvent.UNHOLD);
|
|
464
|
+
this.callKit.connect.setConnectStatus(CallStatus.calling);
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
// package/config.ts
|
|
469
|
+
var Config = class {
|
|
470
|
+
callKit;
|
|
471
|
+
constructor(callKit) {
|
|
472
|
+
this.callKit = callKit;
|
|
473
|
+
}
|
|
474
|
+
config = {
|
|
475
|
+
version: "1.0.2",
|
|
476
|
+
host: "",
|
|
477
|
+
log: "debug",
|
|
478
|
+
audioRef: void 0,
|
|
479
|
+
constrains: constrainsDefault,
|
|
480
|
+
socket: "",
|
|
481
|
+
userInfo: {
|
|
482
|
+
wsUrl: "",
|
|
483
|
+
sessionId: "",
|
|
484
|
+
// User
|
|
485
|
+
username: "",
|
|
486
|
+
// Password
|
|
487
|
+
password: "",
|
|
488
|
+
// Extension number
|
|
489
|
+
extno: "",
|
|
490
|
+
userPart: "",
|
|
491
|
+
agentId: "",
|
|
492
|
+
fsUserId: "",
|
|
493
|
+
fsPassword: "",
|
|
494
|
+
fsIp: "",
|
|
495
|
+
fsPort: "",
|
|
496
|
+
iceInfo: [],
|
|
497
|
+
iceGatheringTimeout: 0
|
|
498
|
+
},
|
|
499
|
+
// EXECUTE setUserStatus
|
|
500
|
+
isAutoUpdateUserStatus: true
|
|
501
|
+
};
|
|
502
|
+
getConfig = () => this.config;
|
|
503
|
+
setConfig = async (key, value) => {
|
|
504
|
+
this.config[key] = value;
|
|
505
|
+
};
|
|
506
|
+
setUserInfo = async (key, value) => {
|
|
507
|
+
this.config.userInfo[key] = value;
|
|
508
|
+
this.callKit.logger.debug(`setUserInfo: key: ${key}, value: ${value}`);
|
|
509
|
+
};
|
|
510
|
+
reset = () => {
|
|
511
|
+
if (this.isLogin()) {
|
|
512
|
+
this.config.userInfo = {
|
|
513
|
+
wsUrl: "",
|
|
514
|
+
sessionId: "",
|
|
515
|
+
username: "",
|
|
516
|
+
password: "",
|
|
517
|
+
userPart: "",
|
|
518
|
+
extno: "",
|
|
519
|
+
agentId: "",
|
|
520
|
+
fsUserId: "",
|
|
521
|
+
fsPassword: "",
|
|
522
|
+
fsIp: "",
|
|
523
|
+
fsPort: "",
|
|
524
|
+
iceInfo: [],
|
|
525
|
+
iceGatheringTimeout: this.config.userInfo.iceGatheringTimeout
|
|
526
|
+
};
|
|
527
|
+
this.callKit.trigger(KitEvent.KIT_LOGIN_CHANGE, false);
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
validate = () => {
|
|
531
|
+
const {
|
|
532
|
+
userPart,
|
|
533
|
+
fsIp,
|
|
534
|
+
fsPassword,
|
|
535
|
+
fsPort
|
|
536
|
+
} = this.config.userInfo;
|
|
537
|
+
if (!userPart || !fsIp || !fsPort || !fsPassword) {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
return true;
|
|
541
|
+
};
|
|
542
|
+
isLogin = () => this.validate();
|
|
543
|
+
check() {
|
|
544
|
+
if (!this.isLogin()) {
|
|
545
|
+
this.callKit.logger.error("User not logged in", {
|
|
546
|
+
errCode: ErrorCode.USER_NOT_LOGIN
|
|
547
|
+
});
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
return true;
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
// package/logger.ts
|
|
555
|
+
function getLevel(level) {
|
|
556
|
+
return LoggerLevelMap[level];
|
|
557
|
+
}
|
|
558
|
+
var Logger = class {
|
|
559
|
+
prefix = "CallKit";
|
|
560
|
+
level = "debug";
|
|
561
|
+
callKit;
|
|
562
|
+
constructor(callKit, level) {
|
|
563
|
+
this.callKit = callKit;
|
|
564
|
+
this.level = level || "debug";
|
|
565
|
+
}
|
|
566
|
+
setLevel(level) {
|
|
567
|
+
this.level = level;
|
|
568
|
+
}
|
|
569
|
+
debug(msg, extra) {
|
|
570
|
+
if (getLevel(this.level) >= getLevel("debug")) {
|
|
571
|
+
this.output("blue")(msg, extra);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
log(msg, extra) {
|
|
575
|
+
if (getLevel(this.level) >= getLevel("log")) {
|
|
576
|
+
this.output("green")(msg, extra);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
warn(msg, extra) {
|
|
580
|
+
if (getLevel(this.level) >= getLevel("warn")) {
|
|
581
|
+
this.output("orange")(msg, extra);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
error(msg, extra) {
|
|
585
|
+
const message = msg?.message ?? msg;
|
|
586
|
+
if (getLevel(this.level) >= getLevel("error")) {
|
|
587
|
+
this.output("red")(message, extra);
|
|
588
|
+
}
|
|
589
|
+
const { errCode, ...rest } = extra;
|
|
590
|
+
const errorCode = errCode ?? ErrorCode.UNKNOWN_ERROR;
|
|
591
|
+
this.callKit.trigger(KitEvent.KIT_ERROR, {
|
|
592
|
+
code: errorCode,
|
|
593
|
+
msg: message,
|
|
594
|
+
data: rest
|
|
595
|
+
});
|
|
596
|
+
this.callKit.reset();
|
|
597
|
+
const error = new Error(message);
|
|
598
|
+
error.name = "CallKitError";
|
|
599
|
+
error.code = errorCode;
|
|
600
|
+
error.data = rest;
|
|
601
|
+
throw error;
|
|
602
|
+
}
|
|
603
|
+
output(color) {
|
|
604
|
+
return (msg, extra = {}) => {
|
|
605
|
+
const now = /* @__PURE__ */ new Date();
|
|
606
|
+
if (Object.keys(extra).length > 0) {
|
|
607
|
+
console.log(
|
|
608
|
+
`%c[${this.prefix}] %c ${msg} %o %c ${now.toLocaleString()}`,
|
|
609
|
+
`color: ${color};`,
|
|
610
|
+
"color:block;",
|
|
611
|
+
extra,
|
|
612
|
+
"color:#999;"
|
|
613
|
+
);
|
|
614
|
+
} else {
|
|
615
|
+
console.log(
|
|
616
|
+
`%c[${this.prefix}] %c ${msg} %c ${now.toLocaleString()}`,
|
|
617
|
+
`color: ${color};`,
|
|
618
|
+
"color:block;",
|
|
619
|
+
"color:#999;"
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
// package/connect.ts
|
|
627
|
+
import {
|
|
628
|
+
UserAgent,
|
|
629
|
+
Web,
|
|
630
|
+
Registerer,
|
|
631
|
+
SessionState
|
|
632
|
+
} from "sip.js";
|
|
633
|
+
function convertObjectStringToJSON(input) {
|
|
634
|
+
const corrected = input.replace(/(\w+):\s*'(.*?)'/g, '"$1": "$2"').replace(/'/g, '"');
|
|
635
|
+
return corrected;
|
|
636
|
+
}
|
|
637
|
+
var closeStream = (stream) => {
|
|
638
|
+
if (stream)
|
|
639
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
640
|
+
};
|
|
641
|
+
var initUserMedia = () => {
|
|
642
|
+
if (typeof navigator.mediaDevices === "undefined") {
|
|
643
|
+
navigator.mediaDevices = {};
|
|
644
|
+
}
|
|
645
|
+
if (typeof navigator.mediaDevices.getUserMedia === "undefined") {
|
|
646
|
+
navigator.mediaDevices.getUserMedia = (constraints) => {
|
|
647
|
+
const getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
|
|
648
|
+
if (!getUserMedia) {
|
|
649
|
+
return Promise.reject(
|
|
650
|
+
new Error("Browser version is too low, please upgrade and try again.")
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
return new Promise((resolve, reject) => {
|
|
654
|
+
getUserMedia.call(navigator, constraints, resolve, reject);
|
|
655
|
+
});
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
var Connect = class {
|
|
660
|
+
callKit;
|
|
661
|
+
/**
|
|
662
|
+
* connectStatus: init registered connecting calling
|
|
663
|
+
*/
|
|
664
|
+
connectStatus = CallStatus.init;
|
|
665
|
+
currentSession;
|
|
666
|
+
mediaStream;
|
|
667
|
+
userAgent;
|
|
668
|
+
registerer;
|
|
669
|
+
sipConnected = false;
|
|
670
|
+
/**
|
|
671
|
+
* Whether it's an outgoing call
|
|
672
|
+
*/
|
|
673
|
+
isOutgoing = false;
|
|
674
|
+
/**
|
|
675
|
+
* Whether it's an active hangup
|
|
676
|
+
*/
|
|
677
|
+
isUnprompted = false;
|
|
678
|
+
/**
|
|
679
|
+
* Whether registered
|
|
680
|
+
* @param
|
|
681
|
+
* @deprecated Deprecated, please use isRegistered method
|
|
682
|
+
*/
|
|
683
|
+
get isRegister() {
|
|
684
|
+
return this.isRegistered();
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Call hold
|
|
688
|
+
* @param isHold
|
|
689
|
+
*/
|
|
690
|
+
isHold = false;
|
|
691
|
+
/**
|
|
692
|
+
* Whether muted
|
|
693
|
+
*/
|
|
694
|
+
isMute = false;
|
|
695
|
+
constructor(callKit) {
|
|
696
|
+
this.callKit = callKit;
|
|
697
|
+
}
|
|
698
|
+
reset() {
|
|
699
|
+
if (this.connectStatus !== CallStatus.init) {
|
|
700
|
+
this.setConnectStatus(CallStatus.init);
|
|
701
|
+
}
|
|
702
|
+
if (this.isRegistered()) {
|
|
703
|
+
this.unregister();
|
|
704
|
+
}
|
|
705
|
+
this.currentSession = void 0;
|
|
706
|
+
this.mediaStream = void 0;
|
|
707
|
+
this.userAgent = void 0;
|
|
708
|
+
this.registerer = void 0;
|
|
709
|
+
this.isOutgoing = false;
|
|
710
|
+
this.isUnprompted = false;
|
|
711
|
+
this.sipConnected = false;
|
|
712
|
+
if (this.isHold) {
|
|
713
|
+
this.setHoldStatus(false);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
getAduioReference() {
|
|
717
|
+
const { audioRef } = this.callKit.config.getConfig();
|
|
718
|
+
if (typeof audioRef === "function") {
|
|
719
|
+
return audioRef();
|
|
720
|
+
}
|
|
721
|
+
return audioRef;
|
|
722
|
+
}
|
|
723
|
+
async permission() {
|
|
724
|
+
this.callKit.logger.debug("permission");
|
|
725
|
+
initUserMedia();
|
|
726
|
+
const _stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
727
|
+
closeStream(_stream);
|
|
728
|
+
}
|
|
729
|
+
isRegistered() {
|
|
730
|
+
return [
|
|
731
|
+
CallStatus.registered,
|
|
732
|
+
CallStatus.connecting,
|
|
733
|
+
CallStatus.ringing,
|
|
734
|
+
CallStatus.calling,
|
|
735
|
+
CallStatus.holding
|
|
736
|
+
].includes(this.connectStatus);
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Making connection
|
|
740
|
+
* @returns
|
|
741
|
+
*/
|
|
742
|
+
isConnecting() {
|
|
743
|
+
return this.connectStatus === CallStatus.connecting;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* In call
|
|
747
|
+
* @returns
|
|
748
|
+
*/
|
|
749
|
+
isCalling() {
|
|
750
|
+
return this.connectStatus === CallStatus.calling;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Ringing
|
|
754
|
+
*/
|
|
755
|
+
isRinging() {
|
|
756
|
+
return this.connectStatus === CallStatus.ringing;
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
*
|
|
760
|
+
*/
|
|
761
|
+
isHolding() {
|
|
762
|
+
return this.connectStatus === CallStatus.holding;
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Call ended, call not started
|
|
766
|
+
* @returns
|
|
767
|
+
*/
|
|
768
|
+
isInit() {
|
|
769
|
+
return this.connectStatus === CallStatus.init;
|
|
770
|
+
}
|
|
771
|
+
async register() {
|
|
772
|
+
if (this.connectStatus !== CallStatus.init) {
|
|
773
|
+
if (this.connectStatus === CallStatus.registered) {
|
|
774
|
+
this.callKit.logger.warn("connectStatus is registered");
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
this.callKit.logger.error("connectStatus is not init", {
|
|
778
|
+
errCode: ErrorCode.CONNECT_CALL_STATUS_ERROR
|
|
779
|
+
});
|
|
780
|
+
this.callKit.callCenter.callEnd();
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
this.callKit.logger.debug("connect register");
|
|
784
|
+
await this.permission().catch((err) => {
|
|
785
|
+
this.callKit.logger.error(err, {
|
|
786
|
+
errCode: ErrorCode.WEBRTC_USER_MEDIA_ERROR
|
|
787
|
+
});
|
|
788
|
+
});
|
|
789
|
+
const { userInfo, constrains } = this.callKit.config.getConfig();
|
|
790
|
+
const localStreamFactory = async () => {
|
|
791
|
+
this.mediaStream = await navigator.mediaDevices.getUserMedia(constrains);
|
|
792
|
+
return this.mediaStream;
|
|
793
|
+
};
|
|
794
|
+
const {
|
|
795
|
+
userPart,
|
|
796
|
+
fsIp,
|
|
797
|
+
fsPort,
|
|
798
|
+
iceInfo,
|
|
799
|
+
wsUrl
|
|
800
|
+
} = userInfo;
|
|
801
|
+
const connectConfig = {
|
|
802
|
+
uri: UserAgent.makeURI(`sip:${userPart}@${fsIp}:${fsPort}`),
|
|
803
|
+
displayName: userPart,
|
|
804
|
+
transportOptions: {
|
|
805
|
+
wsServers: [wsUrl],
|
|
806
|
+
traceSip: true
|
|
807
|
+
},
|
|
808
|
+
logLevel: "error",
|
|
809
|
+
allowLegacyNotifications: true,
|
|
810
|
+
contactName: userPart,
|
|
811
|
+
sessionDescriptionHandlerFactory: Web.defaultSessionDescriptionHandlerFactory(localStreamFactory),
|
|
812
|
+
sessionDescriptionHandlerFactoryOptions: {
|
|
813
|
+
constraints: constrains,
|
|
814
|
+
iceGatheringTimeout: userInfo.iceGatheringTimeout,
|
|
815
|
+
peerConnectionConfiguration: {
|
|
816
|
+
iceServers: JSON.parse(convertObjectStringToJSON(iceInfo))
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
this.callKit.logger.debug("connect connectConfig", connectConfig);
|
|
821
|
+
this.userAgent = new UserAgent(connectConfig);
|
|
822
|
+
const remoteStream = new MediaStream();
|
|
823
|
+
const setupRemoteMedia = (session) => {
|
|
824
|
+
const audioRef = this.getAduioReference();
|
|
825
|
+
this.callKit.logger.debug("connect setupRemoteMedia", audioRef);
|
|
826
|
+
session.sessionDescriptionHandler.peerConnection.getReceivers().forEach((receiver) => {
|
|
827
|
+
if (receiver.track) {
|
|
828
|
+
remoteStream.addTrack(receiver.track);
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
if (audioRef) {
|
|
832
|
+
audioRef.srcObject = remoteStream;
|
|
833
|
+
audioRef.play().catch((error) => {
|
|
834
|
+
this.callKit.logger.error(error.message, {
|
|
835
|
+
errCode: ErrorCode.WEBRTC_AUDIO_PLAY_ERROR
|
|
836
|
+
});
|
|
837
|
+
});
|
|
838
|
+
} else {
|
|
839
|
+
this.callKit.logger.error("video is not exist", {
|
|
840
|
+
errCode: ErrorCode.WEBRTC_AUDIO_PLAYER_ERROR
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
const registererOptions = {};
|
|
845
|
+
this.registerer = new Registerer(this.userAgent, registererOptions);
|
|
846
|
+
this.userAgent.delegate = {
|
|
847
|
+
onInvite: (invite) => {
|
|
848
|
+
this.callKit.logger.debug("connect onInvite");
|
|
849
|
+
this.currentSession = invite;
|
|
850
|
+
this.currentSession.stateChange.addListener((state) => {
|
|
851
|
+
switch (state) {
|
|
852
|
+
case SessionState.Establishing:
|
|
853
|
+
this.callKit.logger.debug("connect Establishing");
|
|
854
|
+
break;
|
|
855
|
+
case SessionState.Established:
|
|
856
|
+
this.callKit.logger.debug("connect Established");
|
|
857
|
+
if (this.connectStatus === CallStatus.registered) {
|
|
858
|
+
this.callKit.logger.warn("call is already hangup");
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
this.sipConnected = true;
|
|
862
|
+
setupRemoteMedia(this.currentSession);
|
|
863
|
+
break;
|
|
864
|
+
case SessionState.Terminating:
|
|
865
|
+
this.callKit.logger.debug("connect Terminating");
|
|
866
|
+
break;
|
|
867
|
+
case SessionState.Terminated:
|
|
868
|
+
this.callKit.logger.debug("connect Terminated");
|
|
869
|
+
if (!this.isUnprompted) {
|
|
870
|
+
this.callKit.callCenter.callEnd();
|
|
871
|
+
}
|
|
872
|
+
this.isUnprompted = false;
|
|
873
|
+
break;
|
|
874
|
+
default:
|
|
875
|
+
break;
|
|
876
|
+
}
|
|
877
|
+
});
|
|
878
|
+
const options = {
|
|
879
|
+
sessionDescriptionHandlerOptions: {
|
|
880
|
+
constraints: constrains,
|
|
881
|
+
alwaysAcquireMediaFirst: true
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
if (this.isOutgoing) {
|
|
885
|
+
this.currentSession.accept(options);
|
|
886
|
+
} else {
|
|
887
|
+
this.callKit.trigger(KitEvent.KIT_INVITE, {
|
|
888
|
+
accept: () => {
|
|
889
|
+
this.setConnectStatus(CallStatus.connecting);
|
|
890
|
+
this.callKit.trigger(KitEvent.CALL_CONNECTING, /* @__PURE__ */ new Date());
|
|
891
|
+
this.currentSession.accept(options);
|
|
892
|
+
},
|
|
893
|
+
reject: () => {
|
|
894
|
+
this.currentSession.reject();
|
|
895
|
+
this.callKit.callCenter.callEnd(true, false);
|
|
896
|
+
},
|
|
897
|
+
getInviteData: () => {
|
|
898
|
+
const { request: request2 } = this.currentSession;
|
|
899
|
+
const headerNames = Object.keys(request2.headers);
|
|
900
|
+
const xHeaders = {};
|
|
901
|
+
headerNames.filter((name) => name.toLocaleLowerCase().startsWith("x-antaios")).forEach((name) => {
|
|
902
|
+
xHeaders[name.toLocaleLowerCase()] = request2.getHeader(name);
|
|
903
|
+
});
|
|
904
|
+
this.callKit.logger.debug("get invite data", xHeaders);
|
|
905
|
+
return xHeaders;
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
},
|
|
910
|
+
onConnect: async () => {
|
|
911
|
+
this.callKit.logger.debug("connect onConnect");
|
|
912
|
+
await this.registerer.register().then(() => {
|
|
913
|
+
this.callKit.socket.send(SocketSendEvent.START);
|
|
914
|
+
}).catch((err) => {
|
|
915
|
+
this.callKit.logger.error(err?.message, {
|
|
916
|
+
errCode: ErrorCode.WEBRTC_REGISTER_ERROR
|
|
917
|
+
});
|
|
918
|
+
});
|
|
919
|
+
},
|
|
920
|
+
onDisconnect: () => {
|
|
921
|
+
this.callKit.logger.debug("connect onDisconnect");
|
|
922
|
+
this.callKit.callCenter.callEnd();
|
|
923
|
+
},
|
|
924
|
+
onRegister: () => {
|
|
925
|
+
this.callKit.logger.debug("connect onRegister");
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
await this.userAgent.start().catch((err) => {
|
|
929
|
+
this.callKit.callCenter.callEnd(false, true);
|
|
930
|
+
this.callKit.logger.error(err, {
|
|
931
|
+
errCode: ErrorCode.WEBRTC_USER_AGENT_ERROR
|
|
932
|
+
});
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
async unregister() {
|
|
936
|
+
this.callKit.logger.debug("connect unregister");
|
|
937
|
+
if (!this.isRegistered() || !this.registerer) {
|
|
938
|
+
this.callKit.logger.warn("No registerer to unregister.");
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
await this.registerer.unregister({ all: true }).then(() => {
|
|
942
|
+
this.setConnectStatus(CallStatus.init);
|
|
943
|
+
}).catch((err) => {
|
|
944
|
+
this.callKit.logger.error(err, {
|
|
945
|
+
errCode: ErrorCode.WEBRTC_CANCEL_REGISTER_ERROR
|
|
946
|
+
});
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
async call(callback) {
|
|
950
|
+
this.callKit.logger.debug("connect call");
|
|
951
|
+
this.isOutgoing = true;
|
|
952
|
+
if (!this.isRegistered()) {
|
|
953
|
+
await this.register();
|
|
954
|
+
}
|
|
955
|
+
this.setConnectStatus(CallStatus.connecting);
|
|
956
|
+
this.callKit.trigger(KitEvent.CALL_CONNECTING, /* @__PURE__ */ new Date());
|
|
957
|
+
const { userInfo } = this.callKit.config.getConfig();
|
|
958
|
+
callback(userInfo);
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Update registration status
|
|
962
|
+
* @param register
|
|
963
|
+
*/
|
|
964
|
+
setRegister(register) {
|
|
965
|
+
this.callKit.logger.debug(`connect setRegister:${register}`);
|
|
966
|
+
this.callKit.trigger(KitEvent.KIT_REGISTER_CHANGE, register);
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Set call status
|
|
970
|
+
* @param status
|
|
971
|
+
*/
|
|
972
|
+
setConnectStatus(status) {
|
|
973
|
+
this.callKit.logger.debug(`connect setConnectStatus: ${status}`);
|
|
974
|
+
if (this.isRegistered() && status === CallStatus.init) {
|
|
975
|
+
this.setRegister(false);
|
|
976
|
+
}
|
|
977
|
+
if (!this.isRegistered() && status !== CallStatus.init) {
|
|
978
|
+
this.setRegister(true);
|
|
979
|
+
}
|
|
980
|
+
this.connectStatus = status;
|
|
981
|
+
this.callKit.trigger(KitEvent.KIT_CALL_STATUS_CHANGE, status);
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Hang up
|
|
985
|
+
* @param isUnprompted Whether actively hanging up
|
|
986
|
+
* @param isError Whether an error occurred
|
|
987
|
+
* @returns
|
|
988
|
+
*/
|
|
989
|
+
async hangup(isUnprompted = false, isError = false) {
|
|
990
|
+
this.callKit.logger.debug(`connect hangup isError: ${isError}`);
|
|
991
|
+
if (this.connectStatus === CallStatus.init || this.connectStatus === CallStatus.registered)
|
|
992
|
+
return;
|
|
993
|
+
this.isOutgoing = false;
|
|
994
|
+
this.isUnprompted = isUnprompted;
|
|
995
|
+
try {
|
|
996
|
+
if (isUnprompted) {
|
|
997
|
+
this.callKit.socket.send(SocketSendEvent.AGENT_HANGUP);
|
|
998
|
+
const shouldSendBye = this.sipConnected || this.isRinging() || this.isCalling() || this.isHolding();
|
|
999
|
+
if (shouldSendBye) {
|
|
1000
|
+
await this.currentSession?.bye();
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
this.sipConnected = false;
|
|
1004
|
+
closeStream(this.mediaStream);
|
|
1005
|
+
const audioRef = this.getAduioReference();
|
|
1006
|
+
if (audioRef) {
|
|
1007
|
+
audioRef.pause();
|
|
1008
|
+
audioRef.srcObject = null;
|
|
1009
|
+
}
|
|
1010
|
+
if (isError) {
|
|
1011
|
+
this.setConnectStatus(CallStatus.init);
|
|
1012
|
+
} else {
|
|
1013
|
+
this.setConnectStatus(CallStatus.registered);
|
|
1014
|
+
}
|
|
1015
|
+
this.callKit.trigger(KitEvent.CALL_END, /* @__PURE__ */ new Date());
|
|
1016
|
+
} catch (err) {
|
|
1017
|
+
this.callKit.trigger(KitEvent.CALL_END, /* @__PURE__ */ new Date());
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* The remote media stream. Undefined if call not answered.
|
|
1022
|
+
* @param session - Session to get the media stream from.
|
|
1023
|
+
*/
|
|
1024
|
+
getRemoteMediaStream(session) {
|
|
1025
|
+
this.callKit.logger.debug("connect getRemoteMediaStream");
|
|
1026
|
+
const sdh = session.sessionDescriptionHandler;
|
|
1027
|
+
if (!sdh) {
|
|
1028
|
+
return void 0;
|
|
1029
|
+
}
|
|
1030
|
+
return sdh.remoteMediaStream;
|
|
1031
|
+
}
|
|
1032
|
+
setupRemoteMedia(session) {
|
|
1033
|
+
this.callKit.logger.debug("connect setupRemoteMedia");
|
|
1034
|
+
const remoteStream = this.getRemoteMediaStream(session);
|
|
1035
|
+
const audioRef = this.getAduioReference();
|
|
1036
|
+
if (audioRef) {
|
|
1037
|
+
audioRef.autoplay = true;
|
|
1038
|
+
audioRef.srcObject = remoteStream;
|
|
1039
|
+
audioRef.play().catch((error) => {
|
|
1040
|
+
this.callKit.logger.error(error.message, {
|
|
1041
|
+
errCode: ErrorCode.WEBRTC_AUDIO_PLAY_ERROR
|
|
1042
|
+
});
|
|
1043
|
+
});
|
|
1044
|
+
remoteStream.onaddtrack = () => {
|
|
1045
|
+
this.callKit.logger.debug("Remote media onaddtrack");
|
|
1046
|
+
audioRef.load();
|
|
1047
|
+
audioRef.play().catch((error) => {
|
|
1048
|
+
this.callKit.logger.error(error.message, {
|
|
1049
|
+
errCode: ErrorCode.WEBRTC_AUDIO_PLAY_ERROR
|
|
1050
|
+
});
|
|
1051
|
+
});
|
|
1052
|
+
};
|
|
1053
|
+
} else {
|
|
1054
|
+
this.callKit.logger.error("video is not exist", {
|
|
1055
|
+
errCode: ErrorCode.WEBRTC_AUDIO_PLAYER_ERROR
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Update hold
|
|
1061
|
+
* @param hold
|
|
1062
|
+
*/
|
|
1063
|
+
setHoldStatus(hold) {
|
|
1064
|
+
this.callKit.logger.debug("connect setHold", hold);
|
|
1065
|
+
this.isHold = hold;
|
|
1066
|
+
this.callKit.trigger(KitEvent.KIT_SET_HOLD, hold);
|
|
1067
|
+
}
|
|
1068
|
+
async setHold(hold) {
|
|
1069
|
+
this.setHoldStatus(hold);
|
|
1070
|
+
}
|
|
1071
|
+
async hold() {
|
|
1072
|
+
this.callKit.logger.debug("connect hold");
|
|
1073
|
+
if (this.connectStatus !== CallStatus.calling || !this.currentSession) {
|
|
1074
|
+
this.callKit.logger.error("Current status is not in call", {
|
|
1075
|
+
errCode: ErrorCode.WEBRTC_HOLE_STATUS_ERROR
|
|
1076
|
+
});
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
await this.setHold(true);
|
|
1080
|
+
}
|
|
1081
|
+
async unhold() {
|
|
1082
|
+
this.callKit.logger.debug("connect unhold");
|
|
1083
|
+
await this.setHold(false);
|
|
1084
|
+
}
|
|
1085
|
+
async setMute(mute) {
|
|
1086
|
+
this.callKit.logger.debug("connect setMute", mute);
|
|
1087
|
+
if (!this.currentSession) {
|
|
1088
|
+
this.callKit.logger.error("No active session", {
|
|
1089
|
+
errCode: ErrorCode.WEBRTC_MUTE_STATUS_ERROR
|
|
1090
|
+
});
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
try {
|
|
1094
|
+
const sdh = this.currentSession.sessionDescriptionHandler;
|
|
1095
|
+
if (!sdh || !("peerConnection" in sdh)) {
|
|
1096
|
+
throw new Error("Invalid session description handler");
|
|
1097
|
+
}
|
|
1098
|
+
const pc = sdh.peerConnection;
|
|
1099
|
+
const audioSender = pc.getSenders().find((sender) => sender.track?.kind === "audio");
|
|
1100
|
+
if (audioSender && audioSender.track) {
|
|
1101
|
+
audioSender.track.enabled = !mute;
|
|
1102
|
+
this.isMute = mute;
|
|
1103
|
+
this.callKit.trigger(KitEvent.KIT_SET_MUTE, mute);
|
|
1104
|
+
} else {
|
|
1105
|
+
throw new Error("No audio track found");
|
|
1106
|
+
}
|
|
1107
|
+
} catch (error) {
|
|
1108
|
+
this.callKit.logger.error("Failed to set mute state", {
|
|
1109
|
+
errCode: ErrorCode.WEBRTC_MUTE_ERROR,
|
|
1110
|
+
error
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
async mute() {
|
|
1115
|
+
this.callKit.logger.debug("connect mute");
|
|
1116
|
+
if (this.connectStatus !== CallStatus.calling || !this.currentSession) {
|
|
1117
|
+
this.callKit.logger.error("Current status is not in call", {
|
|
1118
|
+
errCode: ErrorCode.WEBRTC_MUTE_STATUS_ERROR
|
|
1119
|
+
});
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
await this.setMute(true);
|
|
1123
|
+
}
|
|
1124
|
+
async unmute() {
|
|
1125
|
+
this.callKit.logger.debug("connect unmute");
|
|
1126
|
+
if (this.connectStatus !== CallStatus.calling || !this.currentSession) {
|
|
1127
|
+
this.callKit.logger.error("Current status is not in call", {
|
|
1128
|
+
errCode: ErrorCode.WEBRTC_MUTE_STATUS_ERROR
|
|
1129
|
+
});
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
await this.setMute(false);
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
|
|
1136
|
+
// package/socket.ts
|
|
1137
|
+
var RECONNECT_CONFIG = {
|
|
1138
|
+
enabled: true,
|
|
1139
|
+
maxAttempts: 1,
|
|
1140
|
+
delay: 1e3,
|
|
1141
|
+
backoffMultiplier: 1.5,
|
|
1142
|
+
pingInterval: 3e4,
|
|
1143
|
+
pingTimeout: 5e3
|
|
1144
|
+
};
|
|
1145
|
+
var Socket = class {
|
|
1146
|
+
callKit;
|
|
1147
|
+
ws;
|
|
1148
|
+
socketConfig;
|
|
1149
|
+
lastPingTime = void 0;
|
|
1150
|
+
isConnected = false;
|
|
1151
|
+
pingTimer;
|
|
1152
|
+
// Whether received server hangup confirmation
|
|
1153
|
+
recivedClose = false;
|
|
1154
|
+
// Whether received start confirmation
|
|
1155
|
+
satrtConfirm = false;
|
|
1156
|
+
reconnectTimer;
|
|
1157
|
+
isReconnecting = false;
|
|
1158
|
+
reconnectAttempts = 0;
|
|
1159
|
+
constructor(callKit) {
|
|
1160
|
+
this.callKit = callKit;
|
|
1161
|
+
const { reconnect } = this.callKit.config.getConfig();
|
|
1162
|
+
this.socketConfig = {
|
|
1163
|
+
...RECONNECT_CONFIG,
|
|
1164
|
+
...reconnect
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
init() {
|
|
1168
|
+
const { socket } = this.callKit.config.getConfig();
|
|
1169
|
+
this.callKit.logger.debug(`socket init: ${socket}`);
|
|
1170
|
+
this.connect(socket);
|
|
1171
|
+
}
|
|
1172
|
+
connect(socketUrl) {
|
|
1173
|
+
this.ws = new WebSocket(socketUrl);
|
|
1174
|
+
this.ws.onopen = (ev) => this.onOpen(ev);
|
|
1175
|
+
this.ws.onclose = (ev) => this.onClose(ev);
|
|
1176
|
+
this.ws.onerror = (ev) => this.onError(ev);
|
|
1177
|
+
this.ws.onmessage = (ev) => this.onMessage(ev);
|
|
1178
|
+
}
|
|
1179
|
+
onOpen(ev) {
|
|
1180
|
+
this.callKit.logger.debug("socket onOpen", ev);
|
|
1181
|
+
this.isConnected = true;
|
|
1182
|
+
this.lastPingTime = Date.now();
|
|
1183
|
+
this.checkPing();
|
|
1184
|
+
if (this.reconnectTimer) {
|
|
1185
|
+
clearTimeout(this.reconnectTimer);
|
|
1186
|
+
}
|
|
1187
|
+
this.reconnectAttempts = 0;
|
|
1188
|
+
}
|
|
1189
|
+
onClose(ev) {
|
|
1190
|
+
this.callKit.logger.debug("socket onClose", ev);
|
|
1191
|
+
this.isConnected = false;
|
|
1192
|
+
this.satrtConfirm = false;
|
|
1193
|
+
if (this.pingTimer) {
|
|
1194
|
+
clearInterval(this.pingTimer);
|
|
1195
|
+
this.pingTimer = void 0;
|
|
1196
|
+
}
|
|
1197
|
+
this.callKit.connect.hangup();
|
|
1198
|
+
this.reset();
|
|
1199
|
+
}
|
|
1200
|
+
onError(ev) {
|
|
1201
|
+
this.callKit.logger.error("socket onError", {
|
|
1202
|
+
errCode: ErrorCode.SOCKET_CONNECT_ERROR,
|
|
1203
|
+
data: ev
|
|
1204
|
+
});
|
|
1205
|
+
this.isConnected = false;
|
|
1206
|
+
if (!this.isReconnecting && this.socketConfig.maxAttempts > 0) {
|
|
1207
|
+
this.attemptReconnect();
|
|
1208
|
+
} else if (this.reconnectAttempts >= this.socketConfig.maxAttempts) {
|
|
1209
|
+
this.reset();
|
|
1210
|
+
this.callKit.logger.error(
|
|
1211
|
+
"Reconnection failed, maximum retry attempts reached",
|
|
1212
|
+
{
|
|
1213
|
+
errCode: ErrorCode.SOCKET_RECONNECT_FAILED
|
|
1214
|
+
}
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
onMessage(ev) {
|
|
1219
|
+
const data = JSON.parse(ev.data);
|
|
1220
|
+
this.callKit.logger.debug("socket onMessage", data);
|
|
1221
|
+
if (data.event === SocketReceiveEvent.PONG) {
|
|
1222
|
+
this.lastPingTime = Date.now();
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1225
|
+
if (data.event === SocketReceiveEvent.START_CONFIRM) {
|
|
1226
|
+
this.callKit.logger.debug("register success");
|
|
1227
|
+
this.satrtConfirm = true;
|
|
1228
|
+
this.callKit.connect.setConnectStatus(CallStatus.registered);
|
|
1229
|
+
}
|
|
1230
|
+
if (data.event === SocketReceiveEvent.CALL_SUCCESS) {
|
|
1231
|
+
this.recivedClose = false;
|
|
1232
|
+
this.callKit.logger.debug("callStart");
|
|
1233
|
+
this.callKit.user.setUserStatus(UserStatus.busy);
|
|
1234
|
+
}
|
|
1235
|
+
if (data.event === SocketReceiveEvent.CALL_FAILED) {
|
|
1236
|
+
this.callKit.logger.debug(data.msg, {
|
|
1237
|
+
errCode: ErrorCode.SOCKET_CALL_ERROR
|
|
1238
|
+
});
|
|
1239
|
+
this.callKit.user.setUserStatus(UserStatus.online);
|
|
1240
|
+
}
|
|
1241
|
+
if (data.event === SocketReceiveEvent.CUSTOMER_RINGING) {
|
|
1242
|
+
this.callKit.logger.debug(data.msg);
|
|
1243
|
+
if (this.callKit.connect.isConnecting()) {
|
|
1244
|
+
this.callKit.trigger(KitEvent.CALL_RINGING, /* @__PURE__ */ new Date());
|
|
1245
|
+
this.callKit.connect.setConnectStatus(CallStatus.ringing);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
if (data.event === SocketReceiveEvent.CUSTOMER_PICK_UP) {
|
|
1249
|
+
this.callKit.logger.debug(data.msg);
|
|
1250
|
+
if (this.callKit.connect.isRinging()) {
|
|
1251
|
+
this.callKit.connect.setConnectStatus(CallStatus.calling);
|
|
1252
|
+
this.callKit.trigger(KitEvent.CALL_PICK_UP, /* @__PURE__ */ new Date());
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
if (data.event === SocketReceiveEvent.AGENT_PICK_UP) {
|
|
1256
|
+
this.callKit.logger.debug(data.msg);
|
|
1257
|
+
this.callKit.trigger(KitEvent.AGENT_PICK_UP, /* @__PURE__ */ new Date());
|
|
1258
|
+
}
|
|
1259
|
+
if (data.event === SocketReceiveEvent.CUSTOMER_HANG_UP) {
|
|
1260
|
+
this.callKit.logger.debug(data.msg);
|
|
1261
|
+
this.callKit.trigger(KitEvent.CALL_HANG_UP, /* @__PURE__ */ new Date());
|
|
1262
|
+
this.callKit.user.setUserStatus(UserStatus.catNap);
|
|
1263
|
+
}
|
|
1264
|
+
if (data.event === SocketReceiveEvent.CUSTOMER_NO_ANSWER) {
|
|
1265
|
+
this.callKit.logger.debug(data.msg);
|
|
1266
|
+
this.callKit.trigger(KitEvent.CALL_NO_ANSWER);
|
|
1267
|
+
this.callKit.user.setUserStatus(UserStatus.catNap);
|
|
1268
|
+
}
|
|
1269
|
+
if (data.event === SocketReceiveEvent.CALL_CDR) {
|
|
1270
|
+
this.callKit.logger.debug(data.msg);
|
|
1271
|
+
this.callKit.trigger(KitEvent.CALL_CDR, data.data);
|
|
1272
|
+
}
|
|
1273
|
+
if (data.event === SocketReceiveEvent.STOP_CONFIRM) {
|
|
1274
|
+
this.callKit.logger.debug(data.msg);
|
|
1275
|
+
this.recivedClose = true;
|
|
1276
|
+
}
|
|
1277
|
+
if (data.event === SocketReceiveEvent.CLOSE) {
|
|
1278
|
+
const { userInfo } = this.callKit.config.getConfig();
|
|
1279
|
+
this.callKit.logger.debug(data.msg);
|
|
1280
|
+
this.send(SocketSendEvent.END, {
|
|
1281
|
+
agentId: userInfo.agentId
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
if (data.event === SocketReceiveEvent.ERROR) {
|
|
1285
|
+
this.callKit.logger.error(data.msg, {
|
|
1286
|
+
errCode: ErrorCode.SOKET_SERVER_ERROR,
|
|
1287
|
+
data
|
|
1288
|
+
});
|
|
1289
|
+
this.callKit.user.setUserStatus(UserStatus.catNap);
|
|
1290
|
+
}
|
|
1291
|
+
if (data.event === SocketReceiveEvent.AGENT_NO_ANSWER) {
|
|
1292
|
+
this.callKit.user.setUserStatus(UserStatus.catNap);
|
|
1293
|
+
}
|
|
1294
|
+
this.callKit.trigger(KitEvent.SERVER_SOCKET_EVENT, data);
|
|
1295
|
+
}
|
|
1296
|
+
send(event, message) {
|
|
1297
|
+
if (!this.isConnected) {
|
|
1298
|
+
this.callKit.logger.error("socket not connected", {
|
|
1299
|
+
errCode: ErrorCode.SOCKET_CONNECT_ERROR
|
|
1300
|
+
});
|
|
1301
|
+
this.callKit.config.reset();
|
|
1302
|
+
this.callKit.reset();
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
const { userInfo } = this.callKit.config.getConfig();
|
|
1306
|
+
const { sessionId, extno, agentId } = userInfo;
|
|
1307
|
+
if (!sessionId) {
|
|
1308
|
+
this.callKit.logger.error("sessionId is empty", {
|
|
1309
|
+
errCode: ErrorCode.SOCKET_CONNECT_ERROR
|
|
1310
|
+
});
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
const msg = {
|
|
1314
|
+
event,
|
|
1315
|
+
sessionId,
|
|
1316
|
+
...message
|
|
1317
|
+
};
|
|
1318
|
+
if (SocketSendEvent.CALL === event) {
|
|
1319
|
+
msg.phoneNum = extno;
|
|
1320
|
+
msg.agentId = agentId;
|
|
1321
|
+
}
|
|
1322
|
+
this.callKit.logger.debug("socket send", msg);
|
|
1323
|
+
switch (event) {
|
|
1324
|
+
case SocketSendEvent.PING:
|
|
1325
|
+
this.lastPingTime = Date.now();
|
|
1326
|
+
this.ws?.send(JSON.stringify({ event, ...msg }));
|
|
1327
|
+
break;
|
|
1328
|
+
default:
|
|
1329
|
+
this.ws?.send(JSON.stringify({ event, ...msg }));
|
|
1330
|
+
break;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Attempt to close socket, need to wait for server confirmation
|
|
1335
|
+
* @returns
|
|
1336
|
+
*/
|
|
1337
|
+
async requestClose() {
|
|
1338
|
+
return new Promise((resolve) => {
|
|
1339
|
+
let remainingTime = 5;
|
|
1340
|
+
const interval = setInterval(() => {
|
|
1341
|
+
remainingTime -= 1;
|
|
1342
|
+
if (this.recivedClose || remainingTime <= 0) {
|
|
1343
|
+
clearInterval(interval);
|
|
1344
|
+
resolve(this.recivedClose);
|
|
1345
|
+
}
|
|
1346
|
+
}, 1e3);
|
|
1347
|
+
});
|
|
1348
|
+
}
|
|
1349
|
+
ping() {
|
|
1350
|
+
if (!this.isConnected)
|
|
1351
|
+
return;
|
|
1352
|
+
this.send(SocketSendEvent.PING);
|
|
1353
|
+
const now = Date.now();
|
|
1354
|
+
this.callKit.logger.debug(`socket ping: ${now - this.lastPingTime}ms`);
|
|
1355
|
+
const { pingInterval, pingTimeout } = this.socketConfig;
|
|
1356
|
+
if (now - this.lastPingTime > pingInterval + pingTimeout) {
|
|
1357
|
+
this.callKit.logger.error("socket ping timeout", {
|
|
1358
|
+
errCode: ErrorCode.SOCKET_PING_TIMEOUT
|
|
1359
|
+
});
|
|
1360
|
+
if (this.ws && this.isConnected) {
|
|
1361
|
+
this.ws.close(4001, "ping timeout");
|
|
1362
|
+
} else {
|
|
1363
|
+
this.reset();
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
checkPing() {
|
|
1368
|
+
if (this.pingTimer) {
|
|
1369
|
+
clearInterval(this.pingTimer);
|
|
1370
|
+
}
|
|
1371
|
+
this.ping();
|
|
1372
|
+
this.pingTimer = setInterval(() => {
|
|
1373
|
+
this.ping();
|
|
1374
|
+
}, this.socketConfig.pingInterval);
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
*
|
|
1378
|
+
* @param isWaitConfirm Whether need to wait for close confirmation
|
|
1379
|
+
*/
|
|
1380
|
+
async reset(isWaitConfirm = true) {
|
|
1381
|
+
if (this.pingTimer) {
|
|
1382
|
+
clearInterval(this.pingTimer);
|
|
1383
|
+
}
|
|
1384
|
+
if (this.reconnectTimer) {
|
|
1385
|
+
clearTimeout(this.reconnectTimer);
|
|
1386
|
+
}
|
|
1387
|
+
this.lastPingTime = void 0;
|
|
1388
|
+
this.pingTimer = void 0;
|
|
1389
|
+
this.satrtConfirm = false;
|
|
1390
|
+
this.isReconnecting = false;
|
|
1391
|
+
this.reconnectAttempts = 0;
|
|
1392
|
+
if (this.ws && this.isConnected) {
|
|
1393
|
+
if (isWaitConfirm) {
|
|
1394
|
+
await this.requestClose();
|
|
1395
|
+
}
|
|
1396
|
+
this.recivedClose = false;
|
|
1397
|
+
this.callKit.logger.debug("socket destroy");
|
|
1398
|
+
this.ws.close();
|
|
1399
|
+
this.isConnected = false;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
attemptReconnect() {
|
|
1403
|
+
if (this.isReconnecting) {
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
this.isReconnecting = true;
|
|
1407
|
+
const delay = this.socketConfig.delay * this.socketConfig.backoffMultiplier ** this.reconnectAttempts;
|
|
1408
|
+
this.callKit.logger.debug(
|
|
1409
|
+
`Preparing reconnection attempt ${this.reconnectAttempts + 1}, delay: ${delay}ms`
|
|
1410
|
+
);
|
|
1411
|
+
this.reconnectTimer = setTimeout(() => {
|
|
1412
|
+
const { socket } = this.callKit.config.getConfig();
|
|
1413
|
+
this.connect(socket);
|
|
1414
|
+
this.reconnectAttempts += 1;
|
|
1415
|
+
this.isReconnecting = false;
|
|
1416
|
+
}, delay);
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
|
|
1420
|
+
// package/user.ts
|
|
1421
|
+
var User = class {
|
|
1422
|
+
callKit;
|
|
1423
|
+
userStatus;
|
|
1424
|
+
// logout(1, "unregistered"), idle(2, "free"), break(3, "nap"), busy(4, "busy")
|
|
1425
|
+
constructor(callKit) {
|
|
1426
|
+
this.callKit = callKit;
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1429
|
+
*
|
|
1430
|
+
* @param status logout(1, "unregistered"), idle(2, "free"), break(3, "nap"), busy(4, "busy")
|
|
1431
|
+
*/
|
|
1432
|
+
async setUserStatus(status) {
|
|
1433
|
+
const { isAutoUpdateUserStatus } = this.callKit.config.getConfig();
|
|
1434
|
+
if (status === this.userStatus || !isAutoUpdateUserStatus)
|
|
1435
|
+
return;
|
|
1436
|
+
return this.updateUserStatus(status);
|
|
1437
|
+
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Update user status
|
|
1440
|
+
* @param status
|
|
1441
|
+
*/
|
|
1442
|
+
async updateUserStatus(status) {
|
|
1443
|
+
const { agentId } = this.callKit.config.getConfig().userInfo;
|
|
1444
|
+
if (!this.callKit.config.isLogin()) {
|
|
1445
|
+
this.userStatus = UserStatus.offline;
|
|
1446
|
+
this.callKit.trigger(KitEvent.KIT_USER_STATUS_CHANGE, UserStatus.offline);
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
await this.callKit.api.setUserStatus({
|
|
1450
|
+
agentId,
|
|
1451
|
+
userStatus: status
|
|
1452
|
+
}).then(() => {
|
|
1453
|
+
this.userStatus = status;
|
|
1454
|
+
this.callKit.trigger(KitEvent.KIT_USER_STATUS_CHANGE, status);
|
|
1455
|
+
}).catch((err) => {
|
|
1456
|
+
this.callKit.logger.error(err, {
|
|
1457
|
+
errCode: ErrorCode.API_USER_STATUS_UPDATE_ERROR
|
|
1458
|
+
});
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
};
|
|
1462
|
+
|
|
1463
|
+
// package/index.ts
|
|
1464
|
+
var CallKit = class {
|
|
1465
|
+
api;
|
|
1466
|
+
config;
|
|
1467
|
+
logger;
|
|
1468
|
+
callCenter;
|
|
1469
|
+
connect;
|
|
1470
|
+
socket;
|
|
1471
|
+
user;
|
|
1472
|
+
listener = [];
|
|
1473
|
+
constructor(options) {
|
|
1474
|
+
this.config = new Config(this);
|
|
1475
|
+
this.config.setConfig("log", options.log);
|
|
1476
|
+
this.config.setConfig("audioRef", options.audioRef);
|
|
1477
|
+
this.config.setConfig("host", options.host);
|
|
1478
|
+
this.config.setConfig(
|
|
1479
|
+
"constrains",
|
|
1480
|
+
options.constrains || constrainsDefault
|
|
1481
|
+
);
|
|
1482
|
+
this.config.setConfig("socket", options.socket);
|
|
1483
|
+
this.config.setConfig(
|
|
1484
|
+
"isAutoUpdateUserStatus",
|
|
1485
|
+
options.isAutoUpdateUserStatus === void 0 ? isAutoUpdateUserStatusDefault : options.isAutoUpdateUserStatus
|
|
1486
|
+
);
|
|
1487
|
+
this.logger = new Logger(this, options.log);
|
|
1488
|
+
this.logger.debug("callKit init", options);
|
|
1489
|
+
this.api = new Api(this);
|
|
1490
|
+
this.connect = new Connect(this);
|
|
1491
|
+
this.callCenter = new Call(this);
|
|
1492
|
+
this.socket = new Socket(this);
|
|
1493
|
+
this.user = new User(this);
|
|
1494
|
+
}
|
|
1495
|
+
async login(username, password, extra = {}) {
|
|
1496
|
+
if (this.config.isLogin()) {
|
|
1497
|
+
this.logger.warn("already login");
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
this.logger.debug("login info:", {
|
|
1501
|
+
username,
|
|
1502
|
+
password
|
|
1503
|
+
});
|
|
1504
|
+
const user = await this.api.login({
|
|
1505
|
+
userName: username,
|
|
1506
|
+
password: md5(username + md5(password))
|
|
1507
|
+
}).catch((err) => {
|
|
1508
|
+
this.logger.error(err, { errCode: ErrorCode.API_USER_LOGIN_ERROR });
|
|
1509
|
+
});
|
|
1510
|
+
if (user) {
|
|
1511
|
+
this.config.setConfig("userInfo", {
|
|
1512
|
+
wsUrl: `wss://${user.wsUrl}`,
|
|
1513
|
+
sessionId: user.sessionId,
|
|
1514
|
+
username,
|
|
1515
|
+
password,
|
|
1516
|
+
agentId: user.agentId,
|
|
1517
|
+
fsUserId: user.fsUserId,
|
|
1518
|
+
userPart: user.userPart,
|
|
1519
|
+
fsPassword: user.fsPassword,
|
|
1520
|
+
fsIp: user.fsIp,
|
|
1521
|
+
fsPort: user.fsPort,
|
|
1522
|
+
iceInfo: user.iceInfo,
|
|
1523
|
+
iceGatheringTimeout: user.iceGatheringTimeout,
|
|
1524
|
+
...extra
|
|
1525
|
+
});
|
|
1526
|
+
this.socket.init();
|
|
1527
|
+
this.trigger(KitEvent.KIT_LOGIN_CHANGE, true);
|
|
1528
|
+
this.user.setUserStatus(UserStatus.offline);
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
async logout() {
|
|
1532
|
+
if (!this.config.check())
|
|
1533
|
+
return;
|
|
1534
|
+
this.logger.debug("logout");
|
|
1535
|
+
await this.user.setUserStatus(UserStatus.offline);
|
|
1536
|
+
if (this.config.isLogin()) {
|
|
1537
|
+
const { sessionId } = this.config.getConfig().userInfo;
|
|
1538
|
+
this.api.loginOut({ sessionId }).catch((err) => {
|
|
1539
|
+
this.logger.error(err, { errCode: ErrorCode.API_USER_LOGOUT_ERROR });
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1542
|
+
await this.hangup();
|
|
1543
|
+
this.socket.reset(false);
|
|
1544
|
+
this.connect.reset();
|
|
1545
|
+
this.config.reset();
|
|
1546
|
+
this.trigger(KitEvent.KIT_LOGIN_CHANGE, false);
|
|
1547
|
+
}
|
|
1548
|
+
async call(extno) {
|
|
1549
|
+
if (!this.config.check())
|
|
1550
|
+
return;
|
|
1551
|
+
if (!this.connect.isRegistered()) {
|
|
1552
|
+
this.logger.warn("Currently not registered");
|
|
1553
|
+
return;
|
|
1554
|
+
}
|
|
1555
|
+
if (extno) {
|
|
1556
|
+
this.config.setUserInfo("extno", extno);
|
|
1557
|
+
}
|
|
1558
|
+
this.logger.debug("call");
|
|
1559
|
+
this.callCenter.callStart();
|
|
1560
|
+
}
|
|
1561
|
+
async register() {
|
|
1562
|
+
if (!this.config.check())
|
|
1563
|
+
return;
|
|
1564
|
+
this.logger.debug("register");
|
|
1565
|
+
this.connect.register();
|
|
1566
|
+
await this.user.setUserStatus(UserStatus.online);
|
|
1567
|
+
}
|
|
1568
|
+
async unregister() {
|
|
1569
|
+
if (!this.config.check())
|
|
1570
|
+
return;
|
|
1571
|
+
this.logger.debug("unregister");
|
|
1572
|
+
this.connect.unregister();
|
|
1573
|
+
await this.user.setUserStatus(UserStatus.offline);
|
|
1574
|
+
}
|
|
1575
|
+
async hangup() {
|
|
1576
|
+
if (!this.config.check())
|
|
1577
|
+
return;
|
|
1578
|
+
this.logger.debug("hangup", this.connect.connectStatus);
|
|
1579
|
+
if (!this.connect.isConnecting() && !this.connect.isRinging() && !this.connect.isCalling() && !this.connect.isHolding()) {
|
|
1580
|
+
this.logger.warn("Currently not in a call");
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
await this.callCenter.callEnd(true);
|
|
1584
|
+
this.user.setUserStatus(UserStatus.catNap);
|
|
1585
|
+
}
|
|
1586
|
+
hold() {
|
|
1587
|
+
if (!this.config.check())
|
|
1588
|
+
return;
|
|
1589
|
+
this.logger.debug("hold");
|
|
1590
|
+
this.callCenter.callHold();
|
|
1591
|
+
}
|
|
1592
|
+
unhold() {
|
|
1593
|
+
if (!this.config.check())
|
|
1594
|
+
return;
|
|
1595
|
+
this.logger.debug("unhold");
|
|
1596
|
+
this.callCenter.callUnhold();
|
|
1597
|
+
}
|
|
1598
|
+
async setFree() {
|
|
1599
|
+
if (!this.config.check())
|
|
1600
|
+
return;
|
|
1601
|
+
this.logger.debug("setFree");
|
|
1602
|
+
await this.user.setUserStatus(UserStatus.online);
|
|
1603
|
+
}
|
|
1604
|
+
async setSleep() {
|
|
1605
|
+
if (!this.config.check())
|
|
1606
|
+
return;
|
|
1607
|
+
this.logger.debug("setSleep");
|
|
1608
|
+
await this.user.setUserStatus(UserStatus.catNap);
|
|
1609
|
+
}
|
|
1610
|
+
async setBusy() {
|
|
1611
|
+
if (!this.config.check())
|
|
1612
|
+
return;
|
|
1613
|
+
this.logger.debug("setBusy");
|
|
1614
|
+
await this.user.setUserStatus(UserStatus.busy);
|
|
1615
|
+
}
|
|
1616
|
+
async reset() {
|
|
1617
|
+
this.logger.debug("reset");
|
|
1618
|
+
this.connect.reset();
|
|
1619
|
+
if (this.config.isLogin()) {
|
|
1620
|
+
await this.user.setUserStatus(UserStatus.online);
|
|
1621
|
+
} else {
|
|
1622
|
+
await this.user.setUserStatus(UserStatus.offline);
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
on(event, callback) {
|
|
1626
|
+
this.logger.debug(`on ${event}`);
|
|
1627
|
+
this.listener.push({
|
|
1628
|
+
event,
|
|
1629
|
+
callback
|
|
1630
|
+
});
|
|
1631
|
+
}
|
|
1632
|
+
off(event, callback) {
|
|
1633
|
+
this.logger.debug(`off ${event}`);
|
|
1634
|
+
if (callback) {
|
|
1635
|
+
this.listener = this.listener.filter(
|
|
1636
|
+
(item) => !(item.event === event && item.callback === callback)
|
|
1637
|
+
);
|
|
1638
|
+
} else {
|
|
1639
|
+
this.listener = this.listener.filter((item) => item.event !== event);
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
removeAllListeners() {
|
|
1643
|
+
this.listener = this.listener.splice(0, this.listener.length);
|
|
1644
|
+
this.logger.debug("removeAllListeners");
|
|
1645
|
+
}
|
|
1646
|
+
trigger(event, data) {
|
|
1647
|
+
this.logger.debug(`trigger ${event}`, { data });
|
|
1648
|
+
this.listener.forEach((item) => {
|
|
1649
|
+
if (item.event === event) {
|
|
1650
|
+
try {
|
|
1651
|
+
item.callback(data);
|
|
1652
|
+
} catch (err) {
|
|
1653
|
+
this.logger.error("Event callback error:", err);
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
});
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
export {
|
|
1660
|
+
CallKit
|
|
1661
|
+
};
|
|
1662
|
+
//# sourceMappingURL=index.mjs.map
|