@wazo/sdk 0.38.7 → 0.38.8

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.
Files changed (106) hide show
  1. package/dist/wazo-sdk.js +2 -2
  2. package/esm/__tests__/api-client.test.js +142 -2
  3. package/esm/__tests__/web-rtc-client.test.js +227 -27
  4. package/esm/api/calld.js +8 -0
  5. package/esm/api/confd.js +134 -2
  6. package/esm/api-client.js +142 -2
  7. package/esm/checker/Checker.js +183 -24
  8. package/esm/checker/checks/aor.js +142 -2
  9. package/esm/checker/checks/api.js +142 -2
  10. package/esm/checker/checks/index.js +183 -24
  11. package/esm/checker/checks/wazo-websocket.js +2 -0
  12. package/esm/checker/checks/webrtc-transport.js +181 -24
  13. package/esm/checker/checks/webrtc.js +181 -24
  14. package/esm/domain/AdHocAPIConference.js +142 -2
  15. package/esm/domain/Features.js +142 -2
  16. package/esm/domain/Meeting.js +18 -0
  17. package/esm/domain/MeetingAuthorization.js +70 -0
  18. package/esm/domain/Phone/CTIPhone.js +142 -2
  19. package/esm/domain/__tests__/Meeting.test.js +87 -1
  20. package/esm/domain/__tests__/MeetingAuthorization.test.js +109 -0
  21. package/esm/index.js +226 -27
  22. package/esm/service/CallApi.js +142 -2
  23. package/esm/service/getApiClient.js +142 -2
  24. package/esm/simple/Auth.js +226 -27
  25. package/esm/simple/Configuration.js +226 -27
  26. package/esm/simple/Directory.js +142 -2
  27. package/esm/simple/Phone.js +226 -27
  28. package/esm/simple/Websocket.js +3 -0
  29. package/esm/simple/index.js +226 -27
  30. package/esm/simple/room/LocalParticipant.js +226 -27
  31. package/esm/simple/room/Participant.js +226 -27
  32. package/esm/simple/room/RemoteParticipant.js +226 -27
  33. package/esm/simple/room/Room.js +226 -27
  34. package/esm/simple/room/SipRoom.js +226 -27
  35. package/esm/simple/room/Stream.js +226 -27
  36. package/esm/simple/room/__tests__/Participant.test.js +14747 -0
  37. package/esm/simple/room/__tests__/RemoteParticipant.test.js +226 -27
  38. package/esm/simple/utils.js +226 -27
  39. package/esm/utils/__tests__/object.test.js +57 -0
  40. package/esm/utils/__tests__/string.test.js +30 -0
  41. package/esm/utils/object.js +24 -0
  42. package/esm/utils/string.js +10 -0
  43. package/esm/web-rtc-client.js +181 -24
  44. package/esm/websocket-client.js +3 -1
  45. package/lib/__tests__/api-client.test.js +142 -2
  46. package/lib/__tests__/web-rtc-client.test.js +227 -27
  47. package/lib/api/calld.js +8 -0
  48. package/lib/api/confd.js +134 -2
  49. package/lib/api-client.js +142 -2
  50. package/lib/checker/Checker.js +183 -24
  51. package/lib/checker/checks/aor.js +142 -2
  52. package/lib/checker/checks/api.js +142 -2
  53. package/lib/checker/checks/index.js +183 -24
  54. package/lib/checker/checks/wazo-websocket.js +2 -0
  55. package/lib/checker/checks/webrtc-transport.js +181 -24
  56. package/lib/checker/checks/webrtc.js +181 -24
  57. package/lib/domain/AdHocAPIConference.js +142 -2
  58. package/lib/domain/Features.js +142 -2
  59. package/lib/domain/Meeting.js +18 -0
  60. package/lib/domain/MeetingAuthorization.js +79 -0
  61. package/lib/domain/Phone/CTIPhone.js +142 -2
  62. package/lib/domain/__tests__/Meeting.test.js +87 -1
  63. package/lib/domain/__tests__/MeetingAuthorization.test.js +111 -0
  64. package/lib/index.js +226 -27
  65. package/lib/service/CallApi.js +142 -2
  66. package/lib/service/getApiClient.js +142 -2
  67. package/lib/simple/Auth.js +226 -27
  68. package/lib/simple/Configuration.js +226 -27
  69. package/lib/simple/Directory.js +142 -2
  70. package/lib/simple/Phone.js +226 -27
  71. package/lib/simple/Websocket.js +3 -0
  72. package/lib/simple/index.js +226 -27
  73. package/lib/simple/room/LocalParticipant.js +226 -27
  74. package/lib/simple/room/Participant.js +226 -27
  75. package/lib/simple/room/RemoteParticipant.js +226 -27
  76. package/lib/simple/room/Room.js +226 -27
  77. package/lib/simple/room/SipRoom.js +226 -27
  78. package/lib/simple/room/Stream.js +226 -27
  79. package/lib/simple/room/__tests__/Participant.test.js +14757 -0
  80. package/lib/simple/room/__tests__/RemoteParticipant.test.js +226 -27
  81. package/lib/simple/utils.js +226 -27
  82. package/lib/utils/__tests__/object.test.js +59 -0
  83. package/lib/utils/__tests__/string.test.js +32 -0
  84. package/lib/utils/object.js +28 -0
  85. package/lib/utils/string.js +14 -0
  86. package/lib/web-rtc-client.js +181 -24
  87. package/lib/websocket-client.js +3 -0
  88. package/package.json +2 -2
  89. package/src/__tests__/web-rtc-client.test.js +46 -3
  90. package/src/api/calld.js +8 -0
  91. package/src/api/confd.js +43 -2
  92. package/src/domain/Meeting.js +20 -0
  93. package/src/domain/MeetingAuthorization.js +67 -0
  94. package/src/domain/__tests__/Meeting.test.js +70 -1
  95. package/src/domain/__tests__/MeetingAuthorization.test.js +58 -0
  96. package/src/simple/room/Participant.js +40 -0
  97. package/src/simple/room/Room.js +2 -2
  98. package/src/simple/room/SipRoom.js +1 -1
  99. package/src/simple/room/__tests__/Participant.test.js +81 -0
  100. package/src/types/WebSocketMessage.js +7 -1
  101. package/src/utils/__tests__/object.test.js +35 -0
  102. package/src/utils/__tests__/string.test.js +23 -0
  103. package/src/utils/object.js +15 -0
  104. package/src/utils/string.js +8 -0
  105. package/src/web-rtc-client.js +39 -22
  106. package/src/websocket-client.js +2 -0
