@wireapp/core 17.30.0 → 17.31.3

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 (239) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/package.json +8 -8
  3. package/src/main/cryptography/GenericMessageMapper.d.ts +0 -1
  4. package/src/main/cryptography/GenericMessageMapper.js +23 -158
  5. package/src/main/Account.js.map +0 -1
  6. package/src/main/Account.test.browser.js +0 -114
  7. package/src/main/Account.test.node.d.ts +0 -1
  8. package/src/main/Account.test.node.js +0 -214
  9. package/src/main/Account.test.node.js.map +0 -1
  10. package/src/main/Account.test.node.ts +0 -236
  11. package/src/main/Account.ts +0 -401
  12. package/src/main/CoreError.js.map +0 -1
  13. package/src/main/CoreError.ts +0 -30
  14. package/src/main/auth/LoginSanitizer.js.map +0 -1
  15. package/src/main/auth/LoginSanitizer.test.node.d.ts +0 -1
  16. package/src/main/auth/LoginSanitizer.test.node.js +0 -56
  17. package/src/main/auth/LoginSanitizer.test.node.js.map +0 -1
  18. package/src/main/auth/LoginSanitizer.test.node.ts +0 -68
  19. package/src/main/auth/LoginSanitizer.ts +0 -44
  20. package/src/main/auth/index.js.map +0 -1
  21. package/src/main/auth/index.ts +0 -20
  22. package/src/main/broadcast/AvailabilityType.js.map +0 -1
  23. package/src/main/broadcast/AvailabilityType.ts +0 -22
  24. package/src/main/broadcast/BroadcastService.js.map +0 -1
  25. package/src/main/broadcast/BroadcastService.ts +0 -66
  26. package/src/main/broadcast/index.js.map +0 -1
  27. package/src/main/broadcast/index.ts +0 -21
  28. package/src/main/client/ClientBackendRepository.js.map +0 -1
  29. package/src/main/client/ClientBackendRepository.ts +0 -33
  30. package/src/main/client/ClientDatabaseRepository.js.map +0 -1
  31. package/src/main/client/ClientDatabaseRepository.ts +0 -130
  32. package/src/main/client/ClientInfo.js.map +0 -1
  33. package/src/main/client/ClientInfo.ts +0 -28
  34. package/src/main/client/ClientService.js.map +0 -1
  35. package/src/main/client/ClientService.ts +0 -116
  36. package/src/main/client/index.js.map +0 -1
  37. package/src/main/client/index.ts +0 -23
  38. package/src/main/connection/ConnectionService.js.map +0 -1
  39. package/src/main/connection/ConnectionService.ts +0 -49
  40. package/src/main/connection/index.js.map +0 -1
  41. package/src/main/connection/index.ts +0 -20
  42. package/src/main/conversation/AbortReason.js.map +0 -1
  43. package/src/main/conversation/AbortReason.ts +0 -22
  44. package/src/main/conversation/AssetService.js.map +0 -1
  45. package/src/main/conversation/AssetService.test.node.d.ts +0 -1
  46. package/src/main/conversation/AssetService.test.node.js +0 -61
  47. package/src/main/conversation/AssetService.test.node.js.map +0 -1
  48. package/src/main/conversation/AssetService.test.node.ts +0 -65
  49. package/src/main/conversation/AssetService.ts +0 -60
  50. package/src/main/conversation/AssetTransferState.js.map +0 -1
  51. package/src/main/conversation/AssetTransferState.ts +0 -23
  52. package/src/main/conversation/ClientActionType.js.map +0 -1
  53. package/src/main/conversation/ClientActionType.ts +0 -20
  54. package/src/main/conversation/ConversationMapper.js.map +0 -1
  55. package/src/main/conversation/ConversationMapper.test.node.d.ts +0 -1
  56. package/src/main/conversation/ConversationMapper.test.node.js +0 -111
  57. package/src/main/conversation/ConversationMapper.test.node.js.map +0 -1
  58. package/src/main/conversation/ConversationMapper.test.node.ts +0 -154
  59. package/src/main/conversation/ConversationMapper.ts +0 -56
  60. package/src/main/conversation/ConversationService.js.map +0 -1
  61. package/src/main/conversation/ConversationService.test.node.d.ts +0 -1
  62. package/src/main/conversation/ConversationService.test.node.js +0 -344
  63. package/src/main/conversation/ConversationService.test.node.js.map +0 -1
  64. package/src/main/conversation/ConversationService.test.node.ts +0 -416
  65. package/src/main/conversation/ConversationService.ts +0 -1024
  66. package/src/main/conversation/GenericMessageType.js.map +0 -1
  67. package/src/main/conversation/GenericMessageType.ts +0 -44
  68. package/src/main/conversation/MessageTimer.js.map +0 -1
  69. package/src/main/conversation/MessageTimer.test.node.d.ts +0 -1
  70. package/src/main/conversation/MessageTimer.test.node.js +0 -88
  71. package/src/main/conversation/MessageTimer.test.node.js.map +0 -1
  72. package/src/main/conversation/MessageTimer.test.node.ts +0 -103
  73. package/src/main/conversation/MessageTimer.ts +0 -56
  74. package/src/main/conversation/ReactionType.js.map +0 -1
  75. package/src/main/conversation/ReactionType.ts +0 -23
  76. package/src/main/conversation/content/AssetContent.js.map +0 -1
  77. package/src/main/conversation/content/AssetContent.ts +0 -71
  78. package/src/main/conversation/content/ButtonActionConfirmationContent.js.map +0 -1
  79. package/src/main/conversation/content/ButtonActionConfirmationContent.ts +0 -21
  80. package/src/main/conversation/content/ButtonActionContent.js.map +0 -1
  81. package/src/main/conversation/content/ButtonActionContent.ts +0 -21
  82. package/src/main/conversation/content/CallingContent.js.map +0 -1
  83. package/src/main/conversation/content/CallingContent.ts +0 -20
  84. package/src/main/conversation/content/ClearedContent.js.map +0 -1
  85. package/src/main/conversation/content/ClearedContent.ts +0 -21
  86. package/src/main/conversation/content/ClientActionContent.js.map +0 -1
  87. package/src/main/conversation/content/ClientActionContent.ts +0 -22
  88. package/src/main/conversation/content/ClientAddContent.js.map +0 -1
  89. package/src/main/conversation/content/ClientAddContent.ts +0 -24
  90. package/src/main/conversation/content/ClientRemoveContent.js.map +0 -1
  91. package/src/main/conversation/content/ClientRemoveContent.ts +0 -25
  92. package/src/main/conversation/content/CompositeContent.js.map +0 -1
  93. package/src/main/conversation/content/CompositeContent.ts +0 -21
  94. package/src/main/conversation/content/ConfirmationContent.js.map +0 -1
  95. package/src/main/conversation/content/ConfirmationContent.ts +0 -21
  96. package/src/main/conversation/content/ContentType.js.map +0 -1
  97. package/src/main/conversation/content/ContentType.ts +0 -112
  98. package/src/main/conversation/content/ConversationContent.js.map +0 -1
  99. package/src/main/conversation/content/ConversationContent.ts +0 -71
  100. package/src/main/conversation/content/DeletedContent.js.map +0 -1
  101. package/src/main/conversation/content/DeletedContent.ts +0 -21
  102. package/src/main/conversation/content/EditedTextContent.js.map +0 -1
  103. package/src/main/conversation/content/EditedTextContent.ts +0 -31
  104. package/src/main/conversation/content/FileContent.js.map +0 -1
  105. package/src/main/conversation/content/FileContent.ts +0 -32
  106. package/src/main/conversation/content/HiddenContent.js.map +0 -1
  107. package/src/main/conversation/content/HiddenContent.ts +0 -21
  108. package/src/main/conversation/content/ImageContent.js.map +0 -1
  109. package/src/main/conversation/content/ImageContent.ts +0 -25
  110. package/src/main/conversation/content/KnockContent.js.map +0 -1
  111. package/src/main/conversation/content/KnockContent.ts +0 -21
  112. package/src/main/conversation/content/LinkPreviewContent.js.map +0 -1
  113. package/src/main/conversation/content/LinkPreviewContent.ts +0 -32
  114. package/src/main/conversation/content/LocationContent.js.map +0 -1
  115. package/src/main/conversation/content/LocationContent.ts +0 -29
  116. package/src/main/conversation/content/MentionContent.js.map +0 -1
  117. package/src/main/conversation/content/MentionContent.ts +0 -21
  118. package/src/main/conversation/content/QuoteContent.js.map +0 -1
  119. package/src/main/conversation/content/QuoteContent.ts +0 -29
  120. package/src/main/conversation/content/ReactionContent.js.map +0 -1
  121. package/src/main/conversation/content/ReactionContent.ts +0 -27
  122. package/src/main/conversation/content/TextContent.js.map +0 -1
  123. package/src/main/conversation/content/TextContent.ts +0 -29
  124. package/src/main/conversation/content/TweetContent.js.map +0 -1
  125. package/src/main/conversation/content/TweetContent.ts +0 -21
  126. package/src/main/conversation/content/index.js.map +0 -1
  127. package/src/main/conversation/content/index.ts +0 -49
  128. package/src/main/conversation/index.js.map +0 -1
  129. package/src/main/conversation/index.ts +0 -28
  130. package/src/main/conversation/message/CompositeContentBuilder.js.map +0 -1
  131. package/src/main/conversation/message/CompositeContentBuilder.ts +0 -60
  132. package/src/main/conversation/message/Message.js.map +0 -1
  133. package/src/main/conversation/message/Message.ts +0 -24
  134. package/src/main/conversation/message/MessageBuilder.js.map +0 -1
  135. package/src/main/conversation/message/MessageBuilder.test.browser.js +0 -27
  136. package/src/main/conversation/message/MessageBuilder.ts +0 -488
  137. package/src/main/conversation/message/MessageService.js.map +0 -1
  138. package/src/main/conversation/message/MessageService.test.node.d.ts +0 -1
  139. package/src/main/conversation/message/MessageService.test.node.js +0 -308
  140. package/src/main/conversation/message/MessageService.test.node.js.map +0 -1
  141. package/src/main/conversation/message/MessageService.test.node.ts +0 -398
  142. package/src/main/conversation/message/MessageService.ts +0 -383
  143. package/src/main/conversation/message/MessageToProtoMapper.js.map +0 -1
  144. package/src/main/conversation/message/MessageToProtoMapper.ts +0 -114
  145. package/src/main/conversation/message/OtrMessage.js.map +0 -1
  146. package/src/main/conversation/message/OtrMessage.ts +0 -160
  147. package/src/main/conversation/message/PayloadBundle.js.map +0 -1
  148. package/src/main/conversation/message/PayloadBundle.ts +0 -101
  149. package/src/main/conversation/message/TeamMessage.js.map +0 -1
  150. package/src/main/conversation/message/TeamMessage.ts +0 -72
  151. package/src/main/conversation/message/TextContentBuilder.js.map +0 -1
  152. package/src/main/conversation/message/TextContentBuilder.ts +0 -88
  153. package/src/main/conversation/message/UserClientsUtil.js.map +0 -1
  154. package/src/main/conversation/message/UserClientsUtil.ts +0 -44
  155. package/src/main/conversation/message/UserClientsUtils.test.node.d.ts +0 -1
  156. package/src/main/conversation/message/UserClientsUtils.test.node.js +0 -42
  157. package/src/main/conversation/message/UserClientsUtils.test.node.js.map +0 -1
  158. package/src/main/conversation/message/UserClientsUtils.test.node.ts +0 -44
  159. package/src/main/conversation/message/UserMessage.js.map +0 -1
  160. package/src/main/conversation/message/UserMessage.ts +0 -95
  161. package/src/main/cryptography/AssetCryptography.browser.js.map +0 -1
  162. package/src/main/cryptography/AssetCryptography.browser.ts +0 -76
  163. package/src/main/cryptography/AssetCryptography.node.js.map +0 -1
  164. package/src/main/cryptography/AssetCryptography.node.ts +0 -85
  165. package/src/main/cryptography/CryptographyDatabaseRepository.js.map +0 -1
  166. package/src/main/cryptography/CryptographyDatabaseRepository.ts +0 -44
  167. package/src/main/cryptography/CryptographyService.js.map +0 -1
  168. package/src/main/cryptography/CryptographyService.test.browser.js +0 -195
  169. package/src/main/cryptography/CryptographyService.test.node.d.ts +0 -1
  170. package/src/main/cryptography/CryptographyService.test.node.js +0 -228
  171. package/src/main/cryptography/CryptographyService.test.node.js.map +0 -1
  172. package/src/main/cryptography/CryptographyService.test.node.ts +0 -246
  173. package/src/main/cryptography/CryptographyService.ts +0 -246
  174. package/src/main/cryptography/EncryptedAsset.js.map +0 -1
  175. package/src/main/cryptography/EncryptedAsset.ts +0 -30
  176. package/src/main/cryptography/GenericMessageMapper.js.map +0 -1
  177. package/src/main/cryptography/GenericMessageMapper.ts +0 -364
  178. package/src/main/cryptography/MessageHashService.js.map +0 -1
  179. package/src/main/cryptography/MessageHashService.test.browser.js +0 -176
  180. package/src/main/cryptography/MessageHashService.test.node.d.ts +0 -1
  181. package/src/main/cryptography/MessageHashService.test.node.js +0 -138
  182. package/src/main/cryptography/MessageHashService.test.node.js.map +0 -1
  183. package/src/main/cryptography/MessageHashService.test.node.ts +0 -176
  184. package/src/main/cryptography/MessageHashService.ts +0 -109
  185. package/src/main/cryptography/SessionPayloadBundle.js.map +0 -1
  186. package/src/main/cryptography/SessionPayloadBundle.ts +0 -23
  187. package/src/main/cryptography/index.js.map +0 -1
  188. package/src/main/cryptography/index.ts +0 -23
  189. package/src/main/giphy/GiphyService.js.map +0 -1
  190. package/src/main/giphy/GiphyService.ts +0 -37
  191. package/src/main/giphy/index.js.map +0 -1
  192. package/src/main/giphy/index.ts +0 -20
  193. package/src/main/index.js.map +0 -1
  194. package/src/main/index.test.browser.js +0 -22
  195. package/src/main/index.ts +0 -34
  196. package/src/main/notification/NotificationBackendRepository.js.map +0 -1
  197. package/src/main/notification/NotificationBackendRepository.ts +0 -33
  198. package/src/main/notification/NotificationDatabaseRepository.js.map +0 -1
  199. package/src/main/notification/NotificationDatabaseRepository.ts +0 -74
  200. package/src/main/notification/NotificationService.js.map +0 -1
  201. package/src/main/notification/NotificationService.test.browser.js +0 -179
  202. package/src/main/notification/NotificationService.test.node.d.ts +0 -1
  203. package/src/main/notification/NotificationService.test.node.js +0 -99
  204. package/src/main/notification/NotificationService.test.node.js.map +0 -1
  205. package/src/main/notification/NotificationService.test.node.ts +0 -124
  206. package/src/main/notification/NotificationService.ts +0 -260
  207. package/src/main/notification/index.js.map +0 -1
  208. package/src/main/notification/index.ts +0 -20
  209. package/src/main/self/SelfService.js.map +0 -1
  210. package/src/main/self/SelfService.ts +0 -59
  211. package/src/main/self/index.js.map +0 -1
  212. package/src/main/self/index.ts +0 -20
  213. package/src/main/team/TeamService.js.map +0 -1
  214. package/src/main/team/TeamService.ts +0 -68
  215. package/src/main/team/index.js.map +0 -1
  216. package/src/main/team/index.ts +0 -20
  217. package/src/main/test/CryptographyHelper.js.map +0 -1
  218. package/src/main/test/CryptographyHelper.ts +0 -57
  219. package/src/main/test/PayloadHelper.js.map +0 -1
  220. package/src/main/test/PayloadHelper.ts +0 -60
  221. package/src/main/user/UserMapper.js.map +0 -1
  222. package/src/main/user/UserMapper.test.node.d.ts +0 -1
  223. package/src/main/user/UserMapper.test.node.js +0 -55
  224. package/src/main/user/UserMapper.test.node.js.map +0 -1
  225. package/src/main/user/UserMapper.test.node.ts +0 -63
  226. package/src/main/user/UserMapper.ts +0 -92
  227. package/src/main/user/UserService.js.map +0 -1
  228. package/src/main/user/UserService.test.node.js +0 -141
  229. package/src/main/user/UserService.ts +0 -98
  230. package/src/main/user/index.js.map +0 -1
  231. package/src/main/user/index.ts +0 -20
  232. package/src/main/util/TypePredicateUtil.js.map +0 -1
  233. package/src/main/util/TypePredicateUtil.test.node.d.ts +0 -1
  234. package/src/main/util/TypePredicateUtil.test.node.js +0 -42
  235. package/src/main/util/TypePredicateUtil.test.node.js.map +0 -1
  236. package/src/main/util/TypePredicateUtil.test.node.ts +0 -44
  237. package/src/main/util/TypePredicateUtil.ts +0 -52
  238. package/src/main/util/index.js.map +0 -1
  239. package/src/main/util/index.ts +0 -20
