mezon-sdk 2.7.1 → 2.7.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.
package/socket.ts ADDED
@@ -0,0 +1,1345 @@
1
+ /**
2
+ * Copyright 2020 The Mezon Authors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { ApiMessageAttachment, ApiMessageMention, ApiMessageReaction, ApiMessageRef, ChannelMessage } from "./client";
18
+ import {Session} from "./session";
19
+ import { WebSocketAdapter, WebSocketAdapterText } from "./web_socket_adapter";
20
+
21
+ /** Stores function references for resolve/reject with a DOM Promise. */
22
+ interface PromiseExecutor {
23
+ resolve: (value?: any) => void;
24
+ reject: (reason?: any) => void;
25
+ }
26
+ /** An object which represents a connected user in the server. */
27
+ export interface Presence {
28
+ /** The id of the user. */
29
+ user_id: string;
30
+ /** The session id of the user. */
31
+ session_id: string;
32
+ /** The username of the user. */
33
+ username: string;
34
+ /** The node the user is connected to. */
35
+ node: string;
36
+ /** The status of the user */
37
+ status: string;
38
+ }
39
+
40
+ /** A response from a channel join operation. */
41
+ export interface Channel {
42
+ /** The server-assigned channel id. */
43
+ id: string;
44
+ // label
45
+ chanel_label: string;
46
+ /** The presences visible on the chat channel. */
47
+ presences: Presence[];
48
+ /** The presence of the current user, i.e. yourself. */
49
+ self: Presence;
50
+ // The ID of the first DM user, or an empty string if this message was not sent through a DM chat.
51
+ clan_logo: string;
52
+ // The ID of the second DM user, or an empty string if this message was not sent through a DM chat.
53
+ category_name: string;
54
+ }
55
+
56
+ export interface ClanJoin {
57
+ clan_join: {
58
+ clan_id: string;
59
+ }
60
+ }
61
+
62
+ /** Join a realtime chat channel. */
63
+ interface ChannelJoin {
64
+ channel_join: {
65
+ /** The id of the channel to join. */
66
+ channel_id: string;
67
+ /** The name of the channel to join. */
68
+ channel_label: string;
69
+ /** The channel type: 1 = Channel, 2 = Direct Message, 3 = Group. */
70
+ type: number;
71
+ /** Whether channel messages are persisted in the database. */
72
+ persistence: boolean;
73
+ /** Whether the user's channel presence is hidden when joining. */
74
+ hidden: boolean;
75
+ };
76
+ }
77
+
78
+ /** Leave a realtime chat channel. */
79
+ interface ChannelLeave {
80
+ channel_leave: {
81
+ /** The id of the channel to leave. */
82
+ channel_id:string;
83
+ // The mode
84
+ mode: number;
85
+ // The channel label
86
+ channel_label: string;
87
+ };
88
+ }
89
+
90
+ /** UserChannelAddedEvent */
91
+ export interface UserChannelAddedEvent {
92
+ // the channel id
93
+ channel_id: string;
94
+ // the user
95
+ users: AddUsers[];
96
+ // the custom status
97
+ status: string;
98
+ // the clan id
99
+ clan_id: string;
100
+ // the channel type
101
+ channel_type: number;
102
+ }
103
+
104
+ export interface AddUsers {
105
+ // User IDs to follow.
106
+ user_id: string;
107
+ // Avatar to follow.
108
+ avatar: string;
109
+ // Username to follow.
110
+ username: string;
111
+ }
112
+
113
+ export interface UserChannelRemovedEvent {
114
+ // the channel id
115
+ channel_id: string;
116
+ // the user_id
117
+ user_ids: string[];
118
+ }
119
+
120
+ export interface UserClanRemovedEvent {
121
+ // the clan id
122
+ clan_id: string;
123
+ // the user_id
124
+ user_ids: string[];
125
+ }
126
+
127
+ /** Last seen message by user */
128
+ export interface LastPinMessageEvent {
129
+ /** The channel this message belongs to. */
130
+ channel_id:string;
131
+ // The mode
132
+ mode: number;
133
+ // The channel label
134
+ channel_label: string;
135
+ /** The unique ID of this message. */
136
+ message_id: string;
137
+ /** user id */
138
+ user_id: string;
139
+ /** operation */
140
+ operation: number;
141
+ }
142
+
143
+ /** Last seen message by user */
144
+ export interface LastSeenMessageEvent {
145
+ /** The channel this message belongs to. */
146
+ channel_id:string;
147
+ // The mode
148
+ mode: number;
149
+ // The channel label
150
+ channel_label: string;
151
+ /** The unique ID of this message. */
152
+ message_id: string;
153
+ }
154
+
155
+ /** User is typing */
156
+ export interface MessageTypingEvent {
157
+ /** The channel this message belongs to. */
158
+ channel_id:string;
159
+ // The mode
160
+ mode: number;
161
+ // The channel label
162
+ channel_label: string;
163
+ /** Message sender, usually a user ID. */
164
+ sender_id: string;
165
+ }
166
+
167
+ // user profile updated event
168
+ export interface UserProfileUpdatedEvent{
169
+ // the user id
170
+ user_id: string;
171
+ // the display_name
172
+ display_name: string;
173
+ // the avatar
174
+ avatar: string;
175
+ // the about_me
176
+ about_me: string;
177
+ // the channel_id
178
+ channel_id: string;
179
+ // the clan_id
180
+ clan_id: string;
181
+ }
182
+
183
+ /** An acknowledgement received in response to sending a message on a chat channel. */
184
+ export interface ChannelMessageAck {
185
+ /** The server-assigned channel ID. */
186
+ channel_id:string;
187
+ // The mode
188
+ mode: number;
189
+ /** A unique ID for the chat message. */
190
+ message_id: string;
191
+ /** A user-defined code for the chat message. */
192
+ code: number;
193
+ /** The username of the sender of the message. */
194
+ username: string;
195
+ /** The UNIX time when the message was created. */
196
+ create_time: string;
197
+ /** The UNIX time when the message was updated. */
198
+ update_time: string;
199
+ /** True if the chat message has been stored in history. */
200
+ persistence: boolean;
201
+ }
202
+
203
+ /** Send a message to a realtime chat channel. */
204
+ interface ChannelMessageSend {
205
+ channel_message_send: {
206
+ /** Clan Id */
207
+ clan_id: string;
208
+ /** The server-assigned channel ID. */
209
+ channel_id:string;
210
+ // The mode
211
+ mode: number;
212
+ // channel label
213
+ channel_label: string;
214
+ /** The content payload. */
215
+ content: any;
216
+ //
217
+ mentions?: Array<ApiMessageMention>;
218
+ //
219
+ attachments?: Array<ApiMessageAttachment>;
220
+ //
221
+ anonymous_message?: boolean;
222
+ //
223
+ mention_everyone?: boolean;
224
+ //
225
+ avatar: string;
226
+ };
227
+ }
228
+
229
+ /** Update a message previously sent to a realtime chat channel. */
230
+ interface ChannelMessageUpdate {
231
+ channel_message_update: {
232
+ /** The server-assigned channel ID. */
233
+ channel_id: string,
234
+ /** The server-assigned channel label. */
235
+
236
+ /** A unique ID for the chat message to be updated. */
237
+ message_id: string,
238
+ /** The content payload. */
239
+ content: any,
240
+ /** mentions */
241
+ mentions?: Array<ApiMessageMention>;
242
+ /** attachments */
243
+ attachments?: Array<ApiMessageAttachment>;
244
+ /** The mode payload. */
245
+ mode: number;
246
+ };
247
+ }
248
+
249
+ /** Remove a message previously sent to a realtime chat channel. */
250
+ interface ChannelMessageRemove {
251
+ channel_message_remove: {
252
+ /** The server-assigned channel ID. */
253
+ channel_id:string;
254
+ // The mode
255
+ mode: number;
256
+ // The channel label
257
+ channel_label: string;
258
+ /** A unique ID for the chat message to be removed. */
259
+ message_id: string;
260
+ };
261
+ }
262
+
263
+ /** Presence update for a particular realtime chat channel. */
264
+ export interface ChannelPresenceEvent {
265
+ /** The unique identifier of the chat channel. */
266
+ channel_id: string;
267
+ // The channel name
268
+ channel_label: string;
269
+ // The mode
270
+ mode: number;
271
+ /** Presences of the users who joined the channel. */
272
+ joins: Presence[];
273
+ /** Presences of users who left the channel. */
274
+ leaves: Presence[];
275
+ }
276
+
277
+ export interface VoiceEndedEvent {
278
+ // id voice
279
+ id: string;
280
+ // The unique identifier of the chat clan.
281
+ clan_id: string;
282
+ // voice channel name
283
+ voice_channel_id: string;
284
+ }
285
+
286
+ export interface VoiceStartedEvent {
287
+ // id voice
288
+ id: string;
289
+ // The unique identifier of the chat clan.
290
+ clan_id: string;
291
+ // voice channel name
292
+ voice_channel_id: string;
293
+ }
294
+
295
+ export interface VoiceLeavedEvent {
296
+ // event id
297
+ id: string;
298
+ // clan id
299
+ clan_id: string;
300
+ // voice channel name
301
+ voice_channel_id: string;
302
+ // voice user id
303
+ voice_user_id: string;
304
+ }
305
+
306
+ export interface VoiceJoinedEvent {
307
+ /** The unique identifier of the chat channel. */
308
+ clan_id: string;
309
+ // The channel name
310
+ clan_name: string;
311
+ // id voice
312
+ id: string;
313
+ // voice participant
314
+ participant: string;
315
+ // user id
316
+ user_id: string;
317
+ // voice channel label
318
+ voice_channel_label: string;
319
+ // voice channel id
320
+ voice_channel_id: string;
321
+ // last screenshot
322
+ last_screenshot: string;
323
+ }
324
+
325
+ export interface CustomStatusEvent {
326
+ // the clan id
327
+ clan_id: string;
328
+ // the user id
329
+ user_id: string;
330
+ // username
331
+ username: string;
332
+ // the status
333
+ status: string;
334
+ }
335
+
336
+ export interface ChannelUpdatedEvent {
337
+ // clan id
338
+ clan_id: string;
339
+ // category
340
+ category_id: string;
341
+ // creator
342
+ creator_id: string;
343
+ // parrent_id
344
+ parrent_id: string;
345
+ // channel id
346
+ channel_id: string;
347
+ // channel label
348
+ channel_label: string;
349
+ // channel type
350
+ channel_type: number;
351
+ // status
352
+ status: number;
353
+ }
354
+
355
+ export interface ChannelCreatedEvent {
356
+ // clan id
357
+ clan_id: string;
358
+ // category
359
+ category_id: string;
360
+ // creator
361
+ creator_id: string;
362
+ // parrent_id
363
+ parrent_id: string;
364
+ // channel id
365
+ channel_id: string;
366
+ // channel label
367
+ channel_label: string;
368
+ // channel private
369
+ channel_private: number;
370
+ // channel type
371
+ channel_type: number;
372
+ // status
373
+ status: number;
374
+ }
375
+
376
+ export interface ChannelDeletedEvent {
377
+ // clan id
378
+ clan_id: string;
379
+ // category
380
+ category_id: string;
381
+ // channel id
382
+ channel_id: string;
383
+ // deletor
384
+ deletor: string;
385
+ }
386
+
387
+ // clan updated event
388
+ export interface ClanUpdatedEvent {
389
+ // the clan id
390
+ clan_id: string;
391
+ // the clan name
392
+ clan_name: string;
393
+ // the clan logo
394
+ clan_logo: string;
395
+ }
396
+
397
+ export interface ClanProfileUpdatedEvent {
398
+ // the user id
399
+ user_id: string;
400
+ // the clan_nick
401
+ clan_nick: string;
402
+ // the avatar
403
+ clan_avatar: string;
404
+ // the clan_id
405
+ clan_id: string;
406
+ }
407
+
408
+ /** Stream identifier */
409
+ export interface StreamId {
410
+ /** The type of stream (e.g. chat). */
411
+ mode: number;
412
+ /** The primary stream subject, usually a user id. */
413
+ subject: string;
414
+ /** A secondary stream subject, for example for a direct chat. */
415
+ descriptor: string;
416
+ /** Meta-information (e.g. chat room name). */
417
+ label: string;
418
+ }
419
+
420
+ /** Stream data. */
421
+ export interface StreamData {
422
+ /** The stream identifier. */
423
+ stream: StreamId;
424
+ /** A reference to the user presence that sent this data, if any. */
425
+ sender?: Presence;
426
+ /** Arbitrary contents of the data message. */
427
+ data: string;
428
+ /** True if this data was delivered reliably. */
429
+ reliable?: boolean;
430
+ }
431
+
432
+ /** Presence updates. */
433
+ export interface StreamPresenceEvent {
434
+ /** The stream identifier. */
435
+ stream: StreamId;
436
+ /** Presences of users who joined the stream. */
437
+ joins: Presence[];
438
+ /** Presences of users who left the stream. */
439
+ leaves: Presence[];
440
+ }
441
+
442
+ /** Execute an Lua function on the server. */
443
+ interface Rpc {
444
+ rpc: ApiRpc;
445
+ }
446
+
447
+ /** Execute an Lua function on the server. */
448
+ export interface ApiRpc {
449
+ //The authentication key used when executed as a non-client HTTP request.
450
+ http_key?: string;
451
+ //The identifier of the function.
452
+ id?: string;
453
+ //The payload of the function which must be a JSON object.
454
+ payload?: string;
455
+ }
456
+
457
+ /** Application-level heartbeat ping. */
458
+ interface Ping {
459
+
460
+ }
461
+
462
+ /** A snapshot of statuses for some set of users. */
463
+ export interface Status {
464
+ /** The user presences to view statuses of. */
465
+ presences: Presence[];
466
+ }
467
+
468
+ /** Start receiving status updates for some set of users. */
469
+ interface StatusFollow {
470
+ /** The IDs of the users to follow. */
471
+ status_follow: {user_ids: string[];}
472
+ }
473
+
474
+ /** A batch of status updates for a given user. */
475
+ export interface StatusPresenceEvent {
476
+ /** This join information is in response to a subscription made to be notified when a user comes online. */
477
+ joins: Presence[];
478
+ /** This join information is in response to a subscription made to be notified when a user goes offline. */
479
+ leaves: Presence[];
480
+ }
481
+
482
+ /** Stop receiving status updates for some set of users. */
483
+ interface StatusUnfollow {
484
+ /** The IDs of user to unfollow. */
485
+ status_unfollow: {user_ids: string[];};
486
+ }
487
+
488
+ /** Set the user's own status. */
489
+ interface StatusUpdate {
490
+ /** Status string to set, if not present the user will appear offline. */
491
+ status_update: {status?: string;};
492
+ }
493
+ export interface ClanNameExistedEvent {
494
+ clan_name: string;
495
+ exist: boolean;
496
+ }
497
+
498
+
499
+ /** */
500
+ export interface StrickerListedEvent {
501
+ // clan id
502
+ clan_id: string;
503
+ // sticker data
504
+ stickers?: Array<ClanSticker>;
505
+ }
506
+
507
+ /** */
508
+ export interface ClanSticker {
509
+ //
510
+ category?: string;
511
+ //
512
+ clan_id?: string;
513
+ //
514
+ create_time?: string;
515
+ //
516
+ creator_id?: string;
517
+ //
518
+ id?: string;
519
+ //
520
+ shortname?: string;
521
+ //
522
+ source?: string;
523
+ }
524
+
525
+ /** */
526
+ export interface EmojiListedEvent {
527
+ // clan id
528
+ clan_id: string;
529
+ // emoji data
530
+ emoji_list?: Array<ClanEmoji>;
531
+ }
532
+
533
+ /** */
534
+ export interface ClanEmoji {
535
+ //
536
+ category?: string;
537
+ //
538
+ creator_id?: string;
539
+ //
540
+ id?: string;
541
+ //
542
+ shortname?: string;
543
+ //
544
+ src?: string;
545
+ }
546
+
547
+ /** */
548
+ export interface ChannelDescListEvent {
549
+ //
550
+ channeldesc?: Array<ChannelDescription>;
551
+ }
552
+
553
+ /** */
554
+ export interface ChannelDescription {
555
+ // The clan of this channel
556
+ clan_id?: string;
557
+ // The channel this message belongs to.
558
+ channel_id?: string;
559
+ // The channel type.
560
+ type?: number;
561
+ // The channel lable
562
+ channel_label?: string;
563
+ // The channel private
564
+ channel_private?: number;
565
+ // meeting code
566
+ meeting_code?: string;
567
+ //
568
+ clan_name?: string;
569
+ //
570
+ parrent_id?: string;
571
+ }
572
+
573
+ // A list of Channel
574
+ export interface HashtagDmListEvent {
575
+ // user Id
576
+ user_id?: Array<string>;
577
+ // Max number of records to return. Between 1 and 100.
578
+ limit?: number;
579
+ // A list of channel.
580
+ hashtag_dm?: Array<HashtagDm>;
581
+ }
582
+
583
+ // hashtagDM
584
+ export interface HashtagDm {
585
+ // The channel id.
586
+ channel_id?: string;
587
+ // The channel lable
588
+ channel_label?: string;
589
+ // The clan of this channel
590
+ clan_id?: string;
591
+ // The clan name
592
+ clan_name?: string;
593
+ //
594
+ meeting_code?: string;
595
+ //
596
+ type?: number;
597
+ //
598
+ channel_private?: number;
599
+ //
600
+ parrent_id?: string;
601
+ }
602
+
603
+ export interface NotificationChannelSettingEvent {
604
+ // The channel id.
605
+ channel_id?: string;
606
+ //
607
+ notification_user_channel?: NotificationUserChannel;
608
+ }
609
+
610
+ export interface NotificationUserChannel {
611
+ //
612
+ active?: number;
613
+ //
614
+ id?: string;
615
+ //
616
+ notification_setting_type?: number;
617
+ //
618
+ time_mute?: string;
619
+ }
620
+
621
+ export interface NotificationCategorySettingEvent {
622
+ //
623
+ category_id?: string;
624
+ //
625
+ notification_user_channel?: NotificationUserChannel;
626
+ }
627
+
628
+ export interface NotificationClanSettingEvent {
629
+ // The clan of this channel
630
+ clan_id?: string;
631
+ //
632
+ notification_setting?: NotificationSetting;
633
+ }
634
+
635
+ export interface NotificationSetting {
636
+ //
637
+ id?: string;
638
+ //
639
+ notification_setting_type?: number;
640
+ }
641
+
642
+ export interface NotifiReactMessageEvent {
643
+ //
644
+ channel_id?: string;
645
+ //
646
+ notifi_react_message?: NotifiReactMessage;
647
+ }
648
+
649
+ export interface NotifiReactMessage {
650
+ //
651
+ id?: string;
652
+ //
653
+ user_id?: string;
654
+ //
655
+ channel_id_req?: string;
656
+ }
657
+
658
+ /** A socket connection to Mezon server. */
659
+ export interface Socket {
660
+ /** Connection is Open */
661
+ isOpen(): boolean;
662
+
663
+ /** Connect to the server. */
664
+ connect(session: Session, createStatus: boolean): Promise<Session>;
665
+
666
+ /** Disconnect from the server. */
667
+ disconnect(fireDisconnectEvent: boolean): void;
668
+
669
+ /** Join clan chat */
670
+ joinClanChat(clan_id: string) : Promise<ClanJoin>;
671
+
672
+ /** Join a chat channel on the server. */
673
+ joinChat(clan_id: string, channel_id: string, channel_type: number) : Promise<Channel>;
674
+
675
+ /** Leave a chat channel on the server. */
676
+ leaveChat(clan_id: string, channel_id: string, channel_type: number) : Promise<void>;
677
+
678
+ /** Remove a chat message from a chat channel on the server. */
679
+ removeChatMessage(clan_id: string, channel_id: string, mode: number, message_id: string) : Promise<ChannelMessageAck>;
680
+
681
+ /** Execute an RPC function to the server. */
682
+ rpc(id?: string, payload?: string, http_key?: string) : Promise<ApiRpc>
683
+
684
+ /** Update a chat message on a chat channel in the server. */
685
+ updateChatMessage(clan_id: string, channel_id: string, mode: number, message_id : string, content: any, mentions?: Array<ApiMessageMention>, attachments?: Array<ApiMessageAttachment>) : Promise<ChannelMessageAck>;
686
+
687
+ /** Update the status for the current user online. */
688
+ updateStatus(status? : string) : Promise<void>;
689
+
690
+ /** Send a chat message to a chat channel on the server. */
691
+ writeChatMessage(clan_id: string, channel_id: string, mode: number, content?: any, mentions?: Array<ApiMessageMention>, attachments?: Array<ApiMessageAttachment>, references?: Array<ApiMessageRef>, anonymous_message?: boolean, mention_everyone?:boolean, avatar?: string) : Promise<ChannelMessageAck>;
692
+
693
+ /** Send message reaction */
694
+ writeMessageReaction(id: string, clan_id: string, channel_id: string, mode: number, message_id: string, emoji_id: string, emoji: string, count: number, message_sender_id: string, action_delete: boolean) : Promise<ApiMessageReaction>;
695
+
696
+ /** Send custom user status */
697
+ writeCustomStatus(clan_id: string, status: string) : Promise<CustomStatusEvent>;
698
+
699
+ /** Handle disconnect events received from the socket. */
700
+ ondisconnect: (evt: Event) => void;
701
+
702
+ /** Handle error events received from the socket. */
703
+ onerror: (evt: Event) => void;
704
+
705
+
706
+ /**
707
+ * An application-level heartbeat timeout that fires after the client does not receive a pong from the server after the heartbeat interval.
708
+ * Most browsers maintain an internal heartbeat, in which case its unlikely you'll need to use this callback. However, Chrome does not implement an internal heartbeat.
709
+ * We fire this separately from `onclose` because heartbeats fail when there's no connectivity, and many browsers don't fire `onclose` until the closing handshake either succeeds or fails.
710
+ * In any case, be aware that `onclose` will still fire if there is a heartbeat timeout in a potentially delayed manner.
711
+ */
712
+ onheartbeattimeout: () => void;
713
+
714
+ oncustomstatus: (statusEvent: CustomStatusEvent) => void;
715
+
716
+ /** Receive channel message. */
717
+ onchannelmessage: (channelMessage: ChannelMessage) => void;
718
+
719
+ /** Receive reaction event */
720
+ onmessagereaction: (messageReactionEvent: ApiMessageReaction) => void;
721
+
722
+ /** Receive channel presence updates. */
723
+ onchannelpresence: (channelPresence: ChannelPresenceEvent) => void;
724
+
725
+ /** Receive added user event */
726
+ onuserchanneladded: (user: UserChannelAddedEvent) => void;
727
+
728
+ /** Receive update user event */
729
+ onuserprofileupdate: (user: UserProfileUpdatedEvent) => void;
730
+
731
+ /** Receive channel removed user event */
732
+ onuserchannelremoved: (user: UserChannelRemovedEvent) => void;
733
+
734
+ /** Receive clan removed user event */
735
+ onuserclanremoved: (user: UserClanRemovedEvent) => void;
736
+
737
+ // when channel is created
738
+ onchannelcreated: (channelCreated: ChannelCreatedEvent) => void;
739
+
740
+ // when channel is deleted
741
+ onchanneldeleted: (channelDeleted: ChannelDeletedEvent) => void;
742
+
743
+ // when channel is updated
744
+ onchannelupdated: (channelUpdated: ChannelUpdatedEvent) => void;
745
+
746
+ // when clan profile is updated
747
+ onclanprofileupdated: (clanprofile: ClanProfileUpdatedEvent) => void;
748
+
749
+ // when clan is updated
750
+ onclanupdated: (clan: ClanUpdatedEvent) => void;
751
+ }
752
+
753
+ /** Reports an error received from a socket message. */
754
+ export interface SocketError {
755
+ /** The error code. */
756
+ code: number;
757
+ /** A message in English to help developers debug the response. */
758
+ message: string;
759
+ }
760
+
761
+ /** A socket connection to Mezon server implemented with the DOM's WebSocket API. */
762
+ export class DefaultSocket implements Socket {
763
+ public static readonly DefaultHeartbeatTimeoutMs = 10000;
764
+ public static readonly DefaultSendTimeoutMs = 10000;
765
+ public static readonly DefaultConnectTimeoutMs = 30000;
766
+
767
+ private readonly cIds: { [key: string]: PromiseExecutor };
768
+ private nextCid: number;
769
+ private _heartbeatTimeoutMs: number;
770
+
771
+ constructor(
772
+ readonly host: string,
773
+ readonly port: string,
774
+ readonly useSSL: boolean = false,
775
+ public verbose: boolean = false,
776
+ readonly adapter : WebSocketAdapter = new WebSocketAdapterText(),
777
+ readonly sendTimeoutMs : number = DefaultSocket.DefaultSendTimeoutMs
778
+ ) {
779
+ this.cIds = {};
780
+ this.nextCid = 1;
781
+ this._heartbeatTimeoutMs = DefaultSocket.DefaultHeartbeatTimeoutMs;
782
+ }
783
+
784
+ generatecid(): string {
785
+ const cid = this.nextCid.toString();
786
+ ++this.nextCid;
787
+ return cid;
788
+ }
789
+
790
+ isOpen(): boolean {
791
+ return this.adapter.isOpen();
792
+ }
793
+
794
+ connect(session: Session, createStatus: boolean = false, connectTimeoutMs: number = DefaultSocket.DefaultConnectTimeoutMs): Promise<Session> {
795
+ if (this.adapter.isOpen()) {
796
+ return Promise.resolve(session);
797
+ }
798
+
799
+ const scheme = (this.useSSL) ? "wss://" : "ws://";
800
+ this.adapter.connect(scheme, this.host, this.port, createStatus, session.token);
801
+
802
+ this.adapter.onClose = (evt: Event) => {
803
+ this.ondisconnect(evt);
804
+ }
805
+
806
+ this.adapter.onError = (evt: Event) => {
807
+ this.onerror(evt);
808
+ }
809
+
810
+ this.adapter.onMessage = (message: any) => {
811
+ if (this.verbose && window && window.console) {
812
+ console.log("Response: %o", JSON.stringify(message));
813
+ }
814
+
815
+ /** Inbound message from server. */
816
+ if (!message.cid) {
817
+ if (message.voice_started_event) {
818
+ this.onvoicestarted(message.voice_started_event)
819
+ } else if (message.voice_ended_event) {
820
+ this.onvoiceended(message.voice_ended_event)
821
+ } else if (message.voice_joined_event) {
822
+ this.onvoicejoined(message.voice_joined_event)
823
+ } else if (message.voice_leaved_event) {
824
+ this.onvoiceleaved(message.voice_leaved_event)
825
+ } else if (message.channel_created_event) {
826
+ this.onchannelcreated(message.channel_created_event)
827
+ } else if (message.channel_deleted_event) {
828
+ this.onchanneldeleted(message.channel_deleted_event)
829
+ } else if (message.channel_updated_event) {
830
+ this.onchannelupdated(message.channel_updated_event)
831
+ } else if (message.clan_profile_updated_event) {
832
+ this.onclanprofileupdated(message.clan_profile_updated_event)
833
+ } else if (message.clan_updated_event) {
834
+ this.onclanupdated(message.clan_updated_event)
835
+ } else if (message.status_presence_event) {
836
+ this.onstatuspresence(<StatusPresenceEvent>message.status_presence_event);
837
+ } else if (message.stream_presence_event) {
838
+ this.onstreampresence(<StreamPresenceEvent>message.stream_presence_event);
839
+ } else if (message.stream_data) {
840
+ this.onstreamdata(<StreamData>message.stream_data);
841
+ } else if (message.channel_message) {
842
+ var content, reactions, mentions, attachments, references;
843
+ try {
844
+ content = JSON.parse(message.channel_message.content);
845
+ } catch(e) {
846
+ //console.log("content is invalid", e)
847
+ }
848
+ try {
849
+ reactions = JSON.parse(message.channel_message.reactions);
850
+ } catch(e) {
851
+ //console.log("reactions is invalid", e)
852
+ }
853
+ try {
854
+ mentions = JSON.parse(message.channel_message.mentions);
855
+ } catch(e) {
856
+ //console.log("mentions is invalid", e)
857
+ }
858
+ try {
859
+ attachments = JSON.parse(message.channel_message.attachments);
860
+ } catch(e) {
861
+ //console.log("attachments is invalid", e)
862
+ }
863
+ try {
864
+ references = JSON.parse(message.channel_message.references);
865
+ } catch(e) {
866
+ //console.log("references is invalid", e);
867
+ }
868
+ var e: ChannelMessage = {
869
+ id: message.id,
870
+ avatar: message.channel_message.avatar,
871
+ channel_id: message.channel_message.channel_id,
872
+ mode: message.channel_message.mode,
873
+ channel_label: message.channel_message.channel_label,
874
+ clan_id: message.channel_message.clan_id,
875
+ code: message.channel_message.code,
876
+ create_time: message.channel_message.create_time,
877
+ message_id: message.channel_message.message_id,
878
+ sender_id: message.channel_message.sender_id,
879
+ update_time: message.channel_message.update_time,
880
+ clan_logo: message.channel_message.clan_logo,
881
+ category_name: message.channel_message.category_name,
882
+ username: message.channel_message.username,
883
+ clan_nick: message.channel_message.clan_nick,
884
+ clan_avatar: message.channel_message.clan_avatar,
885
+ display_name: message.channel_message.display_name,
886
+ content: content,
887
+ reactions: reactions,
888
+ mentions: mentions,
889
+ attachments: attachments,
890
+ references: references,
891
+ };
892
+ this.onchannelmessage(e);
893
+ } else if (message.message_typing_event) {
894
+ this.onmessagetyping(<MessageTypingEvent>message.message_typing_event);
895
+ } else if (message.message_reaction_event) {
896
+ this.onmessagereaction(<ApiMessageReaction>message.message_reaction_event);
897
+ } else if (message.channel_presence_event) {
898
+ this.onchannelpresence(<ChannelPresenceEvent>message.channel_presence_event);
899
+ } else if (message.last_pin_message_event) {
900
+ this.onpinmessage(<LastPinMessageEvent>message.last_pin_message_event);
901
+ } else if (message.custom_status_event) {
902
+ this.oncustomstatus(<CustomStatusEvent>message.custom_status_event);
903
+ } else if (message.user_channel_added_event) {
904
+ this.onuserchanneladded(<UserChannelAddedEvent>message.user_channel_added_event);
905
+ } else if (message.user_channel_added_event) {
906
+ this.onuserprofileupdate(<UserProfileUpdatedEvent>message.user_profile_updated_event);
907
+ } else if (message.user_profile_updated_event) {
908
+ this.onuserchannelremoved(<UserChannelRemovedEvent>message.user_channel_removed_event);
909
+ } else if (message.user_clan_removed_event) {
910
+ this.onuserclanremoved(<UserClanRemovedEvent>message.user_clan_removed_event);
911
+ } else {
912
+ if (this.verbose && window && window.console) {
913
+ console.log("Unrecognized message received: %o", message);
914
+ }
915
+ }
916
+ } else {
917
+ const executor = this.cIds[message.cid];
918
+ if (!executor) {
919
+ if (this.verbose && window && window.console) {
920
+ console.error("No promise executor for message: %o", message);
921
+ }
922
+ return;
923
+ }
924
+ delete this.cIds[message.cid];
925
+
926
+ if (message.error) {
927
+ executor.reject(<SocketError>message.error);
928
+ } else {
929
+ executor.resolve(message);
930
+ }
931
+ }
932
+ }
933
+
934
+ return new Promise((resolve, reject) => {
935
+ this.adapter.onOpen = (evt: Event) => {
936
+ if (this.verbose && window && window.console) {
937
+ console.log(evt);
938
+ }
939
+
940
+ this.pingPong();
941
+ resolve(session);
942
+ }
943
+ this.adapter.onError = (evt: Event) => {
944
+ reject(evt);
945
+ this.adapter.close();
946
+ }
947
+
948
+ setTimeout(() => {
949
+ // if promise has resolved by now, the reject() is a no-op
950
+ reject("The socket timed out when trying to connect.");
951
+ }, connectTimeoutMs);
952
+ });
953
+ }
954
+
955
+ disconnect(fireDisconnectEvent: boolean = true) {
956
+ if (this.adapter.isOpen()) {
957
+ this.adapter.close();
958
+ }
959
+ if (fireDisconnectEvent) {
960
+ this.ondisconnect(<Event>{});
961
+ }
962
+ }
963
+
964
+ setHeartbeatTimeoutMs(ms : number) {
965
+ this._heartbeatTimeoutMs = ms;
966
+ }
967
+
968
+ getHeartbeatTimeoutMs() : number {
969
+ return this._heartbeatTimeoutMs;
970
+ }
971
+
972
+ ondisconnect(evt: Event) {
973
+ if (this.verbose && window && window.console) {
974
+ console.log(evt);
975
+ }
976
+ }
977
+
978
+ onerror(evt: Event) {
979
+ if (this.verbose && window && window.console) {
980
+ console.log(evt);
981
+ }
982
+ }
983
+
984
+ onmessagetyping(messagetyping: MessageTypingEvent) {
985
+ if (this.verbose && window && window.console) {
986
+ console.log(messagetyping);
987
+ }
988
+ }
989
+
990
+ onmessagereaction(messagereaction: ApiMessageReaction) {
991
+ if (this.verbose && window && window.console) {
992
+ console.log(messagereaction);
993
+ }
994
+ }
995
+
996
+ onchannelmessage(channelMessage: ChannelMessage) {
997
+ if (this.verbose && window && window.console) {
998
+ console.log(channelMessage);
999
+ }
1000
+ }
1001
+
1002
+ onchannelpresence(channelPresence: ChannelPresenceEvent) {
1003
+ if (this.verbose && window && window.console) {
1004
+ console.log(channelPresence);
1005
+ }
1006
+ }
1007
+
1008
+ onuserchanneladded(user: UserChannelAddedEvent) {
1009
+ if (this.verbose && window && window.console) {
1010
+ console.log(user);
1011
+ }
1012
+ }
1013
+
1014
+ onuserprofileupdate(user: UserProfileUpdatedEvent) {
1015
+ if (this.verbose && window && window.console) {
1016
+ console.log(user);
1017
+ }
1018
+ }
1019
+
1020
+ onuserchannelremoved(user: UserChannelRemovedEvent) {
1021
+ if (this.verbose && window && window.console) {
1022
+ console.log(user);
1023
+ }
1024
+ }
1025
+
1026
+ onuserclanremoved(user: UserClanRemovedEvent) {
1027
+ if (this.verbose && window && window.console) {
1028
+ console.log(user);
1029
+ }
1030
+ }
1031
+
1032
+ onnotification(notification: Notification) {
1033
+ if (this.verbose && window && window.console) {
1034
+ console.log(notification);
1035
+ }
1036
+ }
1037
+
1038
+ onstatuspresence(statusPresence: StatusPresenceEvent) {
1039
+ if (this.verbose && window && window.console) {
1040
+ console.log(statusPresence);
1041
+ }
1042
+ }
1043
+
1044
+ onpinmessage(pin: LastPinMessageEvent) {
1045
+ if (this.verbose && window && window.console) {
1046
+ console.log(pin);
1047
+ }
1048
+ }
1049
+
1050
+ onvoiceended(voice: VoiceEndedEvent) {
1051
+ if (this.verbose && window && window.console) {
1052
+ console.log(voice);
1053
+ }
1054
+ }
1055
+
1056
+ onvoicestarted(voice: VoiceStartedEvent) {
1057
+ if (this.verbose && window && window.console) {
1058
+ console.log(voice);
1059
+ }
1060
+ }
1061
+
1062
+ onvoicejoined(voiceParticipant: VoiceJoinedEvent) {
1063
+ if (this.verbose && window && window.console) {
1064
+ console.log(voiceParticipant);
1065
+ }
1066
+ }
1067
+
1068
+ onvoiceleaved(voiceParticipant: VoiceLeavedEvent) {
1069
+ if (this.verbose && window && window.console) {
1070
+ console.log(voiceParticipant);
1071
+ }
1072
+ }
1073
+
1074
+ onchannelcreated(channelCreated: ChannelCreatedEvent) {
1075
+ if (this.verbose && window && window.console) {
1076
+ console.log(channelCreated);
1077
+ }
1078
+ }
1079
+
1080
+ onchanneldeleted(channelDeleted: ChannelDeletedEvent) {
1081
+ if (this.verbose && window && window.console) {
1082
+ console.log(channelDeleted);
1083
+ }
1084
+ }
1085
+
1086
+ onchannelupdated(channelUpdated: ChannelUpdatedEvent) {
1087
+ if (this.verbose && window && window.console) {
1088
+ console.log(channelUpdated);
1089
+ }
1090
+ }
1091
+
1092
+ onclanprofileupdated(clanprofile: ClanProfileUpdatedEvent) {
1093
+ if (this.verbose && window && window.console) {
1094
+ console.log(clanprofile);
1095
+ }
1096
+ }
1097
+
1098
+ onclanupdated(clan: ClanUpdatedEvent) {
1099
+ if (this.verbose && window && window.console) {
1100
+ console.log(clan);
1101
+ }
1102
+ }
1103
+
1104
+ onstreampresence(streamPresence: StreamPresenceEvent) {
1105
+ if (this.verbose && window && window.console) {
1106
+ console.log(streamPresence);
1107
+ }
1108
+ }
1109
+
1110
+ onstreamdata(streamData: StreamData) {
1111
+ if (this.verbose && window && window.console) {
1112
+ console.log(streamData);
1113
+ }
1114
+ }
1115
+
1116
+ onheartbeattimeout() {
1117
+ if (this.verbose && window && window.console) {
1118
+ console.log("Heartbeat timeout.");
1119
+ }
1120
+ }
1121
+
1122
+ oncustomstatus(statusEvent: CustomStatusEvent) {
1123
+ if (this.verbose && window && window.console) {
1124
+ console.log(statusEvent);
1125
+ }
1126
+ }
1127
+
1128
+ send(message: ChannelJoin | ChannelLeave | ChannelMessageSend | ChannelMessageUpdate | CustomStatusEvent |
1129
+ ChannelMessageRemove | MessageTypingEvent | LastSeenMessageEvent | Rpc | StatusFollow | StatusUnfollow | StatusUpdate | Ping, sendTimeout = DefaultSocket.DefaultSendTimeoutMs): Promise<any> {
1130
+ const untypedMessage = message as any;
1131
+
1132
+ return new Promise<void>((resolve, reject) => {
1133
+ if (!this.adapter.isOpen()) {
1134
+ reject("Socket connection has not been established yet.");
1135
+ }
1136
+ else {
1137
+ if (untypedMessage.channel_message_send) {
1138
+ untypedMessage.channel_message_send.content = JSON.stringify(untypedMessage.channel_message_send.content);
1139
+ } else if (untypedMessage.channel_message_update) {
1140
+ untypedMessage.channel_message_update.content = JSON.stringify(untypedMessage.channel_message_update.content);
1141
+ }
1142
+
1143
+ const cid = this.generatecid();
1144
+ this.cIds[cid] = {resolve, reject};
1145
+ setTimeout(() => {
1146
+ reject("The socket timed out while waiting for a response.")
1147
+ }, sendTimeout);
1148
+
1149
+ /** Add id for promise executor. */
1150
+ untypedMessage.cid = cid;
1151
+ this.adapter.send(untypedMessage);
1152
+ }
1153
+ });
1154
+ }
1155
+
1156
+ async joinClanChat(clan_id: string): Promise<ClanJoin> {
1157
+
1158
+ const response = await this.send({
1159
+ clan_join: {
1160
+ clan_id: clan_id,
1161
+ }
1162
+ });
1163
+
1164
+ return response.clan_join;
1165
+ }
1166
+
1167
+ async joinChat(clan_id: string, channel_id: string, channel_type: number): Promise<Channel> {
1168
+
1169
+ const response = await this.send({
1170
+ channel_join: {
1171
+ clan_id: clan_id,
1172
+ channel_id: channel_id,
1173
+ channel_type: channel_type,
1174
+ }
1175
+ }
1176
+ );
1177
+
1178
+ return response.channel;
1179
+ }
1180
+
1181
+ leaveChat(clan_id: string, channel_id: string, channel_type: number): Promise<void> {
1182
+ return this.send({channel_leave: {clan_id: clan_id, channel_id: channel_id, channel_type: channel_type}});
1183
+ }
1184
+
1185
+ async removeChatMessage(clan_id: string, channel_id: string, mode: number, message_id: string): Promise<ChannelMessageAck> {
1186
+ const response = await this.send(
1187
+ {
1188
+ channel_message_remove: {
1189
+ clan_id: clan_id,
1190
+ channel_id: channel_id,
1191
+ mode: mode,
1192
+ message_id: message_id
1193
+ }
1194
+ }
1195
+ );
1196
+
1197
+ return response.channel_message_ack;
1198
+ }
1199
+
1200
+ async removePartyMember(party_id: string, member: Presence): Promise<void> {
1201
+ return this.send({party_remove: {
1202
+ party_id: party_id,
1203
+ presence: member
1204
+ }});
1205
+ }
1206
+
1207
+ async rpc(id?: string, payload?: string, http_key?: string): Promise<ApiRpc> {
1208
+ const response = await this.send(
1209
+ {
1210
+ rpc: {
1211
+ id: id,
1212
+ payload: payload,
1213
+ http_key: http_key,
1214
+ }
1215
+ });
1216
+
1217
+ return response.rpc;
1218
+ }
1219
+
1220
+ sendPartyData(party_id: string, op_code: number, data: string | Uint8Array): Promise<void> {
1221
+ return this.send({party_data_send: {party_id: party_id, op_code: op_code, data: data}})
1222
+ }
1223
+
1224
+ unfollowUsers(user_ids : string[]): Promise<void> {
1225
+ return this.send({status_unfollow: {user_ids: user_ids}});
1226
+ }
1227
+
1228
+ async updateChatMessage(clan_id: string, channel_id: string, mode: number, message_id : string, content: any, mentions?: Array<ApiMessageMention>, attachments?: Array<ApiMessageAttachment>): Promise<ChannelMessageAck> {
1229
+ const response = await this.send({channel_message_update: {clan_id: clan_id, channel_id: channel_id, message_id: message_id, content: content, mentions: mentions, attachments: attachments, mode: mode}});
1230
+ return response.channel_message_ack;
1231
+ }
1232
+
1233
+ updateStatus(status?: string): Promise<void> {
1234
+ return this.send({status_update: {status: status}});
1235
+ }
1236
+
1237
+ async writeChatMessage(clan_id: string, channel_id: string, mode: number, content: any, mentions?: Array<ApiMessageMention>, attachments?: Array<ApiMessageAttachment>, references?: Array<ApiMessageRef>, anonymous_message?: boolean, mention_everyone?:Boolean, avatar?: string ): Promise<ChannelMessageAck> {
1238
+ const response = await this.send({channel_message_send: {clan_id: clan_id, channel_id: channel_id, mode: mode, content: content, mentions: mentions, attachments: attachments, references: references, anonymous_message: anonymous_message, mention_everyone: mention_everyone, avatar: avatar}});
1239
+ return response.channel_message_ack;
1240
+ }
1241
+
1242
+ async writeMessageReaction(id: string, clan_id: string, channel_id: string, mode: number, message_id: string, emoji_id: string, emoji: string, count: number, message_sender_id: string, action_delete: boolean): Promise<ApiMessageReaction> {
1243
+ const response = await this.send({message_reaction_event: {id: id, clan_id: clan_id, channel_id: channel_id, mode: mode, message_id: message_id, emoji_id: emoji_id, emoji: emoji, count: count, message_sender_id: message_sender_id, action: action_delete}});
1244
+ return response.message_reaction_event
1245
+ }
1246
+
1247
+ async writeMessageTyping(clan_id: string, channel_id: string, mode: number): Promise<MessageTypingEvent> {
1248
+ const response = await this.send({message_typing_event: {clan_id: clan_id, channel_id: channel_id, mode:mode}});
1249
+ return response.message_typing_event
1250
+ }
1251
+
1252
+ async writeLastSeenMessage(clan_id: string, channel_id: string, mode: number, message_id: string, timestamp: string): Promise<LastSeenMessageEvent> {
1253
+ const response = await this.send({last_seen_message_event: {clan_id: clan_id, channel_id: channel_id, mode: mode, message_id: message_id, timestamp: timestamp}});
1254
+ return response.last_seen_message_event
1255
+ }
1256
+
1257
+ async writeLastPinMessage(clan_id: string, channel_id: string, mode: number, message_id: string, timestamp: string, operation: number): Promise<LastPinMessageEvent> {
1258
+ const response = await this.send({last_pin_message_event: {clan_id: clan_id, channel_id: channel_id, mode: mode, message_id: message_id, timestamp: timestamp, operation: operation}});
1259
+ return response.last_pin_message_event
1260
+ }
1261
+
1262
+ async writeVoiceJoined(id: string, clanId: string, clanName: string, voiceChannelId: string, voiceChannelLabel: string, participant: string, lastScreenshot: string): Promise<VoiceJoinedEvent> {
1263
+ const response = await this.send({voice_joined_event: {clan_id: clanId, clan_name: clanName, id: id, participant: participant, voice_channel_id: voiceChannelId, voice_channel_label: voiceChannelLabel, last_screenshot: lastScreenshot}});
1264
+ return response.voice_joined_event
1265
+ }
1266
+
1267
+ async writeVoiceLeaved(id: string, clanId: string, voiceChannelId: string, voiceUserId: string): Promise<VoiceLeavedEvent> {
1268
+ const response = await this.send({voice_leaved_event: {id: id, clan_id: clanId, voice_channel_id: voiceChannelId, voice_user_id: voiceUserId}});
1269
+ return response.voice_leaved_event
1270
+ }
1271
+
1272
+ async writeCustomStatus(clan_id: string, status: string): Promise<CustomStatusEvent> {
1273
+ const response = await this.send({custom_status_event: {clan_id: clan_id, status: status}});
1274
+ return response.custom_status_event
1275
+ }
1276
+
1277
+ async checkDuplicateClanName(clan_name: string): Promise<ClanNameExistedEvent> {
1278
+ const response = await this.send({clan_name_existed_event: {clan_name: clan_name}});
1279
+ return response.clan_name_existed_event
1280
+ }
1281
+
1282
+ async listClanEmojiByClanId(clan_id: string): Promise<EmojiListedEvent> {
1283
+ const response = await this.send({emojis_listed_event: {clan_id: clan_id}});
1284
+ return response.emojis_listed_event
1285
+ }
1286
+
1287
+ async ListChannelByUserId(): Promise<ChannelDescListEvent> {
1288
+ const response = await this.send({channel_desc_list_event: {}});
1289
+ return response.channel_desc_list_event
1290
+ }
1291
+
1292
+ async hashtagDMList(user_id: Array<string>, limit: number): Promise<HashtagDmListEvent> {
1293
+ const response = await this.send({hashtag_dm_list_event: {user_id: user_id, limit: limit }});
1294
+ return response.hashtag_dm_list_event
1295
+ }
1296
+
1297
+ async listClanStickersByClanId(clan_id: string): Promise<StrickerListedEvent> {
1298
+ const response = await this.send({sticker_listed_event: {clan_id: clan_id}});
1299
+ return response.sticker_listed_event
1300
+ }
1301
+
1302
+ async getNotificationChannelSetting(channel_id: string): Promise<NotificationChannelSettingEvent> {
1303
+ const response = await this.send({notification_channel_setting_event: {channel_id: channel_id}})
1304
+ return response.notification_channel_setting_event
1305
+ }
1306
+
1307
+ async getNotificationCategorySetting(category_id: string): Promise<NotificationCategorySettingEvent> {
1308
+ const response = await this.send({notification_category_setting_event: {category_id: category_id}})
1309
+ return response.notification_category_setting_event
1310
+ }
1311
+
1312
+ async getNotificationClanSetting(clan_id: string): Promise<NotificationClanSettingEvent> {
1313
+ const response = await this.send({notification_clan_setting_event: {clan_id: clan_id}})
1314
+ return response.notification_clan_setting_event
1315
+ }
1316
+
1317
+ async getNotificationReactMessage(channel_id: string): Promise<NotifiReactMessageEvent> {
1318
+ const response = await this.send({notifi_react_message_event: {channel_id: channel_id}})
1319
+ return response.notifi_react_message_event
1320
+ }
1321
+
1322
+ private async pingPong(): Promise<void> {
1323
+ if (!this.adapter.isOpen()) {
1324
+ return;
1325
+ }
1326
+
1327
+ try {
1328
+ await this.send({ping: {}}, this._heartbeatTimeoutMs);
1329
+ } catch {
1330
+ if (this.adapter.isOpen()) {
1331
+ if (window && window.console) {
1332
+ console.error("Server unreachable from heartbeat.");
1333
+ }
1334
+ this.onheartbeattimeout();
1335
+ this.adapter.close();
1336
+ }
1337
+
1338
+ return;
1339
+ }
1340
+
1341
+ // reuse the timeout as the interval for now.
1342
+ // we can separate them out into separate values if needed later.
1343
+ setTimeout(() => this.pingPong(), this._heartbeatTimeoutMs);
1344
+ }
1345
+ };