@wireapp/core 17.20.0 → 17.21.0

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.
@@ -81,7 +81,6 @@ import type {
81
81
  FileAssetMessage,
82
82
  FileAssetMetaDataMessage,
83
83
  HideMessage,
84
- ImageAssetMessage,
85
84
  ImageAssetMessageOutgoing,
86
85
  LocationMessage,
87
86
  OtrMessage,
@@ -264,6 +263,18 @@ export class ConversationService {
264
263
  return undefined;
265
264
  }
266
265
 
266
+ /**
267
+ * Sends a message to a federated environment.
268
+ *
269
+ * @param sendingClientId - The clientId from which the message is sent
270
+ * @param conversationId - The conversation in which to send the message
271
+ * @param conversationDomain - The domain where the conversation lives
272
+ * @param genericMessage - The payload of the message to send
273
+ * @param userIds? - can be either a QualifiedId[] or QualfiedUserClients. The type has some effect on the behavior of the method.
274
+ * When given a QualifiedId[] the method will fetch the freshest list of devices for those users (since they are not given by the consumer). As a consequence no ClientMismatch error will trigger and we will ignore missing clients when sending
275
+ * When given a QualifiedUserClients the method will only send to the clients listed in the userIds. This could lead to ClientMismatch (since the given list of devices might not be the freshest one and new clients could have been created)
276
+ * @return Resolves with the message sending status from backend
277
+ */
267
278
  private async sendFederatedGenericMessage(
268
279
  sendingClientId: string,
269
280
  conversationId: string,
@@ -272,7 +283,9 @@ export class ConversationService {
272
283
  userIds?: QualifiedId[] | QualifiedUserClients,
273
284
  ): Promise<MessageSendingStatus> {
274
285
  const plainTextArray = GenericMessage.encode(genericMessage).finish();
275
- const preKeyBundles = await this.getQualifiedPreKeyBundle(conversationId, conversationDomain, userIds);
286
+ const preKeyBundles = isQualifiedUserClients(userIds)
287
+ ? userIds
288
+ : await this.getQualifiedPreKeyBundle(conversationId, conversationDomain, userIds);
276
289
 
277
290
  const recipients = await this.cryptographyService.encryptQualified(plainTextArray, preKeyBundles);
278
291
 
@@ -282,6 +295,8 @@ export class ConversationService {
282
295
  conversationDomain,
283
296
  recipients,
284
297
  plainTextArray,
298
+ undefined,
299
+ isQualifiedUserClients(userIds), // we want to check mismatch in case the consumer gave an exact list of users/devices
285
300
  );
286
301
  }
287
302
 
@@ -332,160 +347,51 @@ export class ConversationService {
332
347
  : this.messageService.sendOTRMessage(sendingClientId, recipients, conversationId, plainTextArray);
333
348
  }
334
349
 
335
- private async sendButtonAction(
336
- payloadBundle: ButtonActionMessage,
337
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
338
- sendAsProtobuf?: boolean,
339
- conversationDomain?: string,
340
- ): Promise<ButtonActionMessage> {
341
- const genericMessage = GenericMessage.create({
350
+ private generateButtonActionGenericMessage(payloadBundle: ButtonActionMessage): GenericMessage {
351
+ return GenericMessage.create({
342
352
  [GenericMessageType.BUTTON_ACTION]: ButtonAction.create(payloadBundle.content),
343
353
  messageId: payloadBundle.id,
344
354
  });
345
-
346
- await this.sendGenericMessage(
347
- this.apiClient.validatedClientId,
348
- payloadBundle.conversation,
349
- genericMessage,
350
- userIds,
351
- sendAsProtobuf,
352
- conversationDomain,
353
- );
354
-
355
- return {
356
- ...payloadBundle,
357
- messageTimer: 0,
358
- state: PayloadBundleState.OUTGOING_SENT,
359
- };
360
355
  }
361
356
 
362
- private async sendButtonActionConfirmation(
357
+ private generateButtonActionConfirmationGenericMessage(
363
358
  payloadBundle: ButtonActionConfirmationMessage,
364
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
365
- sendAsProtobuf?: boolean,
366
- conversationDomain?: string,
367
- ): Promise<ButtonActionConfirmationMessage> {
368
- const genericMessage = GenericMessage.create({
359
+ ): GenericMessage {
360
+ return GenericMessage.create({
369
361
  [GenericMessageType.BUTTON_ACTION_CONFIRMATION]: ButtonActionConfirmation.create(payloadBundle.content),
370
362
  messageId: payloadBundle.id,
371
363
  });
372
-
373
- await this.sendGenericMessage(
374
- this.apiClient.validatedClientId,
375
- payloadBundle.conversation,
376
- genericMessage,
377
- userIds,
378
- sendAsProtobuf,
379
- conversationDomain,
380
- );
381
-
382
- return {
383
- ...payloadBundle,
384
- messageTimer: 0,
385
- state: PayloadBundleState.OUTGOING_SENT,
386
- };
387
364
  }
388
365
 
389
- private async sendComposite(
390
- payloadBundle: CompositeMessage,
391
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
392
- sendAsProtobuf?: boolean,
393
- conversationDomain?: string,
394
- ): Promise<CompositeMessage> {
395
- const genericMessage = GenericMessage.create({
366
+ private generateCompositeGenericMessage(payloadBundle: CompositeMessage): GenericMessage {
367
+ return GenericMessage.create({
396
368
  [GenericMessageType.COMPOSITE]: Composite.create(payloadBundle.content),
397
369
  messageId: payloadBundle.id,
398
370
  });
399
-
400
- await this.sendGenericMessage(
401
- this.apiClient.validatedClientId,
402
- payloadBundle.conversation,
403
- genericMessage,
404
- userIds,
405
- sendAsProtobuf,
406
- conversationDomain,
407
- );
408
-
409
- return {
410
- ...payloadBundle,
411
- messageTimer: 0,
412
- state: PayloadBundleState.OUTGOING_SENT,
413
- };
414
371
  }
415
372
 
416
- private async sendConfirmation(
417
- payloadBundle: ConfirmationMessage,
418
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
419
- sendAsProtobuf?: boolean,
420
- conversationDomain?: string,
421
- callbacks?: MessageSendingCallbacks,
422
- ): Promise<ConfirmationMessage> {
373
+ private generateConfirmationGenericMessage(payloadBundle: ConfirmationMessage): GenericMessage {
423
374
  const content = Confirmation.create(payloadBundle.content);
424
375
 
425
- const genericMessage = GenericMessage.create({
376
+ return GenericMessage.create({
426
377
  [GenericMessageType.CONFIRMATION]: content,
427
378
  messageId: payloadBundle.id,
428
379
  });
429
- callbacks?.onStart?.(genericMessage);
430
-
431
- const response = await this.sendGenericMessage(
432
- this.apiClient.validatedClientId,
433
- payloadBundle.conversation,
434
- genericMessage,
435
- userIds,
436
- sendAsProtobuf,
437
- conversationDomain,
438
- );
439
- callbacks?.onSuccess?.(genericMessage, response?.time);
440
-
441
- return {
442
- ...payloadBundle,
443
- messageTimer: 0,
444
- state: PayloadBundleState.OUTGOING_SENT,
445
- };
446
380
  }
447
381
 
448
- private async sendEditedText(
449
- payloadBundle: EditedTextMessage,
450
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
451
- sendAsProtobuf?: boolean,
452
- conversationDomain?: string,
453
- callbacks?: MessageSendingCallbacks,
454
- ): Promise<EditedTextMessage> {
382
+ private generateEditedTextGenericMessage(payloadBundle: EditedTextMessage): GenericMessage {
455
383
  const editedMessage = MessageEdit.create({
456
384
  replacingMessageId: payloadBundle.content.originalMessageId,
457
385
  text: MessageToProtoMapper.mapText(payloadBundle),
458
386
  });
459
387
 
460
- const genericMessage = GenericMessage.create({
388
+ return GenericMessage.create({
461
389
  [GenericMessageType.EDITED]: editedMessage,
462
390
  messageId: payloadBundle.id,
463
391
  });
464
- callbacks?.onStart?.(genericMessage);
465
-
466
- const response = await this.sendGenericMessage(
467
- this.apiClient.validatedClientId,
468
- payloadBundle.conversation,
469
- genericMessage,
470
- userIds,
471
- sendAsProtobuf,
472
- conversationDomain,
473
- );
474
- callbacks?.onSuccess?.(genericMessage, response?.time);
475
-
476
- return {
477
- ...payloadBundle,
478
- messageTimer: 0,
479
- state: PayloadBundleState.OUTGOING_SENT,
480
- };
481
392
  }
482
393
 
483
- private async sendFileData(
484
- payloadBundle: FileAssetMessage,
485
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
486
- sendAsProtobuf?: boolean,
487
- conversationDomain?: string,
488
- ): Promise<FileAssetMessage> {
394
+ private generateFileDataGenericMessage(payloadBundle: FileAssetMessage): GenericMessage {
489
395
  if (!payloadBundle.content) {
490
396
  throw new Error('No content for sendFileData provided.');
491
397
  }
@@ -507,38 +413,16 @@ export class ConversationService {
507
413
 
508
414
  assetMessage.status = AssetTransferState.UPLOADED;
509
415
 
510
- let genericMessage = GenericMessage.create({
416
+ const genericMessage = GenericMessage.create({
511
417
  [GenericMessageType.ASSET]: assetMessage,
512
418
  messageId: payloadBundle.id,
513
419
  });
514
420
 
515
421
  const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
516
- if (expireAfterMillis > 0) {
517
- genericMessage = this.createEphemeral(genericMessage, expireAfterMillis);
518
- }
519
-
520
- await this.sendGenericMessage(
521
- this.apiClient.validatedClientId,
522
- payloadBundle.conversation,
523
- genericMessage,
524
- userIds,
525
- sendAsProtobuf,
526
- conversationDomain,
527
- );
528
-
529
- return {
530
- ...payloadBundle,
531
- messageTimer: this.messageTimer.getMessageTimer(payloadBundle.conversation),
532
- state: PayloadBundleState.OUTGOING_SENT,
533
- };
422
+ return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
534
423
  }
535
424
 
536
- private async sendFileMetaData(
537
- payloadBundle: FileAssetMetaDataMessage,
538
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
539
- sendAsProtobuf?: boolean,
540
- conversationDomain?: string,
541
- ): Promise<FileAssetMetaDataMessage> {
425
+ private generateFileMetaDataGenericMessage(payloadBundle: FileAssetMetaDataMessage): GenericMessage {
542
426
  if (!payloadBundle.content) {
543
427
  throw new Error('No content for sendFileMetaData provided.');
544
428
  }
@@ -559,38 +443,16 @@ export class ConversationService {
559
443
  original,
560
444
  });
561
445
 
562
- let genericMessage = GenericMessage.create({
446
+ const genericMessage = GenericMessage.create({
563
447
  [GenericMessageType.ASSET]: assetMessage,
564
448
  messageId: payloadBundle.id,
565
449
  });
566
450
 
567
451
  const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
568
- if (expireAfterMillis > 0) {
569
- genericMessage = this.createEphemeral(genericMessage, expireAfterMillis);
570
- }
571
-
572
- await this.sendGenericMessage(
573
- this.apiClient.validatedClientId,
574
- payloadBundle.conversation,
575
- genericMessage,
576
- userIds,
577
- sendAsProtobuf,
578
- conversationDomain,
579
- );
580
-
581
- return {
582
- ...payloadBundle,
583
- messageTimer: this.messageTimer.getMessageTimer(payloadBundle.conversation),
584
- state: PayloadBundleState.OUTGOING_SENT,
585
- };
452
+ return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
586
453
  }
587
454
 
588
- private async sendFileAbort(
589
- payloadBundle: FileAssetAbortMessage,
590
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
591
- sendAsProtobuf?: boolean,
592
- conversationDomain?: string,
593
- ): Promise<FileAssetAbortMessage> {
455
+ private generateFileAbortGenericMessage(payloadBundle: FileAssetAbortMessage): GenericMessage {
594
456
  if (!payloadBundle.content) {
595
457
  throw new Error('No content for sendFileAbort provided.');
596
458
  }
@@ -605,38 +467,19 @@ export class ConversationService {
605
467
 
606
468
  assetMessage.status = AssetTransferState.NOT_UPLOADED;
607
469
 
608
- let genericMessage = GenericMessage.create({
470
+ const genericMessage = GenericMessage.create({
609
471
  [GenericMessageType.ASSET]: assetMessage,
610
472
  messageId: payloadBundle.id,
611
473
  });
612
474
 
613
475
  const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
614
- if (expireAfterMillis > 0) {
615
- genericMessage = this.createEphemeral(genericMessage, expireAfterMillis);
616
- }
617
-
618
- await this.sendGenericMessage(
619
- this.apiClient.validatedClientId,
620
- payloadBundle.conversation,
621
- genericMessage,
622
- userIds,
623
- sendAsProtobuf,
624
- conversationDomain,
625
- );
626
-
627
- return {
628
- ...payloadBundle,
629
- messageTimer: this.messageTimer.getMessageTimer(payloadBundle.conversation),
630
- state: PayloadBundleState.OUTGOING_SENT,
631
- };
476
+ return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
632
477
  }
633
478
 
634
- private async sendImage(
635
- payloadBundle: ImageAssetMessageOutgoing,
636
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
637
- sendAsProtobuf?: boolean,
638
- conversationDomain?: string,
639
- ): Promise<ImageAssetMessage> {
479
+ private generateImageGenericMessage(payloadBundle: ImageAssetMessageOutgoing): {
480
+ content: AssetContent;
481
+ genericMessage: GenericMessage;
482
+ } {
640
483
  if (!payloadBundle.content) {
641
484
  throw new Error('No content for sendImage provided.');
642
485
  }
@@ -677,33 +520,13 @@ export class ConversationService {
677
520
  });
678
521
 
679
522
  const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
680
- if (expireAfterMillis > 0) {
523
+ if (expireAfterMillis) {
681
524
  genericMessage = this.createEphemeral(genericMessage, expireAfterMillis);
682
525
  }
683
-
684
- await this.sendGenericMessage(
685
- this.apiClient.validatedClientId,
686
- payloadBundle.conversation,
687
- genericMessage,
688
- userIds,
689
- sendAsProtobuf,
690
- conversationDomain,
691
- );
692
-
693
- return {
694
- ...payloadBundle,
695
- content: assetMessage as AssetContent,
696
- messageTimer: this.messageTimer.getMessageTimer(payloadBundle.conversation),
697
- state: PayloadBundleState.OUTGOING_SENT,
698
- };
526
+ return {content: assetMessage as AssetContent, genericMessage};
699
527
  }
700
528
 
701
- private async sendLocation(
702
- payloadBundle: LocationMessage,
703
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
704
- sendAsProtobuf?: boolean,
705
- conversationDomain?: string,
706
- ): Promise<LocationMessage> {
529
+ private generateLocationGenericMessage(payloadBundle: LocationMessage): GenericMessage {
707
530
  const {expectsReadConfirmation, latitude, legalHoldStatus, longitude, name, zoom} = payloadBundle.content;
708
531
 
709
532
  const locationMessage = Location.create({
@@ -715,76 +538,28 @@ export class ConversationService {
715
538
  zoom,
716
539
  });
717
540
 
718
- let genericMessage = GenericMessage.create({
541
+ const genericMessage = GenericMessage.create({
719
542
  [GenericMessageType.LOCATION]: locationMessage,
720
543
  messageId: payloadBundle.id,
721
544
  });
722
545
 
723
546
  const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
724
- if (expireAfterMillis > 0) {
725
- genericMessage = this.createEphemeral(genericMessage, expireAfterMillis);
726
- }
727
-
728
- await this.sendGenericMessage(
729
- this.apiClient.validatedClientId,
730
- payloadBundle.conversation,
731
- genericMessage,
732
- userIds,
733
- sendAsProtobuf,
734
- conversationDomain,
735
- );
736
-
737
- return {
738
- ...payloadBundle,
739
- messageTimer: this.messageTimer.getMessageTimer(payloadBundle.conversation),
740
- state: PayloadBundleState.OUTGOING_SENT,
741
- };
547
+ return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
742
548
  }
743
549
 
744
- private async sendKnock(
745
- payloadBundle: PingMessage,
746
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
747
- sendAsProtobuf?: boolean,
748
- conversationDomain?: string,
749
- callbacks?: MessageSendingCallbacks,
750
- ): Promise<PingMessage> {
550
+ private generatePingGenericMessage(payloadBundle: PingMessage): GenericMessage {
751
551
  const content = Knock.create(payloadBundle.content);
752
552
 
753
- let genericMessage = GenericMessage.create({
553
+ const genericMessage = GenericMessage.create({
754
554
  [GenericMessageType.KNOCK]: content,
755
555
  messageId: payloadBundle.id,
756
556
  });
757
- callbacks?.onStart?.(genericMessage);
758
557
 
759
558
  const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
760
- if (expireAfterMillis > 0) {
761
- genericMessage = this.createEphemeral(genericMessage, expireAfterMillis);
762
- }
763
-
764
- const response = await this.sendGenericMessage(
765
- this.apiClient.validatedClientId,
766
- payloadBundle.conversation,
767
- genericMessage,
768
- userIds,
769
- sendAsProtobuf,
770
- conversationDomain,
771
- );
772
- callbacks?.onSuccess?.(genericMessage, response?.time);
773
-
774
- return {
775
- ...payloadBundle,
776
- conversation: payloadBundle.conversation,
777
- messageTimer: this.messageTimer.getMessageTimer(payloadBundle.conversation),
778
- state: PayloadBundleState.OUTGOING_SENT,
779
- };
559
+ return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
780
560
  }
781
561
 
782
- private async sendReaction(
783
- payloadBundle: ReactionMessage,
784
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
785
- sendAsProtobuf?: boolean,
786
- conversationDomain?: string,
787
- ): Promise<ReactionMessage> {
562
+ private generateReactionGenericMessage(payloadBundle: ReactionMessage): GenericMessage {
788
563
  const {legalHoldStatus, originalMessageId, type} = payloadBundle.content;
789
564
 
790
565
  const reaction = Reaction.create({
@@ -797,114 +572,35 @@ export class ConversationService {
797
572
  [GenericMessageType.REACTION]: reaction,
798
573
  messageId: payloadBundle.id,
799
574
  });
800
-
801
- await this.sendGenericMessage(
802
- this.apiClient.validatedClientId,
803
- payloadBundle.conversation,
804
- genericMessage,
805
- userIds,
806
- sendAsProtobuf,
807
- conversationDomain,
808
- );
809
-
810
- return {
811
- ...payloadBundle,
812
- messageTimer: 0,
813
- state: PayloadBundleState.OUTGOING_SENT,
814
- };
575
+ return genericMessage;
815
576
  }
816
577
 
817
- private async sendSessionReset(
818
- payloadBundle: ResetSessionMessage,
819
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
820
- sendAsProtobuf?: boolean,
821
- conversationDomain?: string,
822
- ): Promise<ResetSessionMessage> {
823
- const genericMessage = GenericMessage.create({
578
+ private generateSessionResetGenericMessage(payloadBundle: ResetSessionMessage): GenericMessage {
579
+ return GenericMessage.create({
824
580
  [GenericMessageType.CLIENT_ACTION]: ClientAction.RESET_SESSION,
825
581
  messageId: payloadBundle.id,
826
582
  });
827
-
828
- await this.sendGenericMessage(
829
- this.apiClient.validatedClientId,
830
- payloadBundle.conversation,
831
- genericMessage,
832
- userIds,
833
- sendAsProtobuf,
834
- conversationDomain,
835
- );
836
-
837
- return {
838
- ...payloadBundle,
839
- messageTimer: this.messageTimer.getMessageTimer(payloadBundle.conversation),
840
- state: PayloadBundleState.OUTGOING_SENT,
841
- };
842
583
  }
843
584
 
844
- private async sendCall(
845
- payloadBundle: CallMessage,
846
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
847
- sendAsProtobuf?: boolean,
848
- conversationDomain?: string,
849
- ): Promise<CallMessage> {
585
+ private generateCallGenericMessage(payloadBundle: CallMessage): GenericMessage {
850
586
  const callMessage = Calling.create({
851
587
  content: payloadBundle.content,
852
588
  });
853
589
 
854
- const genericMessage = GenericMessage.create({
590
+ return GenericMessage.create({
855
591
  [GenericMessageType.CALLING]: callMessage,
856
592
  messageId: payloadBundle.id,
857
593
  });
858
-
859
- await this.sendGenericMessage(
860
- this.apiClient.validatedClientId,
861
- payloadBundle.conversation,
862
- genericMessage,
863
- userIds,
864
- sendAsProtobuf,
865
- conversationDomain,
866
- );
867
-
868
- return {
869
- ...payloadBundle,
870
- messageTimer: 0,
871
- state: PayloadBundleState.OUTGOING_SENT,
872
- };
873
594
  }
874
595
 
875
- private async sendText(
876
- payloadBundle: TextMessage,
877
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
878
- sendAsProtobuf?: boolean,
879
- conversationDomain?: string,
880
- callbacks?: MessageSendingCallbacks,
881
- ): Promise<TextMessage> {
882
- let genericMessage = GenericMessage.create({
596
+ private generateTextGenericMessage(payloadBundle: TextMessage): GenericMessage {
597
+ const genericMessage = GenericMessage.create({
883
598
  messageId: payloadBundle.id,
884
599
  [GenericMessageType.TEXT]: MessageToProtoMapper.mapText(payloadBundle),
885
600
  });
886
601
 
887
602
  const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
888
- if (expireAfterMillis > 0) {
889
- genericMessage = this.createEphemeral(genericMessage, expireAfterMillis);
890
- }
891
- callbacks?.onStart?.(genericMessage);
892
-
893
- const response = await this.sendGenericMessage(
894
- this.apiClient.validatedClientId,
895
- payloadBundle.conversation,
896
- genericMessage,
897
- userIds,
898
- sendAsProtobuf,
899
- conversationDomain,
900
- );
901
- callbacks?.onSuccess?.(genericMessage, response?.time);
902
-
903
- return {
904
- ...payloadBundle,
905
- messageTimer: this.messageTimer.getMessageTimer(payloadBundle.conversation),
906
- state: PayloadBundleState.OUTGOING_SENT,
907
- };
603
+ return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
908
604
  }
909
605
 
910
606
  public async clearConversation(
@@ -1128,64 +824,110 @@ export class ConversationService {
1128
824
  }
1129
825
 
1130
826
  /**
1131
- * @param payloadBundle Outgoing message
1132
- * @param userIds Only send message to specified user IDs or to certain clients of specified user IDs
1133
- * @param [callbacks] Optional callbacks that will be called when the message starts being sent and when it has been succesfully sent. Currently only used for `sendText`.
1134
- * @returns Sent message
827
+ * Sends a message to a conversation
828
+ *
829
+ * @param params.payloadBundle The message to send to the conversation
830
+ * @param params.userIds? Can be either a QualifiedId[], string[], UserClients or QualfiedUserClients. The type has some effect on the behavior of the method.
831
+ * When given a QualifiedId[] or string[] the method will fetch the freshest list of devices for those users (since they are not given by the consumer). As a consequence no ClientMismatch error will trigger and we will ignore missing clients when sending
832
+ * When given a QualifiedUserClients or UserClients the method will only send to the clients listed in the userIds. This could lead to ClientMismatch (since the given list of devices might not be the freshest one and new clients could have been created)
833
+ * When given a QualifiedId[] or QualifiedUserClients the method will send the message through the federated API endpoint
834
+ * When given a string[] or UserClients the method will send the message through the old API endpoint
835
+ * @param params.sendAsProtobuf?
836
+ * @param params.conversationDomain? The domain the conversation lives on (if given with QualifiedId[] or QualfiedUserClients in the userIds params, will send the message to the federated endpoint)
837
+ * @param params.callbacks? Optional callbacks that will be called when the message starts being sent and when it has been succesfully sent.
838
+ * @return resolves with the sent message
1135
839
  */
1136
- public async send({
840
+ public async send<T extends OtrMessage = OtrMessage>({
1137
841
  payloadBundle,
1138
842
  userIds,
1139
843
  sendAsProtobuf,
1140
844
  conversationDomain,
1141
845
  callbacks,
1142
846
  }: {
1143
- payloadBundle: OtrMessage;
847
+ payloadBundle: T;
1144
848
  userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients;
1145
849
  sendAsProtobuf?: boolean;
1146
850
  conversationDomain?: string;
1147
851
  callbacks?: MessageSendingCallbacks;
1148
- }) {
852
+ }): Promise<T> {
853
+ let genericMessage: GenericMessage;
854
+ let processedContent: AssetContent | undefined = undefined;
855
+
1149
856
  switch (payloadBundle.type) {
1150
857
  case PayloadBundleType.ASSET:
1151
- return this.sendFileData(payloadBundle, userIds, sendAsProtobuf, conversationDomain);
858
+ genericMessage = this.generateFileDataGenericMessage(payloadBundle);
859
+ break;
1152
860
  case PayloadBundleType.ASSET_ABORT:
1153
- return this.sendFileAbort(payloadBundle, userIds, sendAsProtobuf, conversationDomain);
861
+ genericMessage = this.generateFileAbortGenericMessage(payloadBundle);
862
+ break;
1154
863
  case PayloadBundleType.ASSET_META:
1155
- return this.sendFileMetaData(payloadBundle, userIds, sendAsProtobuf, conversationDomain);
864
+ genericMessage = this.generateFileMetaDataGenericMessage(payloadBundle);
865
+ break;
1156
866
  case PayloadBundleType.ASSET_IMAGE:
1157
- return this.sendImage(payloadBundle as ImageAssetMessageOutgoing, userIds, sendAsProtobuf, conversationDomain);
867
+ const res = this.generateImageGenericMessage(payloadBundle as ImageAssetMessageOutgoing);
868
+ genericMessage = res.genericMessage;
869
+ processedContent = res.content;
870
+ break;
1158
871
  case PayloadBundleType.BUTTON_ACTION:
1159
- return this.sendButtonAction(payloadBundle, userIds, sendAsProtobuf, conversationDomain);
872
+ genericMessage = this.generateButtonActionGenericMessage(payloadBundle);
873
+ break;
1160
874
  case PayloadBundleType.BUTTON_ACTION_CONFIRMATION:
1161
- return this.sendButtonActionConfirmation(payloadBundle, userIds, sendAsProtobuf, conversationDomain);
875
+ genericMessage = this.generateButtonActionConfirmationGenericMessage(payloadBundle);
876
+ break;
1162
877
  case PayloadBundleType.CALL:
1163
- return this.sendCall(payloadBundle, userIds, sendAsProtobuf, conversationDomain);
878
+ genericMessage = this.generateCallGenericMessage(payloadBundle);
879
+ break;
1164
880
  case PayloadBundleType.CLIENT_ACTION: {
1165
- if (payloadBundle.content.clientAction === ClientAction.RESET_SESSION) {
1166
- return this.sendSessionReset(payloadBundle, userIds, sendAsProtobuf, conversationDomain);
881
+ if (payloadBundle.content.clientAction !== ClientAction.RESET_SESSION) {
882
+ throw new Error(
883
+ `No send method implemented for "${payloadBundle.type}" and ClientAction "${payloadBundle.content}".`,
884
+ );
1167
885
  }
1168
- throw new Error(
1169
- `No send method implemented for "${payloadBundle.type}" and ClientAction "${payloadBundle.content}".`,
1170
- );
886
+ genericMessage = this.generateSessionResetGenericMessage(payloadBundle);
887
+ break;
1171
888
  }
1172
889
  case PayloadBundleType.COMPOSITE:
1173
- return this.sendComposite(payloadBundle, userIds, sendAsProtobuf, conversationDomain);
890
+ genericMessage = this.generateCompositeGenericMessage(payloadBundle);
891
+ break;
1174
892
  case PayloadBundleType.CONFIRMATION:
1175
- return this.sendConfirmation(payloadBundle, userIds, sendAsProtobuf, conversationDomain, callbacks);
893
+ genericMessage = this.generateConfirmationGenericMessage(payloadBundle);
894
+ break;
1176
895
  case PayloadBundleType.LOCATION:
1177
- return this.sendLocation(payloadBundle, userIds, sendAsProtobuf, conversationDomain);
896
+ genericMessage = this.generateLocationGenericMessage(payloadBundle);
897
+ break;
1178
898
  case PayloadBundleType.MESSAGE_EDIT:
1179
- return this.sendEditedText(payloadBundle, userIds, sendAsProtobuf, conversationDomain, callbacks);
899
+ genericMessage = this.generateEditedTextGenericMessage(payloadBundle);
900
+ break;
1180
901
  case PayloadBundleType.PING:
1181
- return this.sendKnock(payloadBundle, userIds, sendAsProtobuf, conversationDomain, callbacks);
902
+ genericMessage = this.generatePingGenericMessage(payloadBundle);
903
+ break;
1182
904
  case PayloadBundleType.REACTION:
1183
- return this.sendReaction(payloadBundle, userIds, sendAsProtobuf, conversationDomain);
905
+ genericMessage = this.generateReactionGenericMessage(payloadBundle);
906
+ break;
1184
907
  case PayloadBundleType.TEXT:
1185
- return this.sendText(payloadBundle, userIds, sendAsProtobuf, conversationDomain, callbacks);
908
+ genericMessage = this.generateTextGenericMessage(payloadBundle);
909
+ break;
1186
910
  default:
1187
911
  throw new Error(`No send method implemented for "${payloadBundle['type']}".`);
1188
912
  }
913
+
914
+ callbacks?.onStart?.(genericMessage);
915
+ const response = await this.sendGenericMessage(
916
+ this.apiClient.validatedClientId,
917
+ payloadBundle.conversation,
918
+ genericMessage,
919
+ userIds,
920
+ sendAsProtobuf,
921
+ conversationDomain,
922
+ );
923
+ callbacks?.onSuccess?.(genericMessage, response?.time);
924
+
925
+ return {
926
+ ...payloadBundle,
927
+ content: processedContent || payloadBundle.content,
928
+ messageTimer: genericMessage.ephemeral?.expireAfterMillis || 0,
929
+ state: PayloadBundleState.OUTGOING_SENT,
930
+ };
1189
931
  }
1190
932
 
1191
933
  public sendTypingStart(conversationId: string): Promise<void> {