@@ -1,1024 +0,0 @@
1
- /*
2
- * Wire
3
- * Copyright (C) 2018 Wire Swiss GmbH
4
- *
5
- * This program is free software: you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation, either version 3 of the License, or
8
- * (at your option) any later version.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see http://www.gnu.org/licenses/.
17
- *
18
- */
19
-
20
- import type {APIClient} from '@wireapp/api-client';
21
- import {
22
- MessageSendingStatus,
23
- Conversation,
24
- CONVERSATION_TYPE,
25
- DefaultConversationRoleName,
26
- MutedStatus,
27
- NewConversation,
28
- QualifiedUserClients,
29
- UserClients,
30
- ClientMismatch,
31
- } from '@wireapp/api-client/src/conversation/';
32
- import {CONVERSATION_TYPING, ConversationMemberUpdateData} from '@wireapp/api-client/src/conversation/data/';
33
- import type {ConversationMemberLeaveEvent} from '@wireapp/api-client/src/event/';
34
- import type {QualifiedId, QualifiedUserPreKeyBundleMap, UserPreKeyBundleMap} from '@wireapp/api-client/src/user/';
35
- import {
36
- Asset,
37
- ButtonAction,
38
- ButtonActionConfirmation,
39
- Calling,
40
- Cleared,
41
- ClientAction,
42
- Composite,
43
- Confirmation,
44
- Ephemeral,
45
- GenericMessage,
46
- Knock,
47
- Location,
48
- MessageDelete,
49
- MessageEdit,
50
- MessageHide,
51
- Reaction,
52
- } from '@wireapp/protocol-messaging';
53
-
54
- import {
55
- AssetService,
56
- AssetTransferState,
57
- GenericMessageType,
58
- MessageTimer,
59
- PayloadBundleSource,
60
- PayloadBundleState,
61
- PayloadBundleType,
62
- } from '../conversation/';
63
- import type {AssetContent, ClearedContent, DeletedContent, HiddenContent, RemoteData} from '../conversation/content/';
64
- import type {CryptographyService} from '../cryptography/';
65
- import * as AssetCryptography from '../cryptography/AssetCryptography.node';
66
- import {isStringArray, isQualifiedIdArray, isQualifiedUserClients, isUserClients} from '../util/TypePredicateUtil';
67
- import {MessageBuilder} from './message/MessageBuilder';
68
- import {MessageService} from './message/MessageService';
69
- import {MessageToProtoMapper} from './message/MessageToProtoMapper';
70
- import type {
71
- ButtonActionConfirmationMessage,
72
- ButtonActionMessage,
73
- CallMessage,
74
- ClearConversationMessage,
75
- CompositeMessage,
76
- ConfirmationMessage,
77
- DeleteMessage,
78
- EditedTextMessage,
79
- FileAssetAbortMessage,
80
- FileAssetMessage,
81
- FileAssetMetaDataMessage,
82
- HideMessage,
83
- ImageAssetMessageOutgoing,
84
- LocationMessage,
85
- OtrMessage,
86
- PingMessage,
87
- ReactionMessage,
88
- ResetSessionMessage,
89
- TextMessage,
90
- } from './message/OtrMessage';
91
-
92
- export enum MessageTargetMode {
93
- NONE,
94
- USERS,
95
- USERS_CLIENTS,
96
- }
97
-
98
- interface MessageSendingOptions {
99
- /**
100
- * The federated domain the server runs on. Should only be set for federation enabled envs
101
- */
102
- conversationDomain?: string;
103
-
104
- /**
105
- * can be either a QualifiedId[] or QualfiedUserClients or undefined. The type has some effect on the behavior of the method.
106
- * When given undefined the method will fetch both the members of the conversations and their devices. No ClientMismatch can happen in that case
107
- * 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
108
- * 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)
109
- */
110
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients;
111
-
112
- /**
113
- * Will send the message as a protobuf payload
114
- */
115
- sendAsProtobuf?: boolean;
116
- nativePush?: boolean;
117
-
118
- /**
119
- * Will be called whenever there is a clientmismatch returned from the server. Needs to be combined with a userIds of type QualifiedUserClients
120
- */
121
- onClientMismatch?: MessageSendingCallbacks['onClientMismatch'];
122
-
123
- /**
124
- * Defines the behavior to use when a mismatch happens on backend side:
125
- * - NONE -> Not a targetted message, we want to send to all the users/clients in the conversation. Will report all missing users and clients (default mode)
126
- * - USERS -> A message targetted to all the clients of the given users (according to params.userIds). Will ignore missing users and only report missing clients for the given params.userIds
127
- * - USERS_CLIENTS -> A message targetted at some specific clients of specific users (according to params.userIds). Will force sending the message even if users or clients are missing
128
- */
129
- targetMode?: MessageTargetMode;
130
- }
131
-
132
- export interface MessageSendingCallbacks {
133
- /**
134
- * Will be called before a message is actually sent. Returning 'false' will prevent the message from being sent
135
- * @param message The message being sent
136
- * @return true or undefined if the message should be sent, false if the message sending should be cancelled
137
- */
138
- onStart?: (message: GenericMessage) => void | boolean | Promise<boolean>;
139
-
140
- onSuccess?: (message: GenericMessage, sentTime?: string) => void;
141
- /**
142
- * Called whenever there is a clientmismatch returned from the server. Will also indicate the sending status of the message (if it was already sent or not)
143
- *
144
- * @param status The mismatch info
145
- * @param wasSent Indicate whether the message was already sent or if it can still be canceled
146
- * @return
147
- */
148
- onClientMismatch?: (
149
- status: ClientMismatch | MessageSendingStatus,
150
- wasSent: boolean,
151
- ) => void | boolean | Promise<boolean>;
152
- }
153
-
154
- export class ConversationService {
155
- public readonly messageTimer: MessageTimer;
156
- public readonly messageBuilder: MessageBuilder;
157
- private readonly messageService: MessageService;
158
-
159
- constructor(
160
- private readonly apiClient: APIClient,
161
- cryptographyService: CryptographyService,
162
- private readonly assetService: AssetService,
163
- ) {
164
- this.messageTimer = new MessageTimer();
165
- this.messageBuilder = new MessageBuilder(this.apiClient, this.assetService);
166
- this.messageService = new MessageService(this.apiClient, cryptographyService);
167
- }
168
-
169
- private createEphemeral(originalGenericMessage: GenericMessage, expireAfterMillis: number): GenericMessage {
170
- const ephemeralMessage = Ephemeral.create({
171
- expireAfterMillis,
172
- [originalGenericMessage.content!]: originalGenericMessage[originalGenericMessage.content!],
173
- });
174
-
175
- const genericMessage = GenericMessage.create({
176
- [GenericMessageType.EPHEMERAL]: ephemeralMessage,
177
- messageId: originalGenericMessage.messageId,
178
- });
179
-
180
- return genericMessage;
181
- }
182
-
183
- private async getConversationQualifiedMembers(conversationId: QualifiedId): Promise<QualifiedId[]> {
184
- const conversation = await this.apiClient.conversation.api.getConversation(conversationId, true);
185
- /*
186
- * If you are sending a message to a conversation, you have to include
187
- * yourself in the list of users if you want to sync a message also to your
188
- * other clients.
189
- */
190
- return (
191
- conversation.members.others
192
- .filter(member => !!member.qualified_id)
193
- .map(member => member.qualified_id!)
194
- // TODO(Federation): Use 'domain' from 'conversation.members.self' when backend has it implemented
195
- .concat({domain: this.apiClient.context!.domain!, id: conversation.members.self.id})
196
- );
197
- }
198
-
199
- /**
200
- * Will generate a prekey bundle for specific users.
201
- * If a QualifiedId array is given the bundle will contain all the clients from those users fetched from the server.
202
- * If a QualifiedUserClients is provided then only the clients in the payload will be targeted (which could generate a ClientMismatch when sending messages)
203
- *
204
- * @param {QualifiedId[]|QualifiedUserClients} userIds - Targeted users.
205
- * @returns {Promise<QualifiedUserPreKeyBundleMap}
206
- */
207
- private async getQualifiedPreKeyBundle(
208
- userIds: QualifiedId[] | QualifiedUserClients,
209
- ): Promise<QualifiedUserPreKeyBundleMap> {
210
- type Target = {id: QualifiedId; clients?: string[]};
211
- let targets: Target[] = [];
212
-
213
- if (userIds) {
214
- if (isQualifiedIdArray(userIds)) {
215
- targets = userIds.map(id => ({id}));
216
- } else {
217
- targets = Object.entries(userIds).reduce<Target[]>((accumulator, [domain, userClients]) => {
218
- for (const userId in userClients) {
219
- accumulator.push({id: {id: userId, domain}, clients: userClients[userId]});
220
- }
221
- return accumulator;
222
- }, []);
223
- }
224
- }
225
-
226
- const preKeys = await Promise.all(
227
- targets.map(async ({id: userId, clients}) => {
228
- const prekeyBundle = await this.apiClient.user.api.getUserPreKeys(userId);
229
- // We filter the clients that should not receive the message (if a QualifiedUserClients was given as parameter)
230
- const userClients = clients
231
- ? prekeyBundle.clients.filter(client => clients.includes(client.client))
232
- : prekeyBundle.clients;
233
- return {user: userId, clients: userClients};
234
- }),
235
- );
236
-
237
- return preKeys.reduce<QualifiedUserPreKeyBundleMap>((bundleMap, qualifiedPrekey) => {
238
- bundleMap[qualifiedPrekey.user.domain] ||= {};
239
- for (const client of qualifiedPrekey.clients) {
240
- bundleMap[qualifiedPrekey.user.domain][qualifiedPrekey.user.id] ||= {};
241
- bundleMap[qualifiedPrekey.user.domain][qualifiedPrekey.user.id][client.client] = client.prekey;
242
- }
243
- return bundleMap;
244
- }, {});
245
- }
246
-
247
- async getPreKeyBundleMap(conversationId: string, userIds?: string[] | UserClients): Promise<UserPreKeyBundleMap> {
248
- let members: string[] = [];
249
-
250
- if (userIds) {
251
- if (isStringArray(userIds)) {
252
- members = userIds;
253
- } else if (isUserClients(userIds)) {
254
- members = Object.keys(userIds);
255
- }
256
- }
257
-
258
- if (!members.length) {
259
- const conversation = await this.apiClient.conversation.api.getConversation(conversationId);
260
- /*
261
- * If you are sending a message to a conversation, you have to include
262
- * yourself in the list of users if you want to sync a message also to your
263
- * other clients.
264
- */
265
- members = conversation.members.others.map(member => member.id).concat(conversation.members.self.id);
266
- }
267
-
268
- const preKeys = await Promise.all(members.map(member => this.apiClient.user.api.getUserPreKeys(member)));
269
-
270
- return preKeys.reduce((bundleMap: UserPreKeyBundleMap, bundle) => {
271
- const userId = bundle.user;
272
- bundleMap[userId] ||= {};
273
- for (const client of bundle.clients) {
274
- bundleMap[userId][client.client] = client.prekey;
275
- }
276
- return bundleMap;
277
- }, {});
278
- }
279
-
280
- private getSelfConversation(): Promise<Conversation> {
281
- const {userId} = this.apiClient.context!;
282
- return this.apiClient.conversation.api.getConversation(userId);
283
- }
284
-
285
- private async getQualifiedRecipientsForConversation(
286
- conversationId: QualifiedId,
287
- userIds?: QualifiedId[] | QualifiedUserClients,
288
- ): Promise<QualifiedUserClients | QualifiedUserPreKeyBundleMap> {
289
- if (isQualifiedUserClients(userIds)) {
290
- return userIds;
291
- }
292
- const recipientIds = userIds || (await this.getConversationQualifiedMembers(conversationId));
293
- return this.getQualifiedPreKeyBundle(recipientIds);
294
- }
295
-
296
- private async getRecipientsForConversation(
297
- conversationId: string,
298
- userIds?: string[] | UserClients,
299
- ): Promise<UserClients | UserPreKeyBundleMap> {
300
- if (isUserClients(userIds)) {
301
- return userIds;
302
- }
303
- return this.getPreKeyBundleMap(conversationId, userIds);
304
- }
305
-
306
- /**
307
- * Sends a message to a conversation
308
- *
309
- * @param sendingClientId The clientId from which the message is sent
310
- * @param conversationId The conversation in which to send the message
311
- * @param genericMessage The payload of the message to send
312
- * @return Resolves with the message sending status from backend
313
- */
314
- private async sendGenericMessage(
315
- sendingClientId: string,
316
- conversationId: string,
317
- genericMessage: GenericMessage,
318
- {
319
- conversationDomain,
320
- userIds,
321
- nativePush,
322
- sendAsProtobuf,
323
- onClientMismatch,
324
- targetMode = MessageTargetMode.NONE,
325
- }: MessageSendingOptions = {},
326
- ) {
327
- const plainText = GenericMessage.encode(genericMessage).finish();
328
- if (targetMode !== MessageTargetMode.NONE && !userIds) {
329
- throw new Error('Cannot send targetted message when no userIds are given');
330
- }
331
- if (conversationDomain) {
332
- if (isStringArray(userIds) || isUserClients(userIds)) {
333
- throw new Error('Invalid userIds option for sending to federated backend');
334
- }
335
- const recipients = await this.getQualifiedRecipientsForConversation(
336
- {id: conversationId, domain: conversationDomain},
337
- userIds,
338
- );
339
- let reportMissing;
340
- if (targetMode === MessageTargetMode.NONE) {
341
- reportMissing = isQualifiedUserClients(userIds); // we want to check mismatch in case the consumer gave an exact list of users/devices
342
- } else if (targetMode === MessageTargetMode.USERS) {
343
- reportMissing = this.extractQualifiedUserIds(userIds);
344
- } else {
345
- // in case the message is fully targetted at user/client pairs, we do not want to report the missing clients or users at all
346
- reportMissing = false;
347
- }
348
- return this.messageService.sendFederatedMessage(sendingClientId, recipients, plainText, {
349
- conversationId: {id: conversationId, domain: conversationDomain},
350
- nativePush,
351
- reportMissing,
352
- onClientMismatch: mismatch => onClientMismatch?.(mismatch, false),
353
- });
354
- }
355
-
356
- if (isQualifiedIdArray(userIds) || isQualifiedUserClients(userIds)) {
357
- throw new Error('Invalid userIds option for sending');
358
- }
359
- const recipients = await this.getRecipientsForConversation(conversationId, userIds);
360
- let reportMissing;
361
- if (targetMode === MessageTargetMode.NONE) {
362
- reportMissing = isUserClients(userIds); // we want to check mismatch in case the consumer gave an exact list of users/devices
363
- } else if (targetMode === MessageTargetMode.USERS) {
364
- reportMissing = this.extractUserIds(userIds);
365
- } else {
366
- // in case the message is fully targetted at user/client pairs, we do not want to report the missing clients or users at all
367
- reportMissing = false;
368
- }
369
- return this.messageService.sendMessage(sendingClientId, recipients, plainText, {
370
- conversationId,
371
- sendAsProtobuf,
372
- nativePush,
373
- reportMissing,
374
- onClientMismatch: mistmatch => onClientMismatch?.(mistmatch, false),
375
- });
376
- }
377
-
378
- private extractUserIds(userIds?: string[] | UserClients): string[] | undefined {
379
- if (isUserClients(userIds)) {
380
- return Object.keys(userIds);
381
- }
382
- return userIds;
383
- }
384
-
385
- private extractQualifiedUserIds(userIds?: QualifiedId[] | QualifiedUserClients): QualifiedId[] | undefined {
386
- if (isQualifiedUserClients(userIds)) {
387
- return Object.entries(userIds).reduce<QualifiedId[]>((ids, [domain, userClients]) => {
388
- return ids.concat(Object.keys(userClients).map(userId => ({domain, id: userId})));
389
- }, []);
390
- }
391
- return userIds;
392
- }
393
-
394
- private generateButtonActionGenericMessage(payloadBundle: ButtonActionMessage): GenericMessage {
395
- return GenericMessage.create({
396
- [GenericMessageType.BUTTON_ACTION]: ButtonAction.create(payloadBundle.content),
397
- messageId: payloadBundle.id,
398
- });
399
- }
400
-
401
- private generateButtonActionConfirmationGenericMessage(
402
- payloadBundle: ButtonActionConfirmationMessage,
403
- ): GenericMessage {
404
- return GenericMessage.create({
405
- [GenericMessageType.BUTTON_ACTION_CONFIRMATION]: ButtonActionConfirmation.create(payloadBundle.content),
406
- messageId: payloadBundle.id,
407
- });
408
- }
409
-
410
- private generateCompositeGenericMessage(payloadBundle: CompositeMessage): GenericMessage {
411
- return GenericMessage.create({
412
- [GenericMessageType.COMPOSITE]: Composite.create(payloadBundle.content),
413
- messageId: payloadBundle.id,
414
- });
415
- }
416
-
417
- private generateConfirmationGenericMessage(payloadBundle: ConfirmationMessage): GenericMessage {
418
- const content = Confirmation.create(payloadBundle.content);
419
-
420
- return GenericMessage.create({
421
- [GenericMessageType.CONFIRMATION]: content,
422
- messageId: payloadBundle.id,
423
- });
424
- }
425
-
426
- private generateEditedTextGenericMessage(payloadBundle: EditedTextMessage): GenericMessage {
427
- const editedMessage = MessageEdit.create({
428
- replacingMessageId: payloadBundle.content.originalMessageId,
429
- text: MessageToProtoMapper.mapText(payloadBundle),
430
- });
431
-
432
- return GenericMessage.create({
433
- [GenericMessageType.EDITED]: editedMessage,
434
- messageId: payloadBundle.id,
435
- });
436
- }
437
-
438
- private generateFileDataGenericMessage(payloadBundle: FileAssetMessage): GenericMessage {
439
- if (!payloadBundle.content) {
440
- throw new Error('No content for sendFileData provided.');
441
- }
442
-
443
- const {asset, expectsReadConfirmation, legalHoldStatus} = payloadBundle.content;
444
-
445
- const remoteData = Asset.RemoteData.create({
446
- assetId: asset.key,
447
- assetToken: asset.token,
448
- otrKey: asset.keyBytes,
449
- sha256: asset.sha256,
450
- });
451
-
452
- const assetMessage = Asset.create({
453
- expectsReadConfirmation,
454
- legalHoldStatus,
455
- uploaded: remoteData,
456
- });
457
-
458
- assetMessage.status = AssetTransferState.UPLOADED;
459
-
460
- const genericMessage = GenericMessage.create({
461
- [GenericMessageType.ASSET]: assetMessage,
462
- messageId: payloadBundle.id,
463
- });
464
-
465
- const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
466
- return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
467
- }
468
-
469
- private generateFileMetaDataGenericMessage(payloadBundle: FileAssetMetaDataMessage): GenericMessage {
470
- if (!payloadBundle.content) {
471
- throw new Error('No content for sendFileMetaData provided.');
472
- }
473
-
474
- const {expectsReadConfirmation, legalHoldStatus, metaData} = payloadBundle.content;
475
-
476
- const original = Asset.Original.create({
477
- audio: metaData.audio,
478
- mimeType: metaData.type,
479
- name: metaData.name,
480
- size: metaData.length,
481
- video: metaData.video,
482
- });
483
-
484
- const assetMessage = Asset.create({
485
- expectsReadConfirmation,
486
- legalHoldStatus,
487
- original,
488
- });
489
-
490
- const genericMessage = GenericMessage.create({
491
- [GenericMessageType.ASSET]: assetMessage,
492
- messageId: payloadBundle.id,
493
- });
494
-
495
- const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
496
- return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
497
- }
498
-
499
- private generateFileAbortGenericMessage(payloadBundle: FileAssetAbortMessage): GenericMessage {
500
- if (!payloadBundle.content) {
501
- throw new Error('No content for sendFileAbort provided.');
502
- }
503
-
504
- const {expectsReadConfirmation, legalHoldStatus, reason} = payloadBundle.content;
505
-
506
- const assetMessage = Asset.create({
507
- expectsReadConfirmation,
508
- legalHoldStatus,
509
- notUploaded: reason,
510
- });
511
-
512
- assetMessage.status = AssetTransferState.NOT_UPLOADED;
513
-
514
- const genericMessage = GenericMessage.create({
515
- [GenericMessageType.ASSET]: assetMessage,
516
- messageId: payloadBundle.id,
517
- });
518
-
519
- const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
520
- return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
521
- }
522
-
523
- private generateImageGenericMessage(payloadBundle: ImageAssetMessageOutgoing): {
524
- content: AssetContent;
525
- genericMessage: GenericMessage;
526
- } {
527
- if (!payloadBundle.content) {
528
- throw new Error('No content for sendImage provided.');
529
- }
530
-
531
- const {asset, expectsReadConfirmation, image, legalHoldStatus} = payloadBundle.content;
532
-
533
- const imageMetadata = Asset.ImageMetaData.create({
534
- height: image.height,
535
- width: image.width,
536
- });
537
-
538
- const original = Asset.Original.create({
539
- [GenericMessageType.IMAGE]: imageMetadata,
540
- mimeType: image.type,
541
- name: null,
542
- size: image.data.length,
543
- });
544
-
545
- const remoteData = Asset.RemoteData.create({
546
- assetId: asset.key,
547
- assetToken: asset.token,
548
- otrKey: asset.keyBytes,
549
- sha256: asset.sha256,
550
- });
551
-
552
- const assetMessage = Asset.create({
553
- expectsReadConfirmation,
554
- legalHoldStatus,
555
- original,
556
- uploaded: remoteData,
557
- });
558
-
559
- assetMessage.status = AssetTransferState.UPLOADED;
560
-
561
- let genericMessage = GenericMessage.create({
562
- [GenericMessageType.ASSET]: assetMessage,
563
- messageId: payloadBundle.id,
564
- });
565
-
566
- const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
567
- if (expireAfterMillis) {
568
- genericMessage = this.createEphemeral(genericMessage, expireAfterMillis);
569
- }
570
- return {content: assetMessage as AssetContent, genericMessage};
571
- }
572
-
573
- private generateLocationGenericMessage(payloadBundle: LocationMessage): GenericMessage {
574
- const {expectsReadConfirmation, latitude, legalHoldStatus, longitude, name, zoom} = payloadBundle.content;
575
-
576
- const locationMessage = Location.create({
577
- expectsReadConfirmation,
578
- latitude,
579
- legalHoldStatus,
580
- longitude,
581
- name,
582
- zoom,
583
- });
584
-
585
- const genericMessage = GenericMessage.create({
586
- [GenericMessageType.LOCATION]: locationMessage,
587
- messageId: payloadBundle.id,
588
- });
589
-
590
- const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
591
- return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
592
- }
593
-
594
- private generatePingGenericMessage(payloadBundle: PingMessage): GenericMessage {
595
- const content = Knock.create(payloadBundle.content);
596
-
597
- const genericMessage = GenericMessage.create({
598
- [GenericMessageType.KNOCK]: content,
599
- messageId: payloadBundle.id,
600
- });
601
-
602
- const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
603
- return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
604
- }
605
-
606
- private generateReactionGenericMessage(payloadBundle: ReactionMessage): GenericMessage {
607
- const {legalHoldStatus, originalMessageId, type} = payloadBundle.content;
608
-
609
- const reaction = Reaction.create({
610
- emoji: type,
611
- legalHoldStatus,
612
- messageId: originalMessageId,
613
- });
614
-
615
- const genericMessage = GenericMessage.create({
616
- [GenericMessageType.REACTION]: reaction,
617
- messageId: payloadBundle.id,
618
- });
619
- return genericMessage;
620
- }
621
-
622
- private generateSessionResetGenericMessage(payloadBundle: ResetSessionMessage): GenericMessage {
623
- return GenericMessage.create({
624
- [GenericMessageType.CLIENT_ACTION]: ClientAction.RESET_SESSION,
625
- messageId: payloadBundle.id,
626
- });
627
- }
628
-
629
- private generateCallGenericMessage(payloadBundle: CallMessage): GenericMessage {
630
- const callMessage = Calling.create({
631
- content: payloadBundle.content,
632
- });
633
-
634
- return GenericMessage.create({
635
- [GenericMessageType.CALLING]: callMessage,
636
- messageId: payloadBundle.id,
637
- });
638
- }
639
-
640
- private generateTextGenericMessage(payloadBundle: TextMessage): GenericMessage {
641
- const genericMessage = GenericMessage.create({
642
- messageId: payloadBundle.id,
643
- [GenericMessageType.TEXT]: MessageToProtoMapper.mapText(payloadBundle),
644
- });
645
-
646
- const expireAfterMillis = this.messageTimer.getMessageTimer(payloadBundle.conversation);
647
- return expireAfterMillis > 0 ? this.createEphemeral(genericMessage, expireAfterMillis) : genericMessage;
648
- }
649
-
650
- public async clearConversation(
651
- conversationId: string,
652
- timestamp: number | Date = new Date(),
653
- messageId: string = MessageBuilder.createId(),
654
- sendAsProtobuf?: boolean,
655
- conversationDomain?: string,
656
- ): Promise<ClearConversationMessage> {
657
- if (timestamp instanceof Date) {
658
- timestamp = timestamp.getTime();
659
- }
660
-
661
- const content: ClearedContent = {
662
- clearedTimestamp: timestamp,
663
- conversationId,
664
- };
665
-
666
- const clearedMessage = Cleared.create(content);
667
-
668
- const genericMessage = GenericMessage.create({
669
- [GenericMessageType.CLEARED]: clearedMessage,
670
- messageId,
671
- });
672
-
673
- const {id: selfConversationId} = await this.getSelfConversation();
674
-
675
- await this.sendGenericMessage(this.apiClient.validatedClientId, selfConversationId, genericMessage, {
676
- conversationDomain,
677
- sendAsProtobuf,
678
- });
679
-
680
- return {
681
- content,
682
- conversation: conversationId,
683
- from: this.apiClient.context!.userId,
684
- id: messageId,
685
- messageTimer: 0,
686
- source: PayloadBundleSource.LOCAL,
687
- state: PayloadBundleState.OUTGOING_SENT,
688
- timestamp: Date.now(),
689
- type: PayloadBundleType.CONVERSATION_CLEAR,
690
- };
691
- }
692
-
693
- public async deleteMessageLocal(
694
- conversationId: string,
695
- messageIdToHide: string,
696
- sendAsProtobuf?: boolean,
697
- conversationDomain?: string,
698
- ): Promise<HideMessage> {
699
- const messageId = MessageBuilder.createId();
700
-
701
- const content: HiddenContent = MessageHide.create({
702
- conversationId,
703
- messageId: messageIdToHide,
704
- });
705
-
706
- const genericMessage = GenericMessage.create({
707
- [GenericMessageType.HIDDEN]: content,
708
- messageId,
709
- });
710
-
711
- const {id: selfConversationId} = await this.getSelfConversation();
712
-
713
- await this.sendGenericMessage(this.apiClient.validatedClientId, selfConversationId, genericMessage, {
714
- sendAsProtobuf,
715
- conversationDomain,
716
- });
717
-
718
- return {
719
- content,
720
- conversation: conversationId,
721
- from: this.apiClient.context!.userId,
722
- id: messageId,
723
- messageTimer: this.messageTimer.getMessageTimer(conversationId),
724
- source: PayloadBundleSource.LOCAL,
725
- state: PayloadBundleState.OUTGOING_SENT,
726
- timestamp: Date.now(),
727
- type: PayloadBundleType.MESSAGE_HIDE,
728
- };
729
- }
730
-
731
- public async deleteMessageEveryone(
732
- conversationId: string,
733
- messageIdToDelete: string,
734
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients,
735
- sendAsProtobuf?: boolean,
736
- conversationDomain?: string,
737
- callbacks?: MessageSendingCallbacks,
738
- ): Promise<DeleteMessage> {
739
- const messageId = MessageBuilder.createId();
740
-
741
- const content: DeletedContent = MessageDelete.create({
742
- messageId: messageIdToDelete,
743
- });
744
-
745
- const genericMessage = GenericMessage.create({
746
- [GenericMessageType.DELETED]: content,
747
- messageId,
748
- });
749
- callbacks?.onStart?.(genericMessage);
750
-
751
- const response = await this.sendGenericMessage(this.apiClient.validatedClientId, conversationId, genericMessage, {
752
- userIds,
753
- sendAsProtobuf,
754
- conversationDomain,
755
- });
756
- callbacks?.onSuccess?.(genericMessage, response?.time);
757
-
758
- return {
759
- content,
760
- conversation: conversationId,
761
- from: this.apiClient.context!.userId,
762
- id: messageId,
763
- messageTimer: this.messageTimer.getMessageTimer(conversationId),
764
- source: PayloadBundleSource.LOCAL,
765
- state: PayloadBundleState.OUTGOING_SENT,
766
- timestamp: Date.now(),
767
- type: PayloadBundleType.MESSAGE_DELETE,
768
- };
769
- }
770
-
771
- public leaveConversation(conversationId: string): Promise<ConversationMemberLeaveEvent> {
772
- return this.apiClient.conversation.api.deleteMember(conversationId, this.apiClient.context!.userId);
773
- }
774
-
775
- public async leaveConversations(conversationIds?: string[]): Promise<ConversationMemberLeaveEvent[]> {
776
- if (!conversationIds) {
777
- const conversation = await this.getConversations();
778
- conversationIds = conversation
779
- .filter(conversation => conversation.type === CONVERSATION_TYPE.REGULAR)
780
- .map(conversation => conversation.id);
781
- }
782
-
783
- return Promise.all(conversationIds.map(conversationId => this.leaveConversation(conversationId)));
784
- }
785
-
786
- public createConversation(name: string, otherUserIds: string | string[] = []): Promise<Conversation> {
787
- const ids = typeof otherUserIds === 'string' ? [otherUserIds] : otherUserIds;
788
-
789
- const newConversation: NewConversation = {
790
- name,
791
- receipt_mode: null,
792
- users: ids,
793
- };
794
-
795
- return this.apiClient.conversation.api.postConversation(newConversation);
796
- }
797
-
798
- public async getConversations(conversationId: string): Promise<Conversation>;
799
- public async getConversations(conversationIds?: string[]): Promise<Conversation[]>;
800
- public async getConversations(conversationIds?: string | string[]): Promise<Conversation[] | Conversation> {
801
- if (!conversationIds || !conversationIds.length) {
802
- return this.apiClient.conversation.api.getAllConversations();
803
- }
804
- if (typeof conversationIds === 'string') {
805
- return this.apiClient.conversation.api.getConversation(conversationIds);
806
- }
807
- return this.apiClient.conversation.api.getConversationsByIds(conversationIds);
808
- }
809
-
810
- public async getAsset({assetId, assetToken, otrKey, sha256}: RemoteData): Promise<Buffer> {
811
- const request = await this.apiClient.asset.api.getAssetV3(assetId, assetToken);
812
- const encryptedBuffer = (await request.response).buffer;
813
-
814
- return AssetCryptography.decryptAsset({
815
- cipherText: Buffer.from(encryptedBuffer),
816
- keyBytes: Buffer.from(otrKey),
817
- sha256: Buffer.from(sha256),
818
- });
819
- }
820
-
821
- public async getUnencryptedAsset(assetId: string, assetToken?: string): Promise<ArrayBuffer> {
822
- const request = await this.apiClient.asset.api.getAssetV3(assetId, assetToken);
823
- return (await request.response).buffer;
824
- }
825
-
826
- public async addUser<T extends string | string[] | QualifiedId | QualifiedId[]>(
827
- conversationId: string,
828
- userIds: T,
829
- ): Promise<T> {
830
- const ids = Array.isArray(userIds) ? userIds : [userIds];
831
- if (isStringArray(ids)) {
832
- await this.apiClient.conversation.api.postMembers(conversationId, ids);
833
- } else if (isQualifiedIdArray(ids)) {
834
- await this.apiClient.conversation.api.postMembersV2(conversationId, ids);
835
- }
836
-
837
- return userIds;
838
- }
839
-
840
- public async removeUser(conversationId: string, userId: string): Promise<string> {
841
- await this.apiClient.conversation.api.deleteMember(conversationId, userId);
842
- return userId;
843
- }
844
-
845
- /**
846
- * Sends a message to a conversation
847
- *
848
- * @param params.payloadBundle The message to send to the conversation
849
- * @param params.userIds? Can be either a QualifiedId[], string[], UserClients or QualfiedUserClients. The type has some effect on the behavior of the method.
850
- * 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
851
- * 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)
852
- * When given a QualifiedId[] or QualifiedUserClients the method will send the message through the federated API endpoint
853
- * When given a string[] or UserClients the method will send the message through the old API endpoint
854
- * @return resolves with the sent message
855
- */
856
- public async send<T extends OtrMessage = OtrMessage>({
857
- payloadBundle,
858
- userIds,
859
- sendAsProtobuf,
860
- conversationDomain,
861
- nativePush,
862
- targetMode,
863
- callbacks,
864
- }: {
865
- payloadBundle: T;
866
- userIds?: string[] | QualifiedId[] | UserClients | QualifiedUserClients;
867
- callbacks?: MessageSendingCallbacks;
868
- } & MessageSendingOptions): Promise<T> {
869
- let genericMessage: GenericMessage;
870
- let processedContent: AssetContent | undefined = undefined;
871
-
872
- switch (payloadBundle.type) {
873
- case PayloadBundleType.ASSET:
874
- genericMessage = this.generateFileDataGenericMessage(payloadBundle);
875
- break;
876
- case PayloadBundleType.ASSET_ABORT:
877
- genericMessage = this.generateFileAbortGenericMessage(payloadBundle);
878
- break;
879
- case PayloadBundleType.ASSET_META:
880
- genericMessage = this.generateFileMetaDataGenericMessage(payloadBundle);
881
- break;
882
- case PayloadBundleType.ASSET_IMAGE:
883
- const res = this.generateImageGenericMessage(payloadBundle as ImageAssetMessageOutgoing);
884
- genericMessage = res.genericMessage;
885
- processedContent = res.content;
886
- break;
887
- case PayloadBundleType.BUTTON_ACTION:
888
- genericMessage = this.generateButtonActionGenericMessage(payloadBundle);
889
- break;
890
- case PayloadBundleType.BUTTON_ACTION_CONFIRMATION:
891
- genericMessage = this.generateButtonActionConfirmationGenericMessage(payloadBundle);
892
- break;
893
- case PayloadBundleType.CALL:
894
- genericMessage = this.generateCallGenericMessage(payloadBundle);
895
- break;
896
- case PayloadBundleType.CLIENT_ACTION: {
897
- if (payloadBundle.content.clientAction !== ClientAction.RESET_SESSION) {
898
- throw new Error(
899
- `No send method implemented for "${payloadBundle.type}" and ClientAction "${payloadBundle.content}".`,
900
- );
901
- }
902
- genericMessage = this.generateSessionResetGenericMessage(payloadBundle);
903
- break;
904
- }
905
- case PayloadBundleType.COMPOSITE:
906
- genericMessage = this.generateCompositeGenericMessage(payloadBundle);
907
- break;
908
- case PayloadBundleType.CONFIRMATION:
909
- genericMessage = this.generateConfirmationGenericMessage(payloadBundle);
910
- break;
911
- case PayloadBundleType.LOCATION:
912
- genericMessage = this.generateLocationGenericMessage(payloadBundle);
913
- break;
914
- case PayloadBundleType.MESSAGE_EDIT:
915
- genericMessage = this.generateEditedTextGenericMessage(payloadBundle);
916
- break;
917
- case PayloadBundleType.PING:
918
- genericMessage = this.generatePingGenericMessage(payloadBundle);
919
- break;
920
- case PayloadBundleType.REACTION:
921
- genericMessage = this.generateReactionGenericMessage(payloadBundle);
922
- break;
923
- case PayloadBundleType.TEXT:
924
- genericMessage = this.generateTextGenericMessage(payloadBundle);
925
- break;
926
- default:
927
- throw new Error(`No send method implemented for "${payloadBundle['type']}".`);
928
- }
929
-
930
- if ((await callbacks?.onStart?.(genericMessage)) === false) {
931
- // If the onStart call returns false, it means the consumer wants to cancel the message sending
932
- return {...payloadBundle, state: PayloadBundleState.CANCELLED};
933
- }
934
-
935
- const response = await this.sendGenericMessage(
936
- this.apiClient.validatedClientId,
937
- payloadBundle.conversation,
938
- genericMessage,
939
- {
940
- userIds,
941
- sendAsProtobuf,
942
- conversationDomain,
943
- nativePush,
944
- targetMode,
945
- onClientMismatch: callbacks?.onClientMismatch,
946
- },
947
- );
948
-
949
- if (!response.errored) {
950
- callbacks?.onSuccess?.(genericMessage, response.time);
951
- if (!this.isClearFromMismatch(response)) {
952
- // We warn the consumer that there is a mismatch that did not prevent message sending
953
- callbacks?.onClientMismatch?.(response, true);
954
- }
955
- }
956
-
957
- return {
958
- ...payloadBundle,
959
- content: processedContent || payloadBundle.content,
960
- messageTimer: genericMessage.ephemeral?.expireAfterMillis || 0,
961
- state: response.errored ? PayloadBundleState.CANCELLED : PayloadBundleState.OUTGOING_SENT,
962
- };
963
- }
964
-
965
- public sendTypingStart(conversationId: string): Promise<void> {
966
- return this.apiClient.conversation.api.postTyping(conversationId, {status: CONVERSATION_TYPING.STARTED});
967
- }
968
-
969
- public sendTypingStop(conversationId: string): Promise<void> {
970
- return this.apiClient.conversation.api.postTyping(conversationId, {status: CONVERSATION_TYPING.STOPPED});
971
- }
972
-
973
- public setConversationMutedStatus(
974
- conversationId: string,
975
- status: MutedStatus,
976
- muteTimestamp: number | Date,
977
- ): Promise<void> {
978
- if (typeof muteTimestamp === 'number') {
979
- muteTimestamp = new Date(muteTimestamp);
980
- }
981
-
982
- const payload: ConversationMemberUpdateData = {
983
- otr_muted_ref: muteTimestamp.toISOString(),
984
- otr_muted_status: status,
985
- };
986
-
987
- return this.apiClient.conversation.api.putMembershipProperties(conversationId, payload);
988
- }
989
-
990
- public toggleArchiveConversation(
991
- conversationId: string,
992
- archived: boolean,
993
- archiveTimestamp: number | Date = new Date(),
994
- ): Promise<void> {
995
- if (typeof archiveTimestamp === 'number') {
996
- archiveTimestamp = new Date(archiveTimestamp);
997
- }
998
-
999
- const payload: ConversationMemberUpdateData = {
1000
- otr_archived: archived,
1001
- otr_archived_ref: archiveTimestamp.toISOString(),
1002
- };
1003
-
1004
- return this.apiClient.conversation.api.putMembershipProperties(conversationId, payload);
1005
- }
1006
-
1007
- public setMemberConversationRole(
1008
- conversationId: string,
1009
- userId: string,
1010
- conversationRole: DefaultConversationRoleName | string,
1011
- ): Promise<void> {
1012
- return this.apiClient.conversation.api.putOtherMember(userId, conversationId, {
1013
- conversation_role: conversationRole,
1014
- });
1015
- }
1016
-
1017
- private isClearFromMismatch(mismatch: ClientMismatch | MessageSendingStatus): boolean {
1018
- const hasMissing = Object.keys(mismatch.missing || {}).length > 0;
1019
- const hasDeleted = Object.keys(mismatch.deleted || {}).length > 0;
1020
- const hasRedundant = Object.keys(mismatch.redundant || {}).length > 0;
1021
- const hasFailed = Object.keys((mismatch as MessageSendingStatus).failed_to_send || {}).length > 0;
1022
- return !hasMissing && !hasDeleted && !hasRedundant && !hasFailed;
1023
- }
1024
- }