agora-appbuilder-core 4.1.8 → 4.1.9-beta.2

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.
@@ -0,0 +1,540 @@
1
+ /*
2
+ ********************************************
3
+ Copyright © 2021 Agora Lab, Inc., all rights reserved.
4
+ AppBuilder and all associated components, source code, APIs, services, and documentation
5
+ (the “Materials”) are owned by Agora Lab, Inc. and its licensors. The Materials may not be
6
+ accessed, used, modified, or distributed for any purpose without a license from Agora Lab, Inc.
7
+ Use without a license or in violation of any license terms and conditions (including use for
8
+ any purpose competitive to Agora Lab, Inc.’s business) is strictly prohibited. For more
9
+ information visit https://appbuilder.agora.io.
10
+ *********************************************
11
+ */
12
+ // @ts-nocheck
13
+ import {
14
+ ChannelAttributeOptions,
15
+ RtmAttribute,
16
+ RtmChannelAttribute,
17
+ Subscription,
18
+ } from 'agora-react-native-rtm/lib/typescript/src';
19
+ import {RtmClientEvents} from 'agora-react-native-rtm/lib/typescript/src/RtmEngine';
20
+ import AgoraRTM, {VERSION} from 'agora-rtm-sdk';
21
+ import RtmClient from 'agora-react-native-rtm';
22
+ import {LogSource, logger} from '../../../src/logger/AppBuilderLogger';
23
+ // export {RtmAttribute}
24
+ //
25
+ interface RtmAttributePlaceholder {}
26
+ export {RtmAttributePlaceholder as RtmAttribute};
27
+
28
+ type callbackType = (args?: any) => void;
29
+
30
+ export default class RtmEngine {
31
+ public appId: string;
32
+ public client: RtmClient;
33
+ public channelMap = new Map<string, any>([]);
34
+ public remoteInvititations = new Map<string, any>([]);
35
+ public localInvititations = new Map<string, any>([]);
36
+ public channelEventsMap = new Map<string, any>([
37
+ ['channelMessageReceived', () => null],
38
+ ['channelMemberJoined', () => null],
39
+ ['channelMemberLeft', () => null],
40
+ ]);
41
+ public clientEventsMap = new Map<string, any>([
42
+ ['connectionStateChanged', () => null],
43
+ ['messageReceived', () => null],
44
+ ['remoteInvitationReceived', () => null],
45
+ ['tokenExpired', () => null],
46
+ ]);
47
+ public localInvitationEventsMap = new Map<string, any>([
48
+ ['localInvitationAccepted', () => null],
49
+ ['localInvitationCanceled', () => null],
50
+ ['localInvitationFailure', () => null],
51
+ ['localInvitationReceivedByPeer', () => null],
52
+ ['localInvitationRefused', () => null],
53
+ ]);
54
+ public remoteInvitationEventsMap = new Map<string, any>([
55
+ ['remoteInvitationAccepted', () => null],
56
+ ['remoteInvitationCanceled', () => null],
57
+ ['remoteInvitationFailure', () => null],
58
+ ['remoteInvitationRefused', () => null],
59
+ ]);
60
+ constructor() {
61
+ this.appId = '';
62
+ logger.debug(LogSource.AgoraSDK, 'Log', 'Using RTM Bridge');
63
+ }
64
+
65
+ on(event: any, listener: any) {
66
+ if (
67
+ event === 'channelMessageReceived' ||
68
+ event === 'channelMemberJoined' ||
69
+ event === 'channelMemberLeft'
70
+ ) {
71
+ this.channelEventsMap.set(event, listener);
72
+ } else if (
73
+ event === 'connectionStateChanged' ||
74
+ event === 'messageReceived' ||
75
+ event === 'remoteInvitationReceived' ||
76
+ event === 'tokenExpired'
77
+ ) {
78
+ this.clientEventsMap.set(event, listener);
79
+ } else if (
80
+ event === 'localInvitationAccepted' ||
81
+ event === 'localInvitationCanceled' ||
82
+ event === 'localInvitationFailure' ||
83
+ event === 'localInvitationReceivedByPeer' ||
84
+ event === 'localInvitationRefused'
85
+ ) {
86
+ this.localInvitationEventsMap.set(event, listener);
87
+ } else if (
88
+ event === 'remoteInvitationAccepted' ||
89
+ event === 'remoteInvitationCanceled' ||
90
+ event === 'remoteInvitationFailure' ||
91
+ event === 'remoteInvitationRefused'
92
+ ) {
93
+ this.remoteInvitationEventsMap.set(event, listener);
94
+ }
95
+ }
96
+
97
+ createClient(APP_ID: string) {
98
+ this.appId = APP_ID;
99
+ this.client = AgoraRTM.createInstance(this.appId);
100
+
101
+ if ($config.GEO_FENCING) {
102
+ try {
103
+ //include area is comma seperated value
104
+ let includeArea = $config.GEO_FENCING_INCLUDE_AREA
105
+ ? $config.GEO_FENCING_INCLUDE_AREA
106
+ : AREAS.GLOBAL;
107
+
108
+ //exclude area is single value
109
+ let excludeArea = $config.GEO_FENCING_EXCLUDE_AREA
110
+ ? $config.GEO_FENCING_EXCLUDE_AREA
111
+ : '';
112
+
113
+ includeArea = includeArea?.split(',');
114
+
115
+ //pass excludedArea if only its provided
116
+ if (excludeArea) {
117
+ AgoraRTM.setArea({
118
+ areaCodes: includeArea,
119
+ excludedArea: excludeArea,
120
+ });
121
+ }
122
+ //otherwise we can pass area directly
123
+ else {
124
+ AgoraRTM.setArea({areaCodes: includeArea});
125
+ }
126
+ } catch (setAeraError) {
127
+ console.log('error on RTM setArea', setAeraError);
128
+ }
129
+ }
130
+
131
+ window.rtmClient = this.client;
132
+
133
+ this.client.on('ConnectionStateChanged', (state, reason) => {
134
+ this.clientEventsMap.get('connectionStateChanged')({state, reason});
135
+ });
136
+
137
+ this.client.on('MessageFromPeer', (msg, uid, msgProps) => {
138
+ this.clientEventsMap.get('messageReceived')({
139
+ text: msg.text,
140
+ ts: msgProps.serverReceivedTs,
141
+ offline: msgProps.isOfflineMessage,
142
+ peerId: uid,
143
+ });
144
+ });
145
+
146
+ this.client.on('RemoteInvitationReceived', (remoteInvitation: any) => {
147
+ this.remoteInvititations.set(remoteInvitation.callerId, remoteInvitation);
148
+ this.clientEventsMap.get('remoteInvitationReceived')({
149
+ callerId: remoteInvitation.callerId,
150
+ content: remoteInvitation.content,
151
+ state: remoteInvitation.state,
152
+ channelId: remoteInvitation.channelId,
153
+ response: remoteInvitation.response,
154
+ });
155
+
156
+ remoteInvitation.on('RemoteInvitationAccepted', () => {
157
+ this.remoteInvitationEventsMap.get('RemoteInvitationAccepted')({
158
+ callerId: remoteInvitation.callerId,
159
+ content: remoteInvitation.content,
160
+ state: remoteInvitation.state,
161
+ channelId: remoteInvitation.channelId,
162
+ response: remoteInvitation.response,
163
+ });
164
+ });
165
+
166
+ remoteInvitation.on('RemoteInvitationCanceled', (content: string) => {
167
+ this.remoteInvitationEventsMap.get('remoteInvitationCanceled')({
168
+ callerId: remoteInvitation.callerId,
169
+ content: content,
170
+ state: remoteInvitation.state,
171
+ channelId: remoteInvitation.channelId,
172
+ response: remoteInvitation.response,
173
+ });
174
+ });
175
+
176
+ remoteInvitation.on('RemoteInvitationFailure', (reason: string) => {
177
+ this.remoteInvitationEventsMap.get('remoteInvitationFailure')({
178
+ callerId: remoteInvitation.callerId,
179
+ content: remoteInvitation.content,
180
+ state: remoteInvitation.state,
181
+ channelId: remoteInvitation.channelId,
182
+ response: remoteInvitation.response,
183
+ code: -1, //Web sends string, RN expect number but can't find enum
184
+ });
185
+ });
186
+
187
+ remoteInvitation.on('RemoteInvitationRefused', () => {
188
+ this.remoteInvitationEventsMap.get('remoteInvitationRefused')({
189
+ callerId: remoteInvitation.callerId,
190
+ content: remoteInvitation.content,
191
+ state: remoteInvitation.state,
192
+ channelId: remoteInvitation.channelId,
193
+ response: remoteInvitation.response,
194
+ });
195
+ });
196
+ });
197
+
198
+ this.client.on('TokenExpired', () => {
199
+ this.clientEventsMap.get('tokenExpired')({}); //RN expect evt: any
200
+ });
201
+ }
202
+
203
+ async login(loginParam: {uid: string; token?: string}): Promise<any> {
204
+ return this.client.login(loginParam);
205
+ }
206
+
207
+ async logout(): Promise<any> {
208
+ return await this.client.logout();
209
+ }
210
+
211
+ async joinChannel(channelId: string): Promise<any> {
212
+ this.channelMap.set(channelId, this.client.createChannel(channelId));
213
+ this.channelMap
214
+ .get(channelId)
215
+ .on('ChannelMessage', (msg: {text: string}, uid: string, messagePros) => {
216
+ let text = msg.text;
217
+ let ts = messagePros.serverReceivedTs;
218
+ this.channelEventsMap.get('channelMessageReceived')({
219
+ uid,
220
+ channelId,
221
+ text,
222
+ ts,
223
+ });
224
+ });
225
+ this.channelMap.get(channelId).on('MemberJoined', (uid: string) => {
226
+ this.channelEventsMap.get('channelMemberJoined')({uid, channelId});
227
+ });
228
+ this.channelMap.get(channelId).on('MemberLeft', (uid: string) => {
229
+ console.log('Member Left', this.channelEventsMap);
230
+ this.channelEventsMap.get('channelMemberLeft')({uid});
231
+ });
232
+ this.channelMap
233
+ .get(channelId)
234
+ .on('AttributesUpdated', (attributes: RtmChannelAttribute) => {
235
+ /**
236
+ * a) Kindly note the below event listener 'channelAttributesUpdated' expects type
237
+ * RtmChannelAttribute[] (array of objects [{key: 'valueOfKey', value: 'valueOfValue}])
238
+ * whereas the above listener 'AttributesUpdated' receives attributes in object form
239
+ * {[valueOfKey]: valueOfValue} of type RtmChannelAttribute
240
+ * b) Hence in this bridge the data should be modified to keep in sync with both the
241
+ * listeners for web and listener for native
242
+ */
243
+ /**
244
+ * 1. Loop through object
245
+ * 2. Create a object {key: "", value: ""} and push into array
246
+ * 3. Return the Array
247
+ */
248
+ const channelAttributes = Object.keys(attributes).reduce((acc, key) => {
249
+ const {value, lastUpdateTs, lastUpdateUserId} = attributes[key];
250
+ acc.push({key, value, lastUpdateTs, lastUpdateUserId});
251
+ return acc;
252
+ }, []);
253
+
254
+ this.channelEventsMap.get('ChannelAttributesUpdated')(
255
+ channelAttributes,
256
+ );
257
+ });
258
+
259
+ return this.channelMap.get(channelId).join();
260
+ }
261
+
262
+ async leaveChannel(channelId: string): Promise<any> {
263
+ if (this.channelMap.get(channelId)) {
264
+ return this.channelMap.get(channelId).leave();
265
+ } else {
266
+ Promise.reject('Wrong channel');
267
+ }
268
+ }
269
+
270
+ async sendMessageByChannelId(channel: string, message: string): Promise<any> {
271
+ if (this.channelMap.get(channel)) {
272
+ return this.channelMap.get(channel).sendMessage({text: message});
273
+ } else {
274
+ console.log(this.channelMap, channel);
275
+ Promise.reject('Wrong channel');
276
+ }
277
+ }
278
+
279
+ destroyClient() {
280
+ console.log('Destroy called');
281
+ this.channelEventsMap.forEach((callback, event) => {
282
+ this.client.off(event, callback);
283
+ });
284
+ this.channelEventsMap.clear();
285
+ this.channelMap.clear();
286
+ this.clientEventsMap.clear();
287
+ this.remoteInvitationEventsMap.clear();
288
+ this.localInvitationEventsMap.clear();
289
+ }
290
+
291
+ async getChannelMembersBychannelId(channel: string) {
292
+ if (this.channelMap.get(channel)) {
293
+ let memberArray: Array<any> = [];
294
+ let currentChannel = this.channelMap.get(channel);
295
+ await currentChannel.getMembers().then((arr: Array<number>) => {
296
+ arr.map((elem: number) => {
297
+ memberArray.push({
298
+ channelId: channel,
299
+ uid: elem,
300
+ });
301
+ });
302
+ });
303
+ return {members: memberArray};
304
+ } else {
305
+ Promise.reject('Wrong channel');
306
+ }
307
+ }
308
+
309
+ async queryPeersOnlineStatus(uid: Array<String>) {
310
+ let peerArray: Array<any> = [];
311
+ await this.client.queryPeersOnlineStatus(uid).then(list => {
312
+ Object.entries(list).forEach(value => {
313
+ peerArray.push({
314
+ online: value[1],
315
+ uid: value[0],
316
+ });
317
+ });
318
+ });
319
+ return {items: peerArray};
320
+ }
321
+
322
+ async renewToken(token: string) {
323
+ return this.client.renewToken(token);
324
+ }
325
+
326
+ async getUserAttributesByUid(uid: string) {
327
+ let response = {};
328
+ await this.client
329
+ .getUserAttributes(uid)
330
+ .then((attributes: string) => {
331
+ response = {attributes, uid};
332
+ })
333
+ .catch((e: any) => {
334
+ Promise.reject(e);
335
+ });
336
+ return response;
337
+ }
338
+
339
+ async getChannelAttributes(channelId: string) {
340
+ let response = {};
341
+ await this.client
342
+ .getChannelAttributes(channelId)
343
+ .then((attributes: RtmChannelAttribute) => {
344
+ /**
345
+ * Here the attributes received are in the format {[valueOfKey]: valueOfValue} of type RtmChannelAttribute
346
+ * We need to convert it into (array of objects [{key: 'valueOfKey', value: 'valueOfValue}])
347
+ /**
348
+ * 1. Loop through object
349
+ * 2. Create a object {key: "", value: ""} and push into array
350
+ * 3. Return the Array
351
+ */
352
+ const channelAttributes = Object.keys(attributes).reduce((acc, key) => {
353
+ const {value, lastUpdateTs, lastUpdateUserId} = attributes[key];
354
+ acc.push({key, value, lastUpdateTs, lastUpdateUserId});
355
+ return acc;
356
+ }, []);
357
+ response = channelAttributes;
358
+ })
359
+ .catch((e: any) => {
360
+ Promise.reject(e);
361
+ });
362
+ return response;
363
+ }
364
+
365
+ async removeAllLocalUserAttributes() {
366
+ return this.client.clearLocalUserAttributes();
367
+ }
368
+
369
+ async removeLocalUserAttributesByKeys(keys: string[]) {
370
+ return this.client.deleteLocalUserAttributesByKeys(keys);
371
+ }
372
+
373
+ async replaceLocalUserAttributes(attributes: string[]) {
374
+ let formattedAttributes: any = {};
375
+ attributes.map(attribute => {
376
+ let key = Object.values(attribute)[0];
377
+ let value = Object.values(attribute)[1];
378
+ formattedAttributes[key] = value;
379
+ });
380
+ return this.client.setLocalUserAttributes({...formattedAttributes});
381
+ }
382
+
383
+ async setLocalUserAttributes(attributes: string[]) {
384
+ let formattedAttributes: any = {};
385
+ attributes.map(attribute => {
386
+ let key = Object.values(attribute)[0];
387
+ let value = Object.values(attribute)[1];
388
+ formattedAttributes[key] = value;
389
+ // console.log('!!!!formattedAttributes', formattedAttributes, key, value);
390
+ });
391
+ return this.client.setLocalUserAttributes({...formattedAttributes});
392
+ }
393
+
394
+ async addOrUpdateLocalUserAttributes(attributes: RtmAttribute[]) {
395
+ let formattedAttributes: any = {};
396
+ attributes.map(attribute => {
397
+ let key = Object.values(attribute)[0];
398
+ let value = Object.values(attribute)[1];
399
+ formattedAttributes[key] = value;
400
+ });
401
+ return this.client.addOrUpdateLocalUserAttributes({...formattedAttributes});
402
+ }
403
+
404
+ async addOrUpdateChannelAttributes(
405
+ channelId: string,
406
+ attributes: RtmChannelAttribute[],
407
+ option: ChannelAttributeOptions,
408
+ ): Promise<void> {
409
+ let formattedAttributes: any = {};
410
+ attributes.map(attribute => {
411
+ let key = Object.values(attribute)[0];
412
+ let value = Object.values(attribute)[1];
413
+ formattedAttributes[key] = value;
414
+ });
415
+ return this.client.addOrUpdateChannelAttributes(
416
+ channelId,
417
+ {...formattedAttributes},
418
+ option,
419
+ );
420
+ }
421
+
422
+ async sendLocalInvitation(invitationProps: any) {
423
+ let invite = this.client.createLocalInvitation(invitationProps.uid);
424
+ this.localInvititations.set(invitationProps.uid, invite);
425
+ invite.content = invitationProps.content;
426
+
427
+ invite.on('LocalInvitationAccepted', (response: string) => {
428
+ this.localInvitationEventsMap.get('localInvitationAccepted')({
429
+ calleeId: invite.calleeId,
430
+ content: invite.content,
431
+ state: invite.state,
432
+ channelId: invite.channelId,
433
+ response,
434
+ });
435
+ });
436
+
437
+ invite.on('LocalInvitationCanceled', () => {
438
+ this.localInvitationEventsMap.get('localInvitationCanceled')({
439
+ calleeId: invite.calleeId,
440
+ content: invite.content,
441
+ state: invite.state,
442
+ channelId: invite.channelId,
443
+ response: invite.response,
444
+ });
445
+ });
446
+
447
+ invite.on('LocalInvitationFailure', (reason: string) => {
448
+ this.localInvitationEventsMap.get('localInvitationFailure')({
449
+ calleeId: invite.calleeId,
450
+ content: invite.content,
451
+ state: invite.state,
452
+ channelId: invite.channelId,
453
+ response: invite.response,
454
+ code: -1, //Web sends string, RN expect number but can't find enum
455
+ });
456
+ });
457
+
458
+ invite.on('LocalInvitationReceivedByPeer', () => {
459
+ this.localInvitationEventsMap.get('localInvitationReceivedByPeer')({
460
+ calleeId: invite.calleeId,
461
+ content: invite.content,
462
+ state: invite.state,
463
+ channelId: invite.channelId,
464
+ response: invite.response,
465
+ });
466
+ });
467
+
468
+ invite.on('LocalInvitationRefused', (response: string) => {
469
+ this.localInvitationEventsMap.get('localInvitationRefused')({
470
+ calleeId: invite.calleeId,
471
+ content: invite.content,
472
+ state: invite.state,
473
+ channelId: invite.channelId,
474
+ response: response,
475
+ });
476
+ });
477
+ return invite.send();
478
+ }
479
+
480
+ async sendMessageToPeer(AgoraPeerMessage: {
481
+ peerId: string;
482
+ offline: boolean;
483
+ text: string;
484
+ }) {
485
+ return this.client.sendMessageToPeer(
486
+ {text: AgoraPeerMessage.text},
487
+ AgoraPeerMessage.peerId,
488
+ );
489
+ //check promise result
490
+ }
491
+
492
+ async acceptRemoteInvitation(remoteInvitationProps: {
493
+ uid: string;
494
+ response?: string;
495
+ channelId: string;
496
+ }) {
497
+ let invite = this.remoteInvititations.get(remoteInvitationProps.uid);
498
+ // console.log(invite);
499
+ // console.log(this.remoteInvititations);
500
+ // console.log(remoteInvitationProps.uid);
501
+ return invite.accept();
502
+ }
503
+
504
+ async refuseRemoteInvitation(remoteInvitationProps: {
505
+ uid: string;
506
+ response?: string;
507
+ channelId: string;
508
+ }) {
509
+ return this.remoteInvititations.get(remoteInvitationProps.uid).refuse();
510
+ }
511
+
512
+ async cancelLocalInvitation(LocalInvitationProps: {
513
+ uid: string;
514
+ content?: string;
515
+ channelId?: string;
516
+ }) {
517
+ console.log(this.localInvititations.get(LocalInvitationProps.uid));
518
+ return this.localInvititations.get(LocalInvitationProps.uid).cancel();
519
+ }
520
+
521
+ getSdkVersion(callback: (version: string) => void) {
522
+ callback(VERSION);
523
+ }
524
+
525
+ addListener<EventType extends keyof RtmClientEvents>(
526
+ event: EventType,
527
+ listener: RtmClientEvents[EventType],
528
+ ): Subscription {
529
+ if (event === 'ChannelAttributesUpdated') {
530
+ this.channelEventsMap.set(event, listener as callbackType);
531
+ }
532
+ return {
533
+ remove: () => {
534
+ console.log(
535
+ 'Use destroy method to remove all the event listeners from the RtcEngine instead.',
536
+ );
537
+ },
538
+ };
539
+ }
540
+ }