@@ -2681,6 +2681,70 @@ class ExternalApp {
2681
2681
 
2682
2682
  //
2683
2683
 
2684
+ class MeetingAuthorization {
2685
+
2686
+
2687
+
2688
+
2689
+
2690
+
2691
+ constructor({
2692
+ meetingUuid,
2693
+ uuid,
2694
+ userUuid,
2695
+ userName,
2696
+ } = {}) {
2697
+ this.meetingUuid = meetingUuid;
2698
+ this.uuid = uuid;
2699
+ this.userUuid = userUuid;
2700
+ this.userName = userName;
2701
+ }
2702
+
2703
+ setStatus(status ) {
2704
+ this.status = status;
2705
+ }
2706
+
2707
+ getStatus() {
2708
+ return this.status;
2709
+ }
2710
+
2711
+ static parse(plain ) {
2712
+ const {
2713
+ meeting_uuid: meetingUuid,
2714
+ uuid,
2715
+ guest_uuid: userUuid,
2716
+ guest_name: userName,
2717
+ } = plain;
2718
+
2719
+ return new MeetingAuthorization({
2720
+ meetingUuid,
2721
+ uuid,
2722
+ userUuid,
2723
+ userName,
2724
+ });
2725
+ }
2726
+
2727
+ static parseMany(items ) {
2728
+ if (!items) {
2729
+ return [];
2730
+ }
2731
+ return items.map(MeetingAuthorization.parse);
2732
+ }
2733
+ }
2734
+
2735
+ //
2736
+
2737
+
2738
+
2739
+
2740
+
2741
+
2742
+
2743
+
2744
+
2745
+
2746
+
2747
+
2684
2748
 
2685
2749
 
2686
2750
 
@@ -2691,6 +2755,7 @@ class ExternalApp {
2691
2755
 
2692
2756
 
2693
2757
 
2758
+
2694
2759
 
2695
2760
 
2696
2761
  class Meeting {
@@ -2705,6 +2770,8 @@ class Meeting {
2705
2770
 
2706
2771
 
2707
2772
 
2773
+
2774
+
2708
2775
 
2709
2776
  static parse(plain ) {
2710
2777
  return new Meeting({
@@ -2717,6 +2784,7 @@ class Meeting {
2717
2784
  extension: plain.exten,
2718
2785
  persistent: plain.persistent,
2719
2786
  creationTime: moment__default['default'](plain.creation_time).toDate(),
2787
+ requireAuthorization: plain.require_authorization,
2720
2788
  });
2721
2789
  }
2722
2790
 
@@ -2741,6 +2809,7 @@ class Meeting {
2741
2809
  extension,
2742
2810
  persistent,
2743
2811
  creationTime,
2812
+ requireAuthorization,
2744
2813
  } = {}) {
2745
2814
  this.guestSipAuthorization = guestSipAuthorization;
2746
2815
  this.uri = uri;
@@ -2751,6 +2820,7 @@ class Meeting {
2751
2820
  this.extension = extension;
2752
2821
  this.persistent = persistent;
2753
2822
  this.creationTime = creationTime;
2823
+ this.requireAuthorization = requireAuthorization;
2754
2824
 
2755
2825
  // Useful to compare instead of instanceof with minified code
2756
2826
  this.type = 'Meeting';
@@ -2761,8 +2831,32 @@ class Meeting {
2761
2831
  const [username, secret] = atob(this.guestSipAuthorization).split(':');
2762
2832
  return { username, secret };
2763
2833
  }
2834
+
2764
2835
  }
2765
2836
 
2837
+ //
2838
+
2839
+ const camelToUnderscore = (key ) => {
2840
+ if (typeof key !== 'string') {
2841
+ throw new Error('Input is not a string');
2842
+ }
2843
+ return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
2844
+ };
2845
+
2846
+ //
2847
+
2848
+ const convertKeysFromCamelToUnderscore = (args ) => {
2849
+ if (!args || typeof args !== 'object' || Array.isArray(args)) {
2850
+ throw new Error('Input is not an object');
2851
+ }
2852
+
2853
+ return Object.keys(args).reduce((acc, key) => {
2854
+ acc[camelToUnderscore(key)] = typeof args[key] === 'object' && !Array.isArray(args[key])
2855
+ ? convertKeysFromCamelToUnderscore(args[key]) : args[key];
2856
+ return acc;
2857
+ }, {});
2858
+ };
2859
+
2766
2860
  /* */
2767
2861
 
2768
2862
  var confdMethods = (client , baseUrl ) => ({
@@ -2831,8 +2925,18 @@ var confdMethods = (client , baseUrl ) => ({
2831
2925
  getMyMeetings: () =>
2832
2926
  client.get(`${baseUrl}/users/me/meetings`).then(response => Meeting.parseMany(response.items)),
2833
2927
 
2834
- createMyMeeting: (name , persistent ) =>
2835
- client.post(`${baseUrl}/users/me/meetings`, { name, persistent }).then(Meeting.parse),
2928
+ createMyMeeting: (args ) =>
2929
+ client
2930
+ .post(`${baseUrl}/users/me/meetings`, convertKeysFromCamelToUnderscore(args))
2931
+ .then(Meeting.parse),
2932
+
2933
+ updateMyMeeting: (meetingUuid , data ) =>
2934
+ client.put(
2935
+ `${baseUrl}/users/me/meetings/${meetingUuid}`,
2936
+ convertKeysFromCamelToUnderscore(data),
2937
+ null,
2938
+ ApiRequester.successResponseParser,
2939
+ ),
2836
2940
 
2837
2941
  deleteMyMeeting: (meetingUuid ) =>
2838
2942
  client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
@@ -2840,8 +2944,36 @@ var confdMethods = (client , baseUrl ) => ({
2840
2944
  getMeeting: (meetingUuid ) =>
2841
2945
  client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2842
2946
 
2947
+ meetingAuthorizations: (meetingUuid ) =>
2948
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations`, null).then(MeetingAuthorization.parseMany),
2949
+
2950
+ meetingAuthorizationReject: (meetingUuid , authorizationUuid ) =>
2951
+ client.put(
2952
+ `${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/reject`,
2953
+ {},
2954
+ null,
2955
+ ApiRequester.successResponseParser,
2956
+ ),
2957
+
2958
+ meetingAuthorizationAccept: (meetingUuid , authorizationUuid ) =>
2959
+ client.put(
2960
+ `${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/accept`,
2961
+ {},
2962
+ null,
2963
+ ApiRequester.successResponseParser,
2964
+ ),
2965
+
2843
2966
  guestGetMeeting: (meetingUuid ) =>
2844
2967
  client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2968
+
2969
+ guestAuthorizationRequest: (userUuid , meetingUuid , username ) =>
2970
+ client
2971
+ .post(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations`, { guest_name: username })
2972
+ .then(MeetingAuthorization.parse),
2973
+
2974
+ guestAuthorizationCheck: (userUuid , meetingUuid , authorizationUuid ) =>
2975
+ client.get(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations/${authorizationUuid}`, null),
2976
+
2845
2977
  });
2846
2978
 
2847
2979
  //
@@ -5066,6 +5198,14 @@ var calldMethods = (client , baseUrl ) => ({
5066
5198
  getMeetingParticipantsAsUser: async (meetingUuid ) =>
5067
5199
  client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
5068
5200
 
5201
+ banMeetingParticipant: (meetingUuid , participantUuid ) =>
5202
+ client.delete(
5203
+ `${baseUrl}/users/me/meetings/${meetingUuid}/participants/${participantUuid}`,
5204
+ null,
5205
+ null,
5206
+ ApiRequester.successResponseParser,
5207
+ ),
5208
+
5069
5209
  listTrunks: () => client.get(`${baseUrl}/trunks`),
5070
5210
 
5071
5211
  mute: (callId ) =>
@@ -7824,7 +7964,7 @@ class WebRTCClient extends Emitter {
7824
7964
  });
7825
7965
  }
7826
7966
 
7827
- changeAudioInputDevice(id , session , force ) {
7967
+ async changeAudioInputDevice(id , session , force ) {
7828
7968
  const currentId = this.getAudioDeviceId();
7829
7969
  logger$8.info('setting audio input device', { id, currentId, session: !!session });
7830
7970
 
@@ -7832,33 +7972,50 @@ class WebRTCClient extends Emitter {
7832
7972
  return null;
7833
7973
  }
7834
7974
 
7975
+ // in order to handle an audio track change for default devices
7976
+ // we need the actual id of the device (not 'default')
7977
+ let deviceId = id;
7978
+ if (id === 'default' && navigator.mediaDevices) {
7979
+ const devices = await navigator.mediaDevices.enumerateDevices();
7980
+ const defaultDevice = devices.find(device => device.deviceId === 'default');
7981
+ if (defaultDevice) {
7982
+ const deviceLabel = defaultDevice.label.replace('Default - ', '');
7983
+ const targetDevice = devices.find(device => device.label === deviceLabel);
7984
+ if (targetDevice) {
7985
+ deviceId = targetDevice.deviceId;
7986
+ if (!force && deviceId === currentId) {
7987
+ return null;
7988
+ }
7989
+ }
7990
+ }
7991
+ }
7992
+
7835
7993
  // let's update the local audio value
7836
7994
  if (this.audio) {
7837
7995
  this.audio = {
7838
7996
  deviceId: {
7839
- exact: id,
7997
+ exact: deviceId,
7840
7998
  },
7841
7999
  };
7842
8000
  }
7843
8001
 
7844
- if (session) {
8002
+ if (session && navigator.mediaDevices) {
7845
8003
  const sdh = session.sessionDescriptionHandler;
7846
8004
  const pc = sdh.peerConnection;
7847
8005
 
7848
- // $FlowFixMe
7849
- return navigator.mediaDevices.getUserMedia({ audio: { deviceId: { exact: id } } }).then(async stream => {
7850
- const audioTrack = stream.getAudioTracks()[0];
7851
- const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
8006
+ const constraints = { audio: { deviceId: { exact: deviceId } } };
8007
+ const stream = await navigator.mediaDevices.getUserMedia(constraints);
8008
+ const audioTrack = stream.getAudioTracks()[0];
8009
+ const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
7852
8010
 
7853
- if (sender) {
7854
- if (sender.track) {
7855
- audioTrack.enabled = sender.track.enabled;
7856
- }
7857
- sender.replaceTrack(audioTrack);
8011
+ if (sender) {
8012
+ if (sender.track) {
8013
+ audioTrack.enabled = sender.track.enabled;
7858
8014
  }
8015
+ sender.replaceTrack(audioTrack);
8016
+ }
7859
8017
 
7860
- return stream;
7861
- });
8018
+ return stream;
7862
8019
  }
7863
8020
  }
7864
8021
 
@@ -7878,14 +8035,14 @@ class WebRTCClient extends Emitter {
7878
8035
  return null;
7879
8036
  }
7880
8037
 
7881
- // let's update the local video value
7882
- if (this.video) {
7883
- this.video = {
7884
- deviceId: {
7885
- exact: id,
7886
- },
7887
- };
7888
- }
8038
+ // let's make sure we don't lose other video constraints settings -- width, height, frameRate...
8039
+ const videoObject = typeof this.video === 'object' ? this.video : {};
8040
+ this.video = {
8041
+ ...videoObject,
8042
+ deviceId: {
8043
+ exact: id,
8044
+ },
8045
+ };
7889
8046
  }
7890
8047
 
7891
8048
  changeSessionVideoInputDevice(id , session ) {
@@ -11280,6 +11437,7 @@ const AGENT_UNPAUSED = 'agent_unpaused';
11280
11437
  const CONFERENCE_ADHOC_PARTICIPANT_LEFT = 'conference_adhoc_participant_left';
11281
11438
  const CONFERENCE_ADHOC_DELETED = 'conference_adhoc_deleted';
11282
11439
  const MEETING_USER_PROGRESS = 'meeting_user_progress';
11440
+ const MEETING_USER_GUEST_AUTHORIZATION_CREATED = 'meeting_user_guest_authorization_created';
11283
11441
 
11284
11442
  const BLACKLIST_EVENTS = [
11285
11443
  CHAT_MESSAGE_SENT,
@@ -11631,6 +11789,7 @@ WebSocketClient.eventLists = [
11631
11789
  CONFERENCE_ADHOC_PARTICIPANT_LEFT,
11632
11790
  CONFERENCE_ADHOC_DELETED,
11633
11791
  MEETING_USER_PROGRESS,
11792
+ MEETING_USER_GUEST_AUTHORIZATION_CREATED,
11634
11793
  ];
11635
11794
 
11636
11795
  var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
@@ -11702,6 +11861,7 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
11702
11861
  CONFERENCE_ADHOC_PARTICIPANT_LEFT: CONFERENCE_ADHOC_PARTICIPANT_LEFT,
11703
11862
  CONFERENCE_ADHOC_DELETED: CONFERENCE_ADHOC_DELETED,
11704
11863
  MEETING_USER_PROGRESS: MEETING_USER_PROGRESS,
11864
+ MEETING_USER_GUEST_AUTHORIZATION_CREATED: MEETING_USER_GUEST_AUTHORIZATION_CREATED,
11705
11865
  HEARTBEAT_ENGINE_VERSION: HEARTBEAT_ENGINE_VERSION,
11706
11866
  'default': WebSocketClient
11707
11867
  });
@@ -11799,7 +11959,7 @@ class SipRoom extends Room {
11799
11959
  logger$3.info('connecting to sip room', { extension, audioOnly, room: !!room });
11800
11960
 
11801
11961
  if (!room) {
11802
- await Wazo.Phone.connect();
11962
+ await Wazo.Phone.connect({ media: constraints });
11803
11963
 
11804
11964
  const withCamera = constraints && !!constraints.video;
11805
11965
 
@@ -13481,7 +13641,7 @@ class Room extends Emitter {
13481
13641
  logger$1.info('connecting to room', { extension, audioOnly, room: !!room });
13482
13642
 
13483
13643
  if (!room) {
13484
- await Wazo.Phone.connect();
13644
+ await Wazo.Phone.connect({ media: constraints });
13485
13645
 
13486
13646
  const withCamera = constraints && !!constraints.video;
13487
13647
 
@@ -13926,7 +14086,7 @@ class Room extends Emitter {
13926
14086
  const participant = this._getParticipantFromCallId(status.callId);
13927
14087
 
13928
14088
  if (participant) {
13929
- // we're received, so no need to broadcast, hence the input false arg
14089
+ // we're receiving, so no need to broadcast
13930
14090
  participant.updateStatus(status, false);
13931
14091
  }
13932
14092
  break;
@@ -14200,6 +14360,7 @@ class Participant extends Emitter {
14200
14360
 
14201
14361
 
14202
14362
 
14363
+
14203
14364
 
14204
14365
 
14205
14366
 
@@ -14217,6 +14378,7 @@ class Participant extends Emitter {
14217
14378
 
14218
14379
 
14219
14380
 
14381
+
14220
14382
 
14221
14383
  /**
14222
14384
  * @param room Room The room where the participant is
@@ -14240,6 +14402,7 @@ class Participant extends Emitter {
14240
14402
  this.screensharing = false;
14241
14403
  this.isOnHold = false;
14242
14404
  this.extra = extra;
14405
+ this.banned = false;
14243
14406
 
14244
14407
  this.ON_UPDATED = 'participant/ON_UPDATED';
14245
14408
  this.ON_START_TALKING = 'participant/ON_START_TALKING';
@@ -14256,6 +14419,7 @@ class Participant extends Emitter {
14256
14419
  this.ON_EXTRA_CHANGE = 'participant/ON_EXTRA_CHANGE';
14257
14420
  this.ON_HOLD = 'participant/ON_HOLD';
14258
14421
  this.ON_RESUME = 'participant/ON_RESUME';
14422
+ this.ON_BAN = 'participant/ON_BAN';
14259
14423
  }
14260
14424
 
14261
14425
  triggerEvent(name , ...args ) {
@@ -14296,6 +14460,10 @@ class Participant extends Emitter {
14296
14460
  status.extra = this.extra;
14297
14461
  break;
14298
14462
  }
14463
+ case this.ON_BAN: {
14464
+ status.banned = true;
14465
+ break;
14466
+ }
14299
14467
  }
14300
14468
 
14301
14469
  if (broadcast) {
@@ -14398,6 +14566,11 @@ class Participant extends Emitter {
14398
14566
  this.triggerUpdate(this.ON_RESUME, broadcast);
14399
14567
  }
14400
14568
 
14569
+ onBan(broadcast = true) {
14570
+ this.banned = true;
14571
+ this.triggerUpdate(this.ON_BAN, broadcast);
14572
+ }
14573
+
14401
14574
  getStatus() {
14402
14575
  return {
14403
14576
  callId: this.callId,
@@ -14444,6 +14617,10 @@ class Participant extends Emitter {
14444
14617
  }
14445
14618
  }
14446
14619
 
14620
+ if (status.banned) {
14621
+ this.onBan(false);
14622
+ }
14623
+
14447
14624
  // Poor man's object comparison
14448
14625
  if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
14449
14626
  this.extra = { ...this.extra, ...status.extra };
@@ -14471,6 +14648,28 @@ class Participant extends Emitter {
14471
14648
  this.streams = streams;
14472
14649
  this.videoStreams = streams;
14473
14650
  }
14651
+
14652
+ async ban(apiRequestDelay = null) {
14653
+ const { meetingUuid } = this.room;
14654
+ if (!meetingUuid) {
14655
+ throw new Error('Attempting to ban a participant without a `meetingUuid`');
14656
+ }
14657
+
14658
+ // this notifies all that someone is being banned
14659
+ this.onBan(true);
14660
+
14661
+ // this allows to delay the actual ban, in order for the banned participant as well as others to react to the situation
14662
+ if (apiRequestDelay) {
14663
+ await this.delay(apiRequestDelay);
14664
+ }
14665
+
14666
+ // proceed with the actual kick
14667
+ return getApiClient().calld.banMeetingParticipant(meetingUuid, this.callId);
14668
+ }
14669
+
14670
+ async delay(ms ) {
14671
+ return new Promise(resolve => setTimeout(resolve, ms));
14672
+ }
14474
14673
  }
14475
14674
 
14476
14675
  //