easyproctor-hml 2.5.17 → 2.5.19

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/esm/index.js CHANGED
@@ -11819,12 +11819,12 @@ var BackendService = class {
11819
11819
  });
11820
11820
  return result.data;
11821
11821
  }
11822
- async verifyFace(proctoringId2, faceImage) {
11822
+ async verifyFace(proctoringId2, faceImage, retry) {
11823
11823
  const result = await this.makeRequestAxios({
11824
11824
  path: `/Realtime/verify-face`,
11825
11825
  method: "POST",
11826
11826
  jwt: this.token,
11827
- body: { "proctoringId": proctoringId2, "base64": faceImage }
11827
+ body: { "proctoringId": proctoringId2, "base64": faceImage, "retry": retry }
11828
11828
  });
11829
11829
  return result.data;
11830
11830
  }
@@ -12700,7 +12700,6 @@ var CameraRecorder = class {
12700
12700
  noiseLimit: 40
12701
12701
  },
12702
12702
  imageBehaviourParameters: {
12703
- frames: 40,
12704
12703
  useUploadImage: true,
12705
12704
  uploadInterval: 20,
12706
12705
  saveVideo: true
@@ -12712,7 +12711,6 @@ var CameraRecorder = class {
12712
12711
  }
12713
12712
  };
12714
12713
  // private imageParams: ImageParameters = {
12715
- // frames: 40,
12716
12714
  // useUploadImage: true,
12717
12715
  // uploadInterval: 20,
12718
12716
  // saveVideo: true
@@ -12804,7 +12802,7 @@ var CameraRecorder = class {
12804
12802
  }
12805
12803
  }
12806
12804
  async startRecording(options) {
12807
- var _a2, _b, _c2, _d, _e3, _f, _g, _h, _i3;
12805
+ var _a2, _b, _c2, _d, _e3, _f, _g, _h;
12808
12806
  if ((((_a2 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _a2.detectPerson) || ((_b = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _b.detectCellPhone) || ((_c2 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _c2.detectFace)) && !(options == null ? void 0 : options.retry)) {
12809
12807
  await this.initializeDetectors();
12810
12808
  }
@@ -12884,7 +12882,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
12884
12882
  this.filesToUpload = [];
12885
12883
  if (this.options.proctoringType == "REALTIME") {
12886
12884
  this.captureFrame();
12887
- this.sendFrameInterval = setInterval(() => this.captureFrame(), 1e3 * ((_i3 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _i3.realtimeUploadInterval));
12888
12885
  }
12889
12886
  this.packageCount = 0;
12890
12887
  }
@@ -12915,7 +12912,8 @@ Setting: ${JSON.stringify(settings, null, 2)}`
12915
12912
  clearInterval(this.imageInterval);
12916
12913
  clearInterval(this.sendFrameInterval);
12917
12914
  if (this.options.proctoringType == "REALTIME" && this.upload && this.backendToken) {
12918
- await this.sendPackage();
12915
+ await this.sendPackage(this.filesToUpload);
12916
+ await this.filesToUpload.splice(0, this.filesToUpload.length);
12919
12917
  }
12920
12918
  this.volumeMeter && this.volumeMeter.stop();
12921
12919
  this.intervalNoiseDetection && clearInterval(this.intervalNoiseDetection);
@@ -12985,23 +12983,29 @@ Setting: ${JSON.stringify(settings, null, 2)}`
12985
12983
  this.canvas.getContext("2d").drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
12986
12984
  return this.canvas.toDataURL("image/jpeg");
12987
12985
  }
12988
- // De um em um segundo captura um frame ligado de 30 em 30 segundos)
12986
+ // captura um frame a cada intervalo de tempo definido no paramsConfig.videoBehaviourParameters?.realtimeCaptureInterval!
12989
12987
  captureFrame() {
12990
- var _a2;
12988
+ var _a2, _b;
12991
12989
  let imageFile;
12992
12990
  this.configImageCapture();
12991
+ let newCanvasWidth = this.videoOptions.width / 2;
12992
+ let newCanvasHeight = this.videoOptions.height / 2;
12993
+ if (newCanvasWidth < 320) newCanvasWidth = 320;
12994
+ if (newCanvasHeight < 180) newCanvasHeight = 180;
12995
+ this.canvas.width = newCanvasWidth;
12996
+ this.canvas.height = newCanvasHeight;
12993
12997
  const packSize = (_a2 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _a2.realtimePackageSize;
12994
- let initSend = false;
12995
- this.imageCount++;
12998
+ this.imageCount = 0;
12996
12999
  this.imageInterval = setInterval(async () => {
13000
+ console.log("capturando frame " + this.imageCount);
12997
13001
  this.canvas.getContext("2d").drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
12998
13002
  const image_data_url = this.canvas.toDataURL("image/jpeg");
12999
13003
  if (this.proctoringId == void 0) return;
13000
- if (initSend == false && packSize == this.imageCount) {
13001
- initSend = true;
13004
+ if (packSize == this.imageCount) {
13002
13005
  this.imageCount = 0;
13003
- clearInterval(this.imageInterval);
13004
- this.sendPackage();
13006
+ const framesToSend = [...this.filesToUpload];
13007
+ this.sendPackage(framesToSend);
13008
+ await this.filesToUpload.splice(0, this.filesToUpload.length);
13005
13009
  }
13006
13010
  let imageName = `${this.proctoringId}_${this.imageCount + 1}.jpg`;
13007
13011
  imageFile = await this.getFile(image_data_url, imageName, "image/jpeg");
@@ -13009,22 +13013,24 @@ Setting: ${JSON.stringify(settings, null, 2)}`
13009
13013
  this.filesToUpload.push(imageFile);
13010
13014
  this.imageCount++;
13011
13015
  }
13012
- }, 1e3);
13016
+ }, ((_b = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _b.realtimeCaptureInterval) * 1e3);
13013
13017
  }
13014
13018
  // envia pacote de imagens
13015
- async sendPackage() {
13019
+ async sendPackage(framesToSend) {
13020
+ var _a2, _b;
13016
13021
  let pending = false;
13017
13022
  let undeliveredPackagesCount = 0;
13023
+ const packSize = (_a2 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _a2.realtimePackageSize;
13024
+ const packCaptureInterval = ((_b = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _b.realtimeCaptureInterval) + 1;
13018
13025
  if (this.upload && this.backendToken && !pending && this.filesToUpload.length > 0) {
13019
13026
  undeliveredPackagesCount = 0;
13020
13027
  pending = true;
13021
13028
  const zip = new import_jszip_min.default();
13022
- const files = this.filesToUpload;
13023
- for (const file of files) {
13029
+ for (const file of framesToSend) {
13024
13030
  zip.file(file.name, file);
13025
13031
  }
13026
13032
  const blob = await zip.generateAsync({ type: "blob" });
13027
- let packageName = "realtime_package_" + 30 * this.packageCount + ".zip";
13033
+ let packageName = "realtime_package_" + packSize * packCaptureInterval * this.packageCount + ".zip";
13028
13034
  const myPackage = new File(
13029
13035
  [blob],
13030
13036
  packageName,
@@ -13037,7 +13043,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
13037
13043
  this.backendToken
13038
13044
  );
13039
13045
  if (uploadResult.uploaded == true) {
13040
- await this.filesToUpload.splice(0, this.filesToUpload.length);
13041
13046
  this.packageCount++;
13042
13047
  } else {
13043
13048
  console.log("erro no upload do pacote");
@@ -15200,9 +15205,15 @@ var AlertRecorder = class {
15200
15205
  // HANDLERS (Funções Arrow para preservar o 'this')
15201
15206
  // ==========================================
15202
15207
  // 1. LOST / RETURN FOCUS
15208
+ this.handleVisibilityChange = () => {
15209
+ if (document.visibilityState === "visible") {
15210
+ this.handleReturnFocus();
15211
+ } else {
15212
+ this.handleLostFocus();
15213
+ }
15214
+ };
15203
15215
  this.handleLostFocus = () => {
15204
15216
  if (this.getRelativeTime() > 1e4) {
15205
- this.createAlert(25 /* FocusOff */, 3 /* Screen */, "Usu\xE1rio mudou de aba ou minimizou");
15206
15217
  const alertPayload = {
15207
15218
  begin: this.getRelativeTime(),
15208
15219
  end: 0,
@@ -15233,7 +15244,7 @@ var AlertRecorder = class {
15233
15244
  const windowWidth = window.outerWidth;
15234
15245
  if (windowWidth < screenWidth * 0.85) {
15235
15246
  const msg = `Split Screen Detectado: Janela ocupa ${(windowWidth / screenWidth * 100).toFixed(0)}% da tela`;
15236
- this.createAlert(200 /* System */, 3 /* Screen */, msg);
15247
+ this.createAlert(43 /* SplitScreen */, 3 /* Screen */, msg);
15237
15248
  this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
15238
15249
  status: "ALERT",
15239
15250
  description: msg,
@@ -15251,7 +15262,7 @@ var AlertRecorder = class {
15251
15262
  this.handleCopy = (e3) => {
15252
15263
  e3.preventDefault();
15253
15264
  const msg = "Tentativa de Copiar (Clipboard)";
15254
- this.createAlert(100 /* ForbiddenAction */, 6 /* System */, msg);
15265
+ this.createAlert(42 /* ClipBoardUse */, 3 /* Screen */, msg);
15255
15266
  this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
15256
15267
  status: "ALERT",
15257
15268
  description: msg,
@@ -15261,7 +15272,7 @@ var AlertRecorder = class {
15261
15272
  this.handleCut = (e3) => {
15262
15273
  e3.preventDefault();
15263
15274
  const msg = "Tentativa de Recortar (Clipboard)";
15264
- this.createAlert(100 /* ForbiddenAction */, 6 /* System */, msg);
15275
+ this.createAlert(42 /* ClipBoardUse */, 3 /* Screen */, msg);
15265
15276
  this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
15266
15277
  status: "ALERT",
15267
15278
  description: msg,
@@ -15271,7 +15282,7 @@ var AlertRecorder = class {
15271
15282
  this.handlePaste = (e3) => {
15272
15283
  e3.preventDefault();
15273
15284
  const msg = "Tentativa de Colar (Clipboard)";
15274
- this.createAlert(100 /* ForbiddenAction */, 6 /* System */, msg);
15285
+ this.createAlert(42 /* ClipBoardUse */, 3 /* Screen */, msg);
15275
15286
  this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
15276
15287
  status: "ALERT",
15277
15288
  description: msg,
@@ -15307,8 +15318,7 @@ var AlertRecorder = class {
15307
15318
  // ==========================================
15308
15319
  attachListeners() {
15309
15320
  if (this.optionsProctoring.captureScreen) {
15310
- window.addEventListener("blur", this.handleLostFocus);
15311
- window.addEventListener("focus", this.handleReturnFocus);
15321
+ window.addEventListener("visibilitychange", this.handleVisibilityChange);
15312
15322
  window.addEventListener("resize", this.handleResize);
15313
15323
  window.document.addEventListener("copy", this.handleCopy);
15314
15324
  window.document.addEventListener("cut", this.handleCut);
@@ -15316,8 +15326,7 @@ var AlertRecorder = class {
15316
15326
  }
15317
15327
  }
15318
15328
  detachListeners() {
15319
- window.removeEventListener("blur", this.handleLostFocus);
15320
- window.removeEventListener("focus", this.handleReturnFocus);
15329
+ window.removeEventListener("visibilitychange", this.handleVisibilityChange);
15321
15330
  window.removeEventListener("resize", this.handleResize);
15322
15331
  window.document.removeEventListener("copy", this.handleCopy);
15323
15332
  window.document.removeEventListener("cut", this.handleCut);
@@ -15352,7 +15361,7 @@ var AlertRecorder = class {
15352
15361
  // }
15353
15362
  // 4. BACKGROUND EVENTS (Eventos disparados manualmente)
15354
15363
  addBackgroundEvent(description, category = 200 /* System */) {
15355
- this.createAlert(category, 6 /* System */, description);
15364
+ this.createAlert(category, 3 /* Screen */, description);
15356
15365
  this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
15357
15366
  status: "ALERT",
15358
15367
  description,
@@ -21590,7 +21599,8 @@ var _ExternalCameraChecker = class _ExternalCameraChecker {
21590
21599
  this.connection = new HubConnectionBuilder().withUrl(hubUrl, {
21591
21600
  accessTokenFactory: () => this.context.token,
21592
21601
  transport: HttpTransportType.WebSockets,
21593
- withCredentials: false
21602
+ withCredentials: false,
21603
+ skipNegotiation: true
21594
21604
  }).withAutomaticReconnect().configureLogging(LogLevel.Information).build();
21595
21605
  this.connection.on(
21596
21606
  "ReceiveMessage",
@@ -21797,7 +21807,6 @@ var Proctoring = class {
21797
21807
  noiseLimit: 40
21798
21808
  },
21799
21809
  imageBehaviourParameters: {
21800
- frames: 40,
21801
21810
  useUploadImage: true,
21802
21811
  uploadInterval: 20,
21803
21812
  saveVideo: true
@@ -21808,8 +21817,8 @@ var Proctoring = class {
21808
21817
  detectCellPhone: false,
21809
21818
  detectNoise: false,
21810
21819
  detectSpeech: false,
21811
- realtimePackageSize: 20,
21812
- realtimeUploadInterval: 30
21820
+ realtimePackageSize: 10,
21821
+ realtimeCaptureInterval: 2
21813
21822
  }
21814
21823
  };
21815
21824
  this.proctoringId = "";
@@ -21945,6 +21954,29 @@ var Proctoring = class {
21945
21954
  return null;
21946
21955
  }
21947
21956
  }
21957
+ // metodo para fechar o alerta realtime e fica tentando verificar a face até 5 vezes
21958
+ async stopRealtimeAlert(alert) {
21959
+ const verifyMaxRetries = 3;
21960
+ const verifyFace = async (verifyCount) => {
21961
+ if (verifyCount > verifyMaxRetries) return;
21962
+ try {
21963
+ var response = await this.backend.stopRealtimeAlert({
21964
+ proctoringId: this.proctoringId,
21965
+ begin: alert.begin,
21966
+ end: alert.end,
21967
+ warningCategoryEnum: this.convertRealtimeTypeToWarningType(alert.type),
21968
+ alertImageBase64: await this.allRecorders.cameraRecorder.getCurrentImageBase64(),
21969
+ retry: verifyCount < verifyMaxRetries - 1 ? true : false
21970
+ });
21971
+ console.log("response stopRealtimeAlert", response);
21972
+ return response;
21973
+ } catch (error) {
21974
+ console.log("error stopRealtimeAlert", error);
21975
+ return verifyFace(verifyCount + 1);
21976
+ }
21977
+ };
21978
+ await verifyFace(1);
21979
+ }
21948
21980
  async onRealtimeAlerts(options = {}) {
21949
21981
  this.setOnLostFocusAlertRecorderCallback();
21950
21982
  this.setOnFocusAlertRecorderCallback();
@@ -21959,13 +21991,7 @@ var Proctoring = class {
21959
21991
  alert: this.convertRealtimeCategoryToAlertCategory(response.category)
21960
21992
  });
21961
21993
  } else if (response.status === "OK") {
21962
- await this.backend.stopRealtimeAlert({
21963
- proctoringId: this.proctoringId,
21964
- begin: response.begin,
21965
- end: response.end,
21966
- warningCategoryEnum: this.convertRealtimeTypeToWarningType(response.type),
21967
- alertImageBase64: await this.allRecorders.cameraRecorder.getCurrentImageBase64()
21968
- });
21994
+ await this.stopRealtimeAlert(response);
21969
21995
  }
21970
21996
  }
21971
21997
  };
@@ -22128,11 +22154,23 @@ Navigator: ${JSON.stringify(_navigator2)}`
22128
22154
  startResponse.screenStream = this.allRecorders.screenRecorder.screenStream;
22129
22155
  }
22130
22156
  this.state = "Recording" /* Recording */;
22131
- setTimeout(async () => {
22157
+ let verifyFirstFaceIntervalCount = 0;
22158
+ let verifyingFace = false;
22159
+ this.verifyFirstFaceInterval = setInterval(async () => {
22132
22160
  if (this.sessionOptions.proctoringType === "REALTIME") {
22133
- await this.backend.verifyFace(this.proctoringId, await this.allRecorders.cameraRecorder.getCurrentImageBase64());
22161
+ if (verifyingFace) return;
22162
+ verifyingFace = true;
22163
+ verifyFirstFaceIntervalCount++;
22164
+ try {
22165
+ var response = await this.backend.verifyFace(this.proctoringId, await this.allRecorders.cameraRecorder.getCurrentImageBase64(), verifyFirstFaceIntervalCount > 5 ? false : true);
22166
+ verifyingFace = false;
22167
+ clearInterval(this.verifyFirstFaceInterval);
22168
+ } catch (error) {
22169
+ verifyingFace = false;
22170
+ return;
22171
+ }
22134
22172
  }
22135
- }, 1e3);
22173
+ }, 1500);
22136
22174
  return startResponse;
22137
22175
  } catch (error) {
22138
22176
  console.log(error);
@@ -22270,6 +22308,9 @@ Upload Services: ${uploaderServices}`,
22270
22308
  await this.backend.externalCameraFinish(externalSessionId);
22271
22309
  }
22272
22310
  }
22311
+ if (this.verifyFirstFaceInterval) {
22312
+ clearInterval(this.verifyFirstFaceInterval);
22313
+ }
22273
22314
  this.state = "Stop" /* Stop */;
22274
22315
  } catch (error) {
22275
22316
  await this.cancel();
@@ -22657,12 +22698,12 @@ function useProctoring(proctoringOptions, enviromentConfig = "prod") {
22657
22698
  const photo = new CapturePhoto();
22658
22699
  const login = proctoring.login.bind(proctoring);
22659
22700
  const originalStart = proctoring.start.bind(proctoring);
22660
- const start = async (parameters2) => {
22701
+ const start = async (parameters2, videoOptions) => {
22661
22702
  const deviceResult = checker.getDeviceCheckResult();
22662
22703
  if (deviceResult) {
22663
22704
  proctoring.setDeviceCheckData(deviceResult);
22664
22705
  }
22665
- return originalStart(parameters2);
22706
+ return originalStart(parameters2, videoOptions);
22666
22707
  };
22667
22708
  const finish = proctoring.finish.bind(proctoring);
22668
22709
  const startChallenge = proctoring.startChallenge.bind(proctoring);
package/index.js CHANGED
@@ -29916,12 +29916,12 @@ var BackendService = class {
29916
29916
  });
29917
29917
  return result.data;
29918
29918
  }
29919
- async verifyFace(proctoringId2, faceImage) {
29919
+ async verifyFace(proctoringId2, faceImage, retry) {
29920
29920
  const result = await this.makeRequestAxios({
29921
29921
  path: `/Realtime/verify-face`,
29922
29922
  method: "POST",
29923
29923
  jwt: this.token,
29924
- body: { "proctoringId": proctoringId2, "base64": faceImage }
29924
+ body: { "proctoringId": proctoringId2, "base64": faceImage, "retry": retry }
29925
29925
  });
29926
29926
  return result.data;
29927
29927
  }
@@ -30797,7 +30797,6 @@ var CameraRecorder = class {
30797
30797
  noiseLimit: 40
30798
30798
  },
30799
30799
  imageBehaviourParameters: {
30800
- frames: 40,
30801
30800
  useUploadImage: true,
30802
30801
  uploadInterval: 20,
30803
30802
  saveVideo: true
@@ -30809,7 +30808,6 @@ var CameraRecorder = class {
30809
30808
  }
30810
30809
  };
30811
30810
  // private imageParams: ImageParameters = {
30812
- // frames: 40,
30813
30811
  // useUploadImage: true,
30814
30812
  // uploadInterval: 20,
30815
30813
  // saveVideo: true
@@ -30901,7 +30899,7 @@ var CameraRecorder = class {
30901
30899
  }
30902
30900
  }
30903
30901
  async startRecording(options) {
30904
- var _a2, _b, _c2, _d, _e3, _f, _g, _h, _i3;
30902
+ var _a2, _b, _c2, _d, _e3, _f, _g, _h;
30905
30903
  if ((((_a2 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _a2.detectPerson) || ((_b = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _b.detectCellPhone) || ((_c2 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _c2.detectFace)) && !(options == null ? void 0 : options.retry)) {
30906
30904
  await this.initializeDetectors();
30907
30905
  }
@@ -30981,7 +30979,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
30981
30979
  this.filesToUpload = [];
30982
30980
  if (this.options.proctoringType == "REALTIME") {
30983
30981
  this.captureFrame();
30984
- this.sendFrameInterval = setInterval(() => this.captureFrame(), 1e3 * ((_i3 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _i3.realtimeUploadInterval));
30985
30982
  }
30986
30983
  this.packageCount = 0;
30987
30984
  }
@@ -31012,7 +31009,8 @@ Setting: ${JSON.stringify(settings, null, 2)}`
31012
31009
  clearInterval(this.imageInterval);
31013
31010
  clearInterval(this.sendFrameInterval);
31014
31011
  if (this.options.proctoringType == "REALTIME" && this.upload && this.backendToken) {
31015
- await this.sendPackage();
31012
+ await this.sendPackage(this.filesToUpload);
31013
+ await this.filesToUpload.splice(0, this.filesToUpload.length);
31016
31014
  }
31017
31015
  this.volumeMeter && this.volumeMeter.stop();
31018
31016
  this.intervalNoiseDetection && clearInterval(this.intervalNoiseDetection);
@@ -31082,23 +31080,29 @@ Setting: ${JSON.stringify(settings, null, 2)}`
31082
31080
  this.canvas.getContext("2d").drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
31083
31081
  return this.canvas.toDataURL("image/jpeg");
31084
31082
  }
31085
- // De um em um segundo captura um frame ligado de 30 em 30 segundos)
31083
+ // captura um frame a cada intervalo de tempo definido no paramsConfig.videoBehaviourParameters?.realtimeCaptureInterval!
31086
31084
  captureFrame() {
31087
- var _a2;
31085
+ var _a2, _b;
31088
31086
  let imageFile;
31089
31087
  this.configImageCapture();
31088
+ let newCanvasWidth = this.videoOptions.width / 2;
31089
+ let newCanvasHeight = this.videoOptions.height / 2;
31090
+ if (newCanvasWidth < 320) newCanvasWidth = 320;
31091
+ if (newCanvasHeight < 180) newCanvasHeight = 180;
31092
+ this.canvas.width = newCanvasWidth;
31093
+ this.canvas.height = newCanvasHeight;
31090
31094
  const packSize = (_a2 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _a2.realtimePackageSize;
31091
- let initSend = false;
31092
- this.imageCount++;
31095
+ this.imageCount = 0;
31093
31096
  this.imageInterval = setInterval(async () => {
31097
+ console.log("capturando frame " + this.imageCount);
31094
31098
  this.canvas.getContext("2d").drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
31095
31099
  const image_data_url = this.canvas.toDataURL("image/jpeg");
31096
31100
  if (this.proctoringId == void 0) return;
31097
- if (initSend == false && packSize == this.imageCount) {
31098
- initSend = true;
31101
+ if (packSize == this.imageCount) {
31099
31102
  this.imageCount = 0;
31100
- clearInterval(this.imageInterval);
31101
- this.sendPackage();
31103
+ const framesToSend = [...this.filesToUpload];
31104
+ this.sendPackage(framesToSend);
31105
+ await this.filesToUpload.splice(0, this.filesToUpload.length);
31102
31106
  }
31103
31107
  let imageName = `${this.proctoringId}_${this.imageCount + 1}.jpg`;
31104
31108
  imageFile = await this.getFile(image_data_url, imageName, "image/jpeg");
@@ -31106,22 +31110,24 @@ Setting: ${JSON.stringify(settings, null, 2)}`
31106
31110
  this.filesToUpload.push(imageFile);
31107
31111
  this.imageCount++;
31108
31112
  }
31109
- }, 1e3);
31113
+ }, ((_b = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _b.realtimeCaptureInterval) * 1e3);
31110
31114
  }
31111
31115
  // envia pacote de imagens
31112
- async sendPackage() {
31116
+ async sendPackage(framesToSend) {
31117
+ var _a2, _b;
31113
31118
  let pending = false;
31114
31119
  let undeliveredPackagesCount = 0;
31120
+ const packSize = (_a2 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _a2.realtimePackageSize;
31121
+ const packCaptureInterval = ((_b = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _b.realtimeCaptureInterval) + 1;
31115
31122
  if (this.upload && this.backendToken && !pending && this.filesToUpload.length > 0) {
31116
31123
  undeliveredPackagesCount = 0;
31117
31124
  pending = true;
31118
31125
  const zip = new import_jszip_min.default();
31119
- const files = this.filesToUpload;
31120
- for (const file of files) {
31126
+ for (const file of framesToSend) {
31121
31127
  zip.file(file.name, file);
31122
31128
  }
31123
31129
  const blob = await zip.generateAsync({ type: "blob" });
31124
- let packageName = "realtime_package_" + 30 * this.packageCount + ".zip";
31130
+ let packageName = "realtime_package_" + packSize * packCaptureInterval * this.packageCount + ".zip";
31125
31131
  const myPackage = new File(
31126
31132
  [blob],
31127
31133
  packageName,
@@ -31134,7 +31140,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
31134
31140
  this.backendToken
31135
31141
  );
31136
31142
  if (uploadResult.uploaded == true) {
31137
- await this.filesToUpload.splice(0, this.filesToUpload.length);
31138
31143
  this.packageCount++;
31139
31144
  } else {
31140
31145
  console.log("erro no upload do pacote");
@@ -33297,9 +33302,15 @@ var AlertRecorder = class {
33297
33302
  // HANDLERS (Funções Arrow para preservar o 'this')
33298
33303
  // ==========================================
33299
33304
  // 1. LOST / RETURN FOCUS
33305
+ this.handleVisibilityChange = () => {
33306
+ if (document.visibilityState === "visible") {
33307
+ this.handleReturnFocus();
33308
+ } else {
33309
+ this.handleLostFocus();
33310
+ }
33311
+ };
33300
33312
  this.handleLostFocus = () => {
33301
33313
  if (this.getRelativeTime() > 1e4) {
33302
- this.createAlert(25 /* FocusOff */, 3 /* Screen */, "Usu\xE1rio mudou de aba ou minimizou");
33303
33314
  const alertPayload = {
33304
33315
  begin: this.getRelativeTime(),
33305
33316
  end: 0,
@@ -33330,7 +33341,7 @@ var AlertRecorder = class {
33330
33341
  const windowWidth = window.outerWidth;
33331
33342
  if (windowWidth < screenWidth * 0.85) {
33332
33343
  const msg = `Split Screen Detectado: Janela ocupa ${(windowWidth / screenWidth * 100).toFixed(0)}% da tela`;
33333
- this.createAlert(200 /* System */, 3 /* Screen */, msg);
33344
+ this.createAlert(43 /* SplitScreen */, 3 /* Screen */, msg);
33334
33345
  this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
33335
33346
  status: "ALERT",
33336
33347
  description: msg,
@@ -33348,7 +33359,7 @@ var AlertRecorder = class {
33348
33359
  this.handleCopy = (e3) => {
33349
33360
  e3.preventDefault();
33350
33361
  const msg = "Tentativa de Copiar (Clipboard)";
33351
- this.createAlert(100 /* ForbiddenAction */, 6 /* System */, msg);
33362
+ this.createAlert(42 /* ClipBoardUse */, 3 /* Screen */, msg);
33352
33363
  this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
33353
33364
  status: "ALERT",
33354
33365
  description: msg,
@@ -33358,7 +33369,7 @@ var AlertRecorder = class {
33358
33369
  this.handleCut = (e3) => {
33359
33370
  e3.preventDefault();
33360
33371
  const msg = "Tentativa de Recortar (Clipboard)";
33361
- this.createAlert(100 /* ForbiddenAction */, 6 /* System */, msg);
33372
+ this.createAlert(42 /* ClipBoardUse */, 3 /* Screen */, msg);
33362
33373
  this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
33363
33374
  status: "ALERT",
33364
33375
  description: msg,
@@ -33368,7 +33379,7 @@ var AlertRecorder = class {
33368
33379
  this.handlePaste = (e3) => {
33369
33380
  e3.preventDefault();
33370
33381
  const msg = "Tentativa de Colar (Clipboard)";
33371
- this.createAlert(100 /* ForbiddenAction */, 6 /* System */, msg);
33382
+ this.createAlert(42 /* ClipBoardUse */, 3 /* Screen */, msg);
33372
33383
  this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
33373
33384
  status: "ALERT",
33374
33385
  description: msg,
@@ -33404,8 +33415,7 @@ var AlertRecorder = class {
33404
33415
  // ==========================================
33405
33416
  attachListeners() {
33406
33417
  if (this.optionsProctoring.captureScreen) {
33407
- window.addEventListener("blur", this.handleLostFocus);
33408
- window.addEventListener("focus", this.handleReturnFocus);
33418
+ window.addEventListener("visibilitychange", this.handleVisibilityChange);
33409
33419
  window.addEventListener("resize", this.handleResize);
33410
33420
  window.document.addEventListener("copy", this.handleCopy);
33411
33421
  window.document.addEventListener("cut", this.handleCut);
@@ -33413,8 +33423,7 @@ var AlertRecorder = class {
33413
33423
  }
33414
33424
  }
33415
33425
  detachListeners() {
33416
- window.removeEventListener("blur", this.handleLostFocus);
33417
- window.removeEventListener("focus", this.handleReturnFocus);
33426
+ window.removeEventListener("visibilitychange", this.handleVisibilityChange);
33418
33427
  window.removeEventListener("resize", this.handleResize);
33419
33428
  window.document.removeEventListener("copy", this.handleCopy);
33420
33429
  window.document.removeEventListener("cut", this.handleCut);
@@ -33449,7 +33458,7 @@ var AlertRecorder = class {
33449
33458
  // }
33450
33459
  // 4. BACKGROUND EVENTS (Eventos disparados manualmente)
33451
33460
  addBackgroundEvent(description, category = 200 /* System */) {
33452
- this.createAlert(category, 6 /* System */, description);
33461
+ this.createAlert(category, 3 /* Screen */, description);
33453
33462
  this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
33454
33463
  status: "ALERT",
33455
33464
  description,
@@ -36839,7 +36848,8 @@ var _ExternalCameraChecker = class _ExternalCameraChecker {
36839
36848
  this.connection = new import_signalr.HubConnectionBuilder().withUrl(hubUrl, {
36840
36849
  accessTokenFactory: () => this.context.token,
36841
36850
  transport: import_signalr.HttpTransportType.WebSockets,
36842
- withCredentials: false
36851
+ withCredentials: false,
36852
+ skipNegotiation: true
36843
36853
  }).withAutomaticReconnect().configureLogging(import_signalr.LogLevel.Information).build();
36844
36854
  this.connection.on(
36845
36855
  "ReceiveMessage",
@@ -37046,7 +37056,6 @@ var Proctoring = class {
37046
37056
  noiseLimit: 40
37047
37057
  },
37048
37058
  imageBehaviourParameters: {
37049
- frames: 40,
37050
37059
  useUploadImage: true,
37051
37060
  uploadInterval: 20,
37052
37061
  saveVideo: true
@@ -37057,8 +37066,8 @@ var Proctoring = class {
37057
37066
  detectCellPhone: false,
37058
37067
  detectNoise: false,
37059
37068
  detectSpeech: false,
37060
- realtimePackageSize: 20,
37061
- realtimeUploadInterval: 30
37069
+ realtimePackageSize: 10,
37070
+ realtimeCaptureInterval: 2
37062
37071
  }
37063
37072
  };
37064
37073
  this.proctoringId = "";
@@ -37194,6 +37203,29 @@ var Proctoring = class {
37194
37203
  return null;
37195
37204
  }
37196
37205
  }
37206
+ // metodo para fechar o alerta realtime e fica tentando verificar a face até 5 vezes
37207
+ async stopRealtimeAlert(alert) {
37208
+ const verifyMaxRetries = 3;
37209
+ const verifyFace = async (verifyCount) => {
37210
+ if (verifyCount > verifyMaxRetries) return;
37211
+ try {
37212
+ var response = await this.backend.stopRealtimeAlert({
37213
+ proctoringId: this.proctoringId,
37214
+ begin: alert.begin,
37215
+ end: alert.end,
37216
+ warningCategoryEnum: this.convertRealtimeTypeToWarningType(alert.type),
37217
+ alertImageBase64: await this.allRecorders.cameraRecorder.getCurrentImageBase64(),
37218
+ retry: verifyCount < verifyMaxRetries - 1 ? true : false
37219
+ });
37220
+ console.log("response stopRealtimeAlert", response);
37221
+ return response;
37222
+ } catch (error) {
37223
+ console.log("error stopRealtimeAlert", error);
37224
+ return verifyFace(verifyCount + 1);
37225
+ }
37226
+ };
37227
+ await verifyFace(1);
37228
+ }
37197
37229
  async onRealtimeAlerts(options = {}) {
37198
37230
  this.setOnLostFocusAlertRecorderCallback();
37199
37231
  this.setOnFocusAlertRecorderCallback();
@@ -37208,13 +37240,7 @@ var Proctoring = class {
37208
37240
  alert: this.convertRealtimeCategoryToAlertCategory(response.category)
37209
37241
  });
37210
37242
  } else if (response.status === "OK") {
37211
- await this.backend.stopRealtimeAlert({
37212
- proctoringId: this.proctoringId,
37213
- begin: response.begin,
37214
- end: response.end,
37215
- warningCategoryEnum: this.convertRealtimeTypeToWarningType(response.type),
37216
- alertImageBase64: await this.allRecorders.cameraRecorder.getCurrentImageBase64()
37217
- });
37243
+ await this.stopRealtimeAlert(response);
37218
37244
  }
37219
37245
  }
37220
37246
  };
@@ -37377,11 +37403,23 @@ Navigator: ${JSON.stringify(_navigator2)}`
37377
37403
  startResponse.screenStream = this.allRecorders.screenRecorder.screenStream;
37378
37404
  }
37379
37405
  this.state = "Recording" /* Recording */;
37380
- setTimeout(async () => {
37406
+ let verifyFirstFaceIntervalCount = 0;
37407
+ let verifyingFace = false;
37408
+ this.verifyFirstFaceInterval = setInterval(async () => {
37381
37409
  if (this.sessionOptions.proctoringType === "REALTIME") {
37382
- await this.backend.verifyFace(this.proctoringId, await this.allRecorders.cameraRecorder.getCurrentImageBase64());
37410
+ if (verifyingFace) return;
37411
+ verifyingFace = true;
37412
+ verifyFirstFaceIntervalCount++;
37413
+ try {
37414
+ var response = await this.backend.verifyFace(this.proctoringId, await this.allRecorders.cameraRecorder.getCurrentImageBase64(), verifyFirstFaceIntervalCount > 5 ? false : true);
37415
+ verifyingFace = false;
37416
+ clearInterval(this.verifyFirstFaceInterval);
37417
+ } catch (error) {
37418
+ verifyingFace = false;
37419
+ return;
37420
+ }
37383
37421
  }
37384
- }, 1e3);
37422
+ }, 1500);
37385
37423
  return startResponse;
37386
37424
  } catch (error) {
37387
37425
  console.log(error);
@@ -37519,6 +37557,9 @@ Upload Services: ${uploaderServices}`,
37519
37557
  await this.backend.externalCameraFinish(externalSessionId);
37520
37558
  }
37521
37559
  }
37560
+ if (this.verifyFirstFaceInterval) {
37561
+ clearInterval(this.verifyFirstFaceInterval);
37562
+ }
37522
37563
  this.state = "Stop" /* Stop */;
37523
37564
  } catch (error) {
37524
37565
  await this.cancel();
@@ -37906,12 +37947,12 @@ function useProctoring(proctoringOptions, enviromentConfig = "prod") {
37906
37947
  const photo = new CapturePhoto();
37907
37948
  const login = proctoring.login.bind(proctoring);
37908
37949
  const originalStart = proctoring.start.bind(proctoring);
37909
- const start = async (parameters2) => {
37950
+ const start = async (parameters2, videoOptions) => {
37910
37951
  const deviceResult = checker.getDeviceCheckResult();
37911
37952
  if (deviceResult) {
37912
37953
  proctoring.setDeviceCheckData(deviceResult);
37913
37954
  }
37914
- return originalStart(parameters2);
37955
+ return originalStart(parameters2, videoOptions);
37915
37956
  };
37916
37957
  const finish = proctoring.finish.bind(proctoring);
37917
37958
  const startChallenge = proctoring.startChallenge.bind(proctoring);