@flashphoner/sfusdk 1.0.1-35 → 1.0.40
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/Gruntfile.js +13 -0
- package/README.md +1 -1
- package/docTemplate/README.md +1 -1
- package/package.json +13 -5
- package/src/examples/commons/js/config.js +81 -0
- package/src/examples/commons/js/display.js +484 -0
- package/src/examples/commons/js/util.js +202 -0
- package/src/examples/commons/media/silence.mp3 +0 -0
- package/src/examples/player/config.json +8 -0
- package/src/examples/player/player.css +19 -0
- package/src/examples/player/player.html +54 -0
- package/src/examples/player/player.js +206 -0
- package/src/examples/two-way-streaming/config.json +34 -0
- package/src/examples/two-way-streaming/two-way-streaming.css +26 -0
- package/src/examples/two-way-streaming/two-way-streaming.html +72 -0
- package/src/examples/two-way-streaming/two-way-streaming.js +346 -0
- package/src/sdk/constants.js +30 -2
- package/src/sdk/messaging.js +22 -11
- package/src/sdk/promise.js +13 -3
- package/src/sdk/sfu-extended.js +149 -19
- package/src/tests/sdk/sfu-extended.test.js +151 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
const constants = SFU.constants;
|
|
2
|
+
const sfu = SFU;
|
|
3
|
+
let mainConfig;
|
|
4
|
+
let localDisplay;
|
|
5
|
+
let remoteDisplay;
|
|
6
|
+
let publishState;
|
|
7
|
+
let playState;
|
|
8
|
+
const PUBLISH = "publish";
|
|
9
|
+
const PLAY = "play";
|
|
10
|
+
const STOP = "stop";
|
|
11
|
+
const PRELOADER_URL="../commons/media/silence.mp3"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Default publishing config
|
|
16
|
+
*/
|
|
17
|
+
const defaultConfig = {
|
|
18
|
+
room: {
|
|
19
|
+
url: "wss://127.0.0.1:8888",
|
|
20
|
+
name: "ROOM1",
|
|
21
|
+
pin: "1234",
|
|
22
|
+
nickName: "User1"
|
|
23
|
+
},
|
|
24
|
+
media: {
|
|
25
|
+
audio: {
|
|
26
|
+
tracks: [
|
|
27
|
+
{
|
|
28
|
+
source: "mic",
|
|
29
|
+
channels: 1
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
video: {
|
|
34
|
+
tracks: [
|
|
35
|
+
{
|
|
36
|
+
source: "camera",
|
|
37
|
+
width: 640,
|
|
38
|
+
height: 360,
|
|
39
|
+
codec: "H264",
|
|
40
|
+
encodings: [
|
|
41
|
+
{ rid: "360p", active: true, maxBitrate: 500000 },
|
|
42
|
+
{ rid: "180p", active: true, maxBitrate: 200000, scaleResolutionDownBy: 2 }
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Current state object
|
|
52
|
+
*/
|
|
53
|
+
const CurrentState = function(prefix) {
|
|
54
|
+
let state = {
|
|
55
|
+
prefix: prefix,
|
|
56
|
+
pc: null,
|
|
57
|
+
session: null,
|
|
58
|
+
room: null,
|
|
59
|
+
set: function(pc, session, room) {
|
|
60
|
+
state.pc = pc;
|
|
61
|
+
state.session = session;
|
|
62
|
+
state.room = room;
|
|
63
|
+
},
|
|
64
|
+
clear: function() {
|
|
65
|
+
state.room = null;
|
|
66
|
+
state.session = null;
|
|
67
|
+
state.pc = null;
|
|
68
|
+
},
|
|
69
|
+
buttonId: function() {
|
|
70
|
+
return state.prefix + "Btn";
|
|
71
|
+
},
|
|
72
|
+
buttonText: function() {
|
|
73
|
+
return (state.prefix.charAt(0).toUpperCase() + state.prefix.slice(1));
|
|
74
|
+
},
|
|
75
|
+
inputId: function() {
|
|
76
|
+
return state.prefix + "Name";
|
|
77
|
+
},
|
|
78
|
+
statusId: function() {
|
|
79
|
+
return state.prefix + "Status";
|
|
80
|
+
},
|
|
81
|
+
formId: function() {
|
|
82
|
+
return state.prefix + "Form";
|
|
83
|
+
},
|
|
84
|
+
errInfoId: function() {
|
|
85
|
+
return state.prefix + "ErrorInfo";
|
|
86
|
+
},
|
|
87
|
+
is: function(value) {
|
|
88
|
+
return (prefix === value);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
return state;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* load config and set default values
|
|
96
|
+
*/
|
|
97
|
+
const init = function() {
|
|
98
|
+
let configName = getUrlParam("config") || "./config.json";
|
|
99
|
+
$("#publishBtn").prop('disabled', true);
|
|
100
|
+
$("#playBtn").prop('disabled', true);
|
|
101
|
+
$("#url").prop('disabled', true);
|
|
102
|
+
$("#roomName").prop('disabled', true);
|
|
103
|
+
$("#publishName").prop('disabled', true);
|
|
104
|
+
$("#playName").prop('disabled', true);
|
|
105
|
+
publishState = CurrentState(PUBLISH);
|
|
106
|
+
playState = CurrentState(PLAY);
|
|
107
|
+
$.getJSON(configName, function(cfg){
|
|
108
|
+
mainConfig = cfg;
|
|
109
|
+
onDisconnected(publishState);
|
|
110
|
+
onDisconnected(playState);
|
|
111
|
+
}).fail(function(e){
|
|
112
|
+
//use default config
|
|
113
|
+
console.error("Error reading configuration file " + configName + ": " + e.status + " " + e.statusText)
|
|
114
|
+
console.log("Default config will be used");
|
|
115
|
+
mainConfig = defaultConfig;
|
|
116
|
+
onDisconnected(publishState);
|
|
117
|
+
onDisconnected(playState);
|
|
118
|
+
});
|
|
119
|
+
$("#url").val(setURL());
|
|
120
|
+
$("#roomName").val("ROOM1-"+createUUID(4));
|
|
121
|
+
$("#publishName").val("Publisher1-"+createUUID(4));
|
|
122
|
+
$("#playName").val("Player1-"+createUUID(4));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* connect to server
|
|
127
|
+
*/
|
|
128
|
+
const connect = function(state) {
|
|
129
|
+
//create peer connection
|
|
130
|
+
pc = new RTCPeerConnection();
|
|
131
|
+
//get config object for room creation
|
|
132
|
+
const roomConfig = getRoomConfig(mainConfig);
|
|
133
|
+
roomConfig.pc = pc;
|
|
134
|
+
roomConfig.url = $("#url").val();
|
|
135
|
+
roomConfig.roomName = $("#roomName").val();
|
|
136
|
+
roomConfig.nickname = $("#" + state.inputId()).val();
|
|
137
|
+
// clean state display items
|
|
138
|
+
setStatus(state.statusId(), "");
|
|
139
|
+
setStatus(state.errInfoId(), "");
|
|
140
|
+
// connect to server and create a room if not
|
|
141
|
+
const session = sfu.createRoom(roomConfig);
|
|
142
|
+
session.on(constants.SFU_EVENT.CONNECTED, function(room) {
|
|
143
|
+
state.set(pc, session, room);
|
|
144
|
+
onConnected(state);
|
|
145
|
+
setStatus(state.statusId(), "ESTABLISHED", "green");
|
|
146
|
+
}).on(constants.SFU_EVENT.DISCONNECTED, function() {
|
|
147
|
+
state.clear();
|
|
148
|
+
onDisconnected(state);
|
|
149
|
+
setStatus(state.statusId(), "DISCONNECTED", "green");
|
|
150
|
+
}).on(constants.SFU_EVENT.FAILED, function(e) {
|
|
151
|
+
state.clear();
|
|
152
|
+
onDisconnected(state);
|
|
153
|
+
setStatus(state.statusId(), "FAILED", "red");
|
|
154
|
+
setStatus(state.errInfoId(), e.status + " " + e.statusText, "red");
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const onConnected = function(state) {
|
|
159
|
+
$("#" + state.buttonId()).text("Stop").off('click').click(function () {
|
|
160
|
+
onStopClick(state);
|
|
161
|
+
});
|
|
162
|
+
$('#url').prop('disabled', true);
|
|
163
|
+
$("#roomName").prop('disabled', true);
|
|
164
|
+
$("#" + state.inputId()).prop('disabled', true);
|
|
165
|
+
// Add errors displaying
|
|
166
|
+
state.room.on(constants.SFU_ROOM_EVENT.FAILED, function(e) {
|
|
167
|
+
setStatus(state.errInfoId(), e, "red");
|
|
168
|
+
}).on(constants.SFU_ROOM_EVENT.OPERATION_FAILED, function (e) {
|
|
169
|
+
setStatus(state.errInfoId(), e.operation + " failed: " + e.error, "red");
|
|
170
|
+
});
|
|
171
|
+
if (state.is(PUBLISH)) {
|
|
172
|
+
publishStreams(state);
|
|
173
|
+
} else if (state.is(PLAY)) {
|
|
174
|
+
playStreams(state);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const onDisconnected = function(state) {
|
|
179
|
+
$("#" + state.buttonId()).text(state.buttonText()).off('click').click(function () {
|
|
180
|
+
onStartClick(state);
|
|
181
|
+
}).prop('disabled', false);
|
|
182
|
+
$("#" + state.inputId()).prop('disabled', false);
|
|
183
|
+
// Check if other session is active
|
|
184
|
+
if ((state.is(PUBLISH) && playState.session)
|
|
185
|
+
|| (state.is(PLAY) && publishState.session)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
$('#url').prop('disabled', false);
|
|
189
|
+
$("#roomName").prop('disabled', false);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const onStartClick = function(state) {
|
|
193
|
+
if (validateForm("connectionForm") && validateForm(state.formId())) {
|
|
194
|
+
$("#" + state.buttonId()).prop('disabled', true);
|
|
195
|
+
if (state.is(PLAY) && Browser().isSafariWebRTC()) {
|
|
196
|
+
playFirstSound(document.getElementById("main"), PRELOADER_URL).then(function () {
|
|
197
|
+
connect(state);
|
|
198
|
+
});
|
|
199
|
+
} else {
|
|
200
|
+
connect(state);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const onStopClick = function(state) {
|
|
206
|
+
$("#" + state.buttonId()).prop('disabled', true);
|
|
207
|
+
if (state.is(PUBLISH)) {
|
|
208
|
+
unPublishStreams(state);
|
|
209
|
+
} else if (state.is(PLAY)) {
|
|
210
|
+
stopStreams(state);
|
|
211
|
+
}
|
|
212
|
+
state.session.disconnect();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const publishStreams = async function(state) {
|
|
216
|
+
let timerId;
|
|
217
|
+
//create local display item to show local streams
|
|
218
|
+
localDisplay = initLocalDisplay(document.getElementById("localVideo"));
|
|
219
|
+
try {
|
|
220
|
+
//get configured local video streams
|
|
221
|
+
let streams = await getVideoStreams(mainConfig);
|
|
222
|
+
let audioStreams = await getAudioStreams(mainConfig);
|
|
223
|
+
//combine local video streams with audio streams
|
|
224
|
+
streams.push.apply(streams, audioStreams);
|
|
225
|
+
let config = {};
|
|
226
|
+
//add our local streams to the room (to PeerConnection)
|
|
227
|
+
streams.forEach(function (s) {
|
|
228
|
+
//add local stream to local display
|
|
229
|
+
localDisplay.add(s.stream.id, $("#" + state.inputId()).val(), s.stream);
|
|
230
|
+
//add each track to PeerConnection
|
|
231
|
+
s.stream.getTracks().forEach((track) => {
|
|
232
|
+
if (s.source === "screen") {
|
|
233
|
+
config[track.id] = s.source;
|
|
234
|
+
}
|
|
235
|
+
addTrackToPeerConnection(state.pc, s.stream, track, s.encodings);
|
|
236
|
+
subscribeTrackToEndedEvent(state.room, track, state.pc);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
state.room.join(config);
|
|
240
|
+
// TODO: Use room state or promises to detect if publishing started to enable stop button
|
|
241
|
+
timerId = waitFor(document.getElementById("localVideo"), 3000, state);
|
|
242
|
+
} catch(e) {
|
|
243
|
+
console.error("Failed to capture streams: " + e);
|
|
244
|
+
setStatus(state.errInfoId(), e.name, "red");
|
|
245
|
+
if (timerId) {
|
|
246
|
+
clearTimeout(timerId);
|
|
247
|
+
timerId = null;
|
|
248
|
+
}
|
|
249
|
+
onStopClick(state);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// A workaround to check if publishing or playback is started
|
|
254
|
+
const waitFor = function (div, timeout, state) {
|
|
255
|
+
let timerId = setTimeout(function () {
|
|
256
|
+
if (div.innerHTML !== "") {
|
|
257
|
+
// Enable stop button
|
|
258
|
+
$("#" + state.buttonId()).prop('disabled', false);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
setStatus(state.errInfoId(), "Something went wrong, stopping", "red");
|
|
262
|
+
onStopClick(state);
|
|
263
|
+
}
|
|
264
|
+
}, timeout);
|
|
265
|
+
return timerId;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const unPublishStreams = function(state) {
|
|
269
|
+
if (localDisplay) {
|
|
270
|
+
localDisplay.stop();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const playStreams = function(state) {
|
|
275
|
+
//create remote display item to show remote streams
|
|
276
|
+
remoteDisplay = initRemoteDisplay(document.getElementById("remoteVideo"), state.room, state.pc);
|
|
277
|
+
state.room.join();
|
|
278
|
+
$("#" + state.buttonId()).prop('disabled', false);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const stopStreams = function(state) {
|
|
282
|
+
if (remoteDisplay) {
|
|
283
|
+
remoteDisplay.stop();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const subscribeTrackToEndedEvent = function(room, track, pc) {
|
|
288
|
+
track.addEventListener("ended", function() {
|
|
289
|
+
//track ended, see if we need to cleanup
|
|
290
|
+
let negotiate = false;
|
|
291
|
+
for (const sender of pc.getSenders()) {
|
|
292
|
+
if (sender.track === track) {
|
|
293
|
+
pc.removeTrack(sender);
|
|
294
|
+
//track found, set renegotiation flag
|
|
295
|
+
negotiate = true;
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (negotiate) {
|
|
300
|
+
//kickoff renegotiation
|
|
301
|
+
room.updateState();
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const addTrackToPeerConnection = function(pc, stream, track, encodings) {
|
|
307
|
+
pc.addTransceiver(track, {
|
|
308
|
+
direction: "sendonly",
|
|
309
|
+
streams: [stream],
|
|
310
|
+
sendEncodings: encodings ? encodings : [] //passing encoding types for video simulcast tracks
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const setStatus = function (status, text, color) {
|
|
315
|
+
const field = document.getElementById(status);
|
|
316
|
+
if (color) {
|
|
317
|
+
field.style.color = color;
|
|
318
|
+
}
|
|
319
|
+
field.innerText = text;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const validateForm = function (formId) {
|
|
323
|
+
var valid = true;
|
|
324
|
+
$('#' + formId + ' :text').each(function () {
|
|
325
|
+
if (!$(this).val()) {
|
|
326
|
+
highlightInput($(this));
|
|
327
|
+
valid = false;
|
|
328
|
+
} else {
|
|
329
|
+
removeHighlight($(this));
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
return valid;
|
|
333
|
+
|
|
334
|
+
function highlightInput(input) {
|
|
335
|
+
input.closest('.input-group').addClass("has-error");
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function removeHighlight(input) {
|
|
339
|
+
input.closest('.input-group').removeClass("has-error");
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const buttonText = function (string) {
|
|
344
|
+
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
345
|
+
}
|
|
346
|
+
|
package/src/sdk/constants.js
CHANGED
|
@@ -56,6 +56,14 @@ const constants = Object.freeze({
|
|
|
56
56
|
*/
|
|
57
57
|
USER_LIST: "USER_LIST",
|
|
58
58
|
|
|
59
|
+
//TODO(naz): documentation
|
|
60
|
+
USER_CHATS: "USER_CHATS",
|
|
61
|
+
CHAT_LOADED: "CHAT_LOADED",
|
|
62
|
+
NEW_CHAT: "NEW_CHAT",
|
|
63
|
+
CHAT_DELETED: "CHAT_DELETED",
|
|
64
|
+
CHAT_UPDATED: "CHAT_UPDATED",
|
|
65
|
+
MESSAGE_STATE: "MESSAGE_STATE",
|
|
66
|
+
|
|
59
67
|
/**
|
|
60
68
|
* @typedef {Object} UserCalendar
|
|
61
69
|
* @property events {UserCalendarEvents} object with events
|
|
@@ -400,6 +408,11 @@ const constants = Object.freeze({
|
|
|
400
408
|
MESSAGE_STATE: "SFU_MESSAGE_STATE",
|
|
401
409
|
USER_LIST: "SFU_USER_LIST",
|
|
402
410
|
USER_CALENDAR: "SFU_USER_CALENDAR",
|
|
411
|
+
USER_CHATS: "SFU_USER_CHATS",
|
|
412
|
+
CHAT_LOADED: "SFU_CHAT_LOADED",
|
|
413
|
+
NEW_CHAT: "SFU_NEW_CHAT",
|
|
414
|
+
CHAT_DELETED: "SFU_CHAT_DELETED",
|
|
415
|
+
CHAT_UPDATED: "SFU_UPDATE_CHAT",
|
|
403
416
|
GET_USER_LIST: "getUserList",
|
|
404
417
|
GET_USER_CALENDAR: "getUserCalendar",
|
|
405
418
|
ADD_CALENDAR_EVENT: "addCalendarEvent",
|
|
@@ -411,7 +424,14 @@ const constants = Object.freeze({
|
|
|
411
424
|
UNSUBSCRIBE_FROM_WAITING_PARTICIPANT: "unsubscribeFromWaitingParticipant",
|
|
412
425
|
MOVE_TO_WAITING_ROOM: "moveToWaitingRoom",
|
|
413
426
|
CONFIGURE_WAITING_ROOM: "configureWaitingRoom",
|
|
414
|
-
TRACK_CONTENT_HEADER: "a=content:"
|
|
427
|
+
TRACK_CONTENT_HEADER: "a=content:",
|
|
428
|
+
GET_USER_CHATS: "getUserChats",
|
|
429
|
+
LOAD_CHAT: "loadChat",
|
|
430
|
+
CREATE_CHAT: "createChat",
|
|
431
|
+
DELETE_CHAT: "deleteChat",
|
|
432
|
+
RENAME_CHAT: "renameChat",
|
|
433
|
+
ADD_MEMBER_TO_CHAT: "addMemberToChat",
|
|
434
|
+
REMOVE_MEMBER_FROM_CHAT: "removeMemberFromChat"
|
|
415
435
|
}),
|
|
416
436
|
/**
|
|
417
437
|
* @namespace FlashphonerSFUExtended.SFU_OPERATIONS
|
|
@@ -430,7 +450,15 @@ const constants = Object.freeze({
|
|
|
430
450
|
ASSIGN_ROLE: "ASSIGN_ROLE",
|
|
431
451
|
SUBSCRIBE_TO_WAITING_PARTICIPANT: "SUBSCRIBE_TO_WAITING_PARTICIPANT",
|
|
432
452
|
UNSUBSCRIBE_FROM_WAITING_PARTICIPANT: "UNSUBSCRIBE_FROM_WAITING_PARTICIPANT",
|
|
433
|
-
MOVE_TO_WAITING_ROOM: "MOVE_TO_WAITING_ROOM"
|
|
453
|
+
MOVE_TO_WAITING_ROOM: "MOVE_TO_WAITING_ROOM",
|
|
454
|
+
CREATE_CHAT: "CREATE_CHAT",
|
|
455
|
+
DELETE_CHAT: "DELETE_CHAT",
|
|
456
|
+
RENAME_CHAT: "RENAME_CHAT",
|
|
457
|
+
LOAD_CHAT: "LOAD_CHAT",
|
|
458
|
+
ADD_MEMBER_TO_CHAT: "ADD_MEMBER_TO_CHAT",
|
|
459
|
+
REMOVE_MEMBER_FROM_CHAT: "REMOVE_MEMBER_FROM_CHAT",
|
|
460
|
+
UPDATE_CHAT_PREFERENCES: "UPDATE_CHAT_PREFERENCES",
|
|
461
|
+
GET_USER_CHATS: "GET_USER_CHATS"
|
|
434
462
|
}),
|
|
435
463
|
/**
|
|
436
464
|
* @namespace FlashphonerSFU.SFU_PARTICIPANT_ROLE
|
package/src/sdk/messaging.js
CHANGED
|
@@ -6,20 +6,31 @@ const create = function(options) {
|
|
|
6
6
|
|
|
7
7
|
/*
|
|
8
8
|
* @param {String} msg.to Recipient's id
|
|
9
|
+
* @param {String} msg.chatId Indicates chat this message belongs to
|
|
9
10
|
* @param {String} msg.body Message body
|
|
10
11
|
*/
|
|
11
12
|
const sendMessage = function(msg) {
|
|
12
13
|
return new Promise(function(resolve, reject) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
//validate
|
|
15
|
+
if (!msg) {
|
|
16
|
+
reject(new Error("Can't send null message"));
|
|
17
|
+
} else if (!msg.body || msg.body === "") {
|
|
18
|
+
reject(new Error("Can't send message without a body"));
|
|
19
|
+
} else if (!msg.chatId || msg.chatId === "") {
|
|
20
|
+
reject(new Error("Can't send message without a chatId"));
|
|
21
|
+
} else {
|
|
22
|
+
const message = {
|
|
23
|
+
id: uuidv4(),
|
|
24
|
+
to: msg.to,
|
|
25
|
+
body: msg.body,
|
|
26
|
+
chatId: msg.chatId
|
|
27
|
+
};
|
|
28
|
+
connection.send("sendMessage", message);
|
|
29
|
+
pendingMessages[message.id] = {
|
|
30
|
+
resolve: resolve,
|
|
31
|
+
reject: reject
|
|
32
|
+
};
|
|
33
|
+
}
|
|
23
34
|
});
|
|
24
35
|
};
|
|
25
36
|
|
|
@@ -28,7 +39,7 @@ const create = function(options) {
|
|
|
28
39
|
if (promise) {
|
|
29
40
|
delete pendingMessages[msg[0].status.id];
|
|
30
41
|
if (msg[0].status.delivered) {
|
|
31
|
-
promise.resolve();
|
|
42
|
+
promise.resolve(msg[0].status);
|
|
32
43
|
} else {
|
|
33
44
|
promise.reject();
|
|
34
45
|
}
|
package/src/sdk/promise.js
CHANGED
|
@@ -8,11 +8,21 @@ function add(id, resolve, reject) {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
function resolve(id, args) {
|
|
11
|
-
getAndRemovePromise(id)
|
|
11
|
+
const promise = getAndRemovePromise(id);
|
|
12
|
+
if (!promise) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
promise.resolve(args);
|
|
16
|
+
return true;
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
function reject(id, args) {
|
|
15
|
-
getAndRemovePromise(id)
|
|
20
|
+
const promise = getAndRemovePromise(id);
|
|
21
|
+
if (!promise) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
promise.reject(args);
|
|
25
|
+
return true;
|
|
16
26
|
}
|
|
17
27
|
|
|
18
28
|
function promised(id) {
|
|
@@ -22,7 +32,7 @@ function promised(id) {
|
|
|
22
32
|
function getAndRemovePromise(id) {
|
|
23
33
|
const promise = promises[id];
|
|
24
34
|
if (!promise) {
|
|
25
|
-
|
|
35
|
+
return;
|
|
26
36
|
}
|
|
27
37
|
delete promises[id];
|
|
28
38
|
return promise;
|