@softtynet/zca-js 2.3.4 → 2.3.6

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 (129) hide show
  1. package/README.md +47 -11
  2. package/dist/apis/call/addUserGroupCall.d.ts +11 -0
  3. package/dist/apis/call/addUserGroupCall.js +48 -0
  4. package/dist/apis/call/answerAckVoiceCall.d.ts +5 -0
  5. package/dist/apis/call/answerAckVoiceCall.js +38 -0
  6. package/dist/apis/call/answerGroupCall.d.ts +10 -0
  7. package/dist/apis/call/answerGroupCall.js +45 -0
  8. package/dist/apis/call/answerVoiceCall.d.ts +11 -0
  9. package/dist/apis/call/answerVoiceCall.js +50 -0
  10. package/dist/apis/call/broadcastGroupCallState.d.ts +10 -0
  11. package/dist/apis/call/broadcastGroupCallState.js +45 -0
  12. package/dist/apis/call/cancelGroupCall.d.ts +10 -0
  13. package/dist/apis/call/cancelGroupCall.js +45 -0
  14. package/dist/apis/call/cancelVoiceCall.d.ts +1 -1
  15. package/dist/apis/call/cancelVoiceCall.js +5 -1
  16. package/dist/apis/call/createController.d.ts +7 -0
  17. package/dist/apis/call/createController.js +9 -0
  18. package/dist/apis/call/createRtcSession.d.ts +8 -0
  19. package/dist/apis/call/createRtcSession.js +10 -0
  20. package/dist/apis/call/endGroupCall.d.ts +10 -0
  21. package/dist/apis/call/endGroupCall.js +45 -0
  22. package/dist/apis/call/finishGroupCall.d.ts +12 -0
  23. package/dist/apis/call/finishGroupCall.js +47 -0
  24. package/dist/apis/call/getGroupCallState.d.ts +3 -0
  25. package/dist/apis/call/getGroupCallState.js +38 -0
  26. package/dist/apis/call/holdVoiceCall.d.ts +5 -0
  27. package/dist/apis/call/holdVoiceCall.js +34 -0
  28. package/dist/apis/call/joinGroupCall.d.ts +11 -0
  29. package/dist/apis/call/joinGroupCall.js +46 -0
  30. package/dist/apis/call/logEndVoiceCall.d.ts +8 -0
  31. package/dist/apis/call/logEndVoiceCall.js +46 -0
  32. package/dist/apis/call/notifyGroupCall.d.ts +9 -0
  33. package/dist/apis/call/notifyGroupCall.js +44 -0
  34. package/dist/apis/call/pingGroupCall.d.ts +10 -0
  35. package/dist/apis/call/pingGroupCall.js +45 -0
  36. package/dist/apis/call/requestAudioToVideoCall.d.ts +5 -0
  37. package/dist/apis/call/requestAudioToVideoCall.js +37 -0
  38. package/dist/apis/call/requestGroupCall.d.ts +9 -0
  39. package/dist/apis/call/requestGroupCall.js +46 -0
  40. package/dist/apis/call/requestShareScreenCall.d.ts +5 -0
  41. package/dist/apis/call/requestShareScreenCall.js +37 -0
  42. package/dist/apis/call/requestVoiceCall.d.ts +10 -0
  43. package/dist/apis/call/requestVoiceCall.js +47 -0
  44. package/dist/apis/call/ringRingGroupCall.d.ts +10 -0
  45. package/dist/apis/call/ringRingGroupCall.js +45 -0
  46. package/dist/apis/call/ringRingVoiceCall.d.ts +5 -0
  47. package/dist/apis/call/ringRingVoiceCall.js +38 -0
  48. package/dist/apis/call/sendRequestGroupCall.d.ts +11 -0
  49. package/dist/apis/call/sendRequestGroupCall.js +48 -0
  50. package/dist/apis/call/sendRequestVoiceCall.d.ts +11 -0
  51. package/dist/apis/call/sendRequestVoiceCall.js +51 -0
  52. package/dist/apis/call/sendVoiceCall.d.ts +8 -1
  53. package/dist/apis/call/sendVoiceCall.js +10 -8
  54. package/dist/apis/call/shareScreenGroupCall.d.ts +10 -0
  55. package/dist/apis/call/shareScreenGroupCall.js +45 -0
  56. package/dist/apis/call/unholdVoiceCall.d.ts +5 -0
  57. package/dist/apis/call/unholdVoiceCall.js +34 -0
  58. package/dist/apis/call/updateCallMediaState.d.ts +7 -0
  59. package/dist/apis/call/updateCallMediaState.js +61 -0
  60. package/dist/apis/sync/downloadTransferSync.js +19 -1
  61. package/dist/apis.d.ts +81 -0
  62. package/dist/apis.js +135 -0
  63. package/dist/call-engine/ZRTPPacketCodec.d.ts +262 -0
  64. package/dist/call-engine/ZRTPPacketCodec.js +506 -0
  65. package/dist/call-engine/ZaloCallController.d.ts +134 -0
  66. package/dist/call-engine/ZaloCallController.js +638 -0
  67. package/dist/call-engine/ZaloCallTransport.d.ts +83 -0
  68. package/dist/call-engine/ZaloCallTransport.js +259 -0
  69. package/dist/call-engine/ZaloRtcSession.d.ts +609 -0
  70. package/dist/call-engine/ZaloRtcSession.js +2939 -0
  71. package/dist/call-engine/ZaloSrtpSession.d.ts +80 -0
  72. package/dist/call-engine/ZaloSrtpSession.js +278 -0
  73. package/dist/call-engine/index.d.ts +18 -0
  74. package/dist/call-engine/index.js +24 -0
  75. package/dist/cjs/apis/call/addUserGroupCall.cjs +53 -0
  76. package/dist/cjs/apis/call/answerAckVoiceCall.cjs +43 -0
  77. package/dist/cjs/apis/call/answerGroupCall.cjs +50 -0
  78. package/dist/cjs/apis/call/answerVoiceCall.cjs +55 -0
  79. package/dist/cjs/apis/call/broadcastGroupCallState.cjs +50 -0
  80. package/dist/cjs/apis/call/cancelGroupCall.cjs +50 -0
  81. package/dist/cjs/apis/call/cancelVoiceCall.cjs +5 -1
  82. package/dist/cjs/apis/call/createController.cjs +14 -0
  83. package/dist/cjs/apis/call/createRtcSession.cjs +15 -0
  84. package/dist/cjs/apis/call/endGroupCall.cjs +50 -0
  85. package/dist/cjs/apis/call/finishGroupCall.cjs +52 -0
  86. package/dist/cjs/apis/call/getGroupCallState.cjs +43 -0
  87. package/dist/cjs/apis/call/holdVoiceCall.cjs +39 -0
  88. package/dist/cjs/apis/call/joinGroupCall.cjs +51 -0
  89. package/dist/cjs/apis/call/logEndVoiceCall.cjs +51 -0
  90. package/dist/cjs/apis/call/notifyGroupCall.cjs +49 -0
  91. package/dist/cjs/apis/call/pingGroupCall.cjs +50 -0
  92. package/dist/cjs/apis/call/requestAudioToVideoCall.cjs +42 -0
  93. package/dist/cjs/apis/call/requestGroupCall.cjs +51 -0
  94. package/dist/cjs/apis/call/requestShareScreenCall.cjs +42 -0
  95. package/dist/cjs/apis/call/requestVoiceCall.cjs +52 -0
  96. package/dist/cjs/apis/call/ringRingGroupCall.cjs +50 -0
  97. package/dist/cjs/apis/call/ringRingVoiceCall.cjs +43 -0
  98. package/dist/cjs/apis/call/sendRequestGroupCall.cjs +53 -0
  99. package/dist/cjs/apis/call/sendRequestVoiceCall.cjs +56 -0
  100. package/dist/cjs/apis/call/sendVoiceCall.cjs +10 -8
  101. package/dist/cjs/apis/call/shareScreenGroupCall.cjs +50 -0
  102. package/dist/cjs/apis/call/unholdVoiceCall.cjs +39 -0
  103. package/dist/cjs/apis/call/updateCallMediaState.cjs +66 -0
  104. package/dist/cjs/apis/sync/downloadTransferSync.cjs +19 -1
  105. package/dist/cjs/apis.cjs +135 -0
  106. package/dist/cjs/call-engine/ZRTPPacketCodec.cjs +525 -0
  107. package/dist/cjs/call-engine/ZaloCallController.cjs +643 -0
  108. package/dist/cjs/call-engine/ZaloCallTransport.cjs +265 -0
  109. package/dist/cjs/call-engine/ZaloRtcSession.cjs +2945 -0
  110. package/dist/cjs/call-engine/ZaloSrtpSession.cjs +287 -0
  111. package/dist/cjs/constants/protocol.cjs +1 -1
  112. package/dist/cjs/crypto/aes.cjs +3 -1
  113. package/dist/cjs/crypto/zdb-cipher.cjs +10 -3
  114. package/dist/cjs/index.cjs +61 -11
  115. package/dist/cjs/models/CallEvent.cjs +95 -1
  116. package/dist/cjs/realtime/handlers/control.handler.cjs +17 -3
  117. package/dist/cjs/realtime/listener.cjs +19 -0
  118. package/dist/constants/protocol.d.ts +1 -1
  119. package/dist/constants/protocol.js +1 -1
  120. package/dist/crypto/aes.js +3 -1
  121. package/dist/crypto/zdb-cipher.js +10 -3
  122. package/dist/index.d.ts +32 -4
  123. package/dist/index.js +2 -0
  124. package/dist/models/CallEvent.d.ts +15 -0
  125. package/dist/models/CallEvent.js +95 -1
  126. package/dist/realtime/handlers/control.handler.js +17 -3
  127. package/dist/realtime/listener.d.ts +5 -0
  128. package/dist/realtime/listener.js +19 -0
  129. package/package.json +2 -1
@@ -167,5 +167,7 @@ export function encryptPin(pin) {
167
167
  }
168
168
  export function validatePin(encryptedPin, pin) {
169
169
  const hash = crypto.createHash("md5").update(pin).digest("hex");
170
- return hash === encryptedPin;
170
+ const a = Buffer.from(hash, "utf8");
171
+ const b = Buffer.from(String(encryptedPin), "utf8");
172
+ return a.length === b.length && crypto.timingSafeEqual(a, b);
171
173
  }
@@ -146,6 +146,9 @@ export function parseZdbHeader(zdbPlaintext) {
146
146
  throw new ZaloApiError("Buffer is not a valid decrypted ZDB4.0 container");
147
147
  }
148
148
  const count = zdbPlaintext.readUInt32BE(COUNT_OFFSET);
149
+ if (count > 100000) {
150
+ throw new ZaloApiError(`ZDB4.0 header entry count exceeds safety limit (${count})`);
151
+ }
149
152
  let offset = COUNT_OFFSET + 4;
150
153
  const entries = [];
151
154
  for (let i = 0; i < count; i++) {
@@ -153,12 +156,16 @@ export function parseZdbHeader(zdbPlaintext) {
153
156
  throw new ZaloApiError("Truncated ZDB4.0 header while reading entry name length");
154
157
  }
155
158
  const nameLen = zdbPlaintext.readUInt32BE(offset);
156
- if (offset + 4 + nameLen + 4 > zdbPlaintext.length) {
157
- throw new ZaloApiError("Truncated ZDB4.0 header while reading entry metadata");
159
+ if (nameLen > 4096 || offset + 4 + nameLen + 4 > zdbPlaintext.length) {
160
+ throw new ZaloApiError("Truncated or invalid ZDB4.0 header while reading entry metadata");
158
161
  }
159
- const name = zdbPlaintext
162
+ const rawName = zdbPlaintext
160
163
  .toString("utf8", offset + 4, offset + 4 + nameLen)
161
164
  .replace(/\0+$/, "");
165
+ const name = rawName.split(/[\\/]/).pop() || rawName;
166
+ if (name === ".." || name === "." || name.includes("..")) {
167
+ throw new ZaloApiError(`Unsafe entry name in ZDB4.0 header: ${rawName}`);
168
+ }
162
169
  const size = zdbPlaintext.readUInt32BE(offset + 4 + nameLen);
163
170
  entries.push({ name, size });
164
171
  offset += 4 + nameLen + 4;
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./models/index.js";
3
3
  export * from "./constants/index.js";
4
4
  export * from "./crypto/index.js";
5
5
  export * from "./core/index.js";
6
+ export * from "./realtime/index.js";
6
7
  export * from "./zalo.js";
7
8
  export type { AuthDomainAPI, BoardDomainAPI, BusinessDomainAPI, CallDomainAPI, ChatDomainAPI, FriendDomainAPI, GroupDomainAPI, MediaDomainAPI, ProfileDomainAPI, StickerDomainAPI, SyncDomainAPI, ZcloudDomainAPI, } from "./apis.js";
8
9
  export type { ContextSession, ContextBase, AppContextExtended, AppContextBase, Options, ZPWServiceMap, ImageMetadataGetter, ImageMetadataGetterResponse, ViewerKeyCacheEntry } from "./context.js";
@@ -100,6 +101,7 @@ export type { GetListBankResponse } from "./apis/business/getListBank.js";
100
101
  export type { GetListBankAccountResponse } from "./apis/business/getListBankAccount.js";
101
102
  export type { BoardItem, GetListBoardResponse, ListBoardOptions } from "./apis/board/getListBoard.js";
102
103
  export type { GetListDeviceResponse } from "./apis/auth/getListDevice.js";
104
+ export type { GetListPinTopicsResponse } from "./apis/board/getListPinTopics.js";
103
105
  export type { GetListReminderResponse, ListReminderOptions, ReminderListGroup, ReminderListUser } from "./apis/board/getListReminder.js";
104
106
  export type { GetMultiUsersByPhonesResponse } from "./apis/friend/getMultiUsersByPhones.js";
105
107
  export type { GetMuteResponse, MuteEntriesInfo } from "./apis/chat/getMute.js";
@@ -160,7 +162,7 @@ export type { SendStickerResponse, SendStickerPayload } from "./apis/chat/sendSt
160
162
  export type { SendTypingEventResponse } from "./apis/chat/sendTypingEvent.js";
161
163
  export type { SendVideoOptions, SendVideoResponse } from "./apis/chat/sendVideo.js";
162
164
  export type { SendVoiceOptions, SendVoiceResponse } from "./apis/chat/sendVoice.js";
163
- export type { RequestCallServerInfo, SendVoiceCallOptions, SendVoiceCallResponse } from "./apis/call/sendVoiceCall.js";
165
+ export type { RequestCallServerEntry, RequestCallServerInfo, SendVoiceCallOptions, SendVoiceCallResponse } from "./apis/call/sendVoiceCall.js";
164
166
  export type { SetHiddenConversationsResponse } from "./apis/chat/setHiddenConversations.js";
165
167
  export type { SetMuteParams, SetMuteResponse } from "./apis/chat/setMute.js";
166
168
  export type { SetPinnedConversationsResponse } from "./apis/chat/setPinnedConversations.js";
@@ -190,15 +192,15 @@ export type { VotePollResponse } from "./apis/board/votePoll.js";
190
192
  export type { CustomAPICallback, CustomAPIProps } from "./apis/custom.js";
191
193
  export type { ClearUnreadFriendRequestsResponse } from "./apis/friend/clearUnreadFriendRequests.js";
192
194
  export type { EncryptGidsResponse } from "./apis/auth/encryptGids.js";
193
- export type { GetAliasListV2Response } from "./apis/friend/getAliasListV2.js";
195
+ export type { AliasItemV2, GetAliasListV2Response } from "./apis/friend/getAliasListV2.js";
194
196
  export type { GetBlockFriendsResponse } from "./apis/friend/getBlockFriends.js";
195
197
  export type { GetCloudInfoResponse } from "./apis/zcloud/getCloudInfo.js";
196
198
  export type { GetCloudSettingsResponse } from "./apis/zcloud/getCloudSettings.js";
197
199
  export type { GetCloudViewerKeyResponse } from "./apis/zcloud/getCloudViewerKey.js";
198
200
  export type { GetConversationMediaOptions, GetConversationMediaResponse, MediaStoreItem, MediaStoreType, } from "./apis/media/getConversationMedia.js";
199
- export type { GetEmojiStatusConfigResponse } from "./apis/profile/getEmojiStatusConfig.js";
201
+ export type { EmojiStatusItem, GetEmojiStatusConfigResponse } from "./apis/profile/getEmojiStatusConfig.js";
200
202
  export type { GetExtraFriendInfoResponse } from "./apis/friend/getExtraFriendInfo.js";
201
- export type { GetExtraGroupInfoResponse } from "./apis/group/getExtraGroupInfo.js";
203
+ export type { ExtraContextInfo, GetExtraGroupInfoResponse } from "./apis/group/getExtraGroupInfo.js";
202
204
  export type { GetFamilyProfileResponse } from "./apis/zcloud/getFamilyProfile.js";
203
205
  export type { GetFamilyUsageResponse } from "./apis/zcloud/getFamilyUsage.js";
204
206
  export type { GetFamilyViewerKeyResponse } from "./apis/zcloud/getFamilyViewerKey.js";
@@ -229,6 +231,31 @@ export type { UpdateRecentSearchOptions, UpdateRecentSearchResponse } from "./ap
229
231
  export type { VerifyCloudMediaOptions, VerifyCloudMediaResponse } from "./apis/zcloud/verifyCloudMedia.js";
230
232
  export type { VoiceToTextResponse } from "./apis/media/voiceToText.js";
231
233
  export type { Voice2TextEvent, Voice2TextEventData } from "./apis/listen.js";
234
+ export type { AddUserGroupCallOptions, AddUserGroupCallResponse } from "./apis/call/addUserGroupCall.js";
235
+ export type { AnswerAckVoiceCallOptions, AnswerAckVoiceCallResponse } from "./apis/call/answerAckVoiceCall.js";
236
+ export type { AnswerGroupCallOptions, AnswerGroupCallResponse } from "./apis/call/answerGroupCall.js";
237
+ export type { AnswerVoiceCallOptions, AnswerVoiceCallResponse } from "./apis/call/answerVoiceCall.js";
238
+ export type { BroadcastGroupCallStateOptions, BroadcastGroupCallStateResponse } from "./apis/call/broadcastGroupCallState.js";
239
+ export type { CancelGroupCallOptions, CancelGroupCallResponse } from "./apis/call/cancelGroupCall.js";
240
+ export type { EndGroupCallOptions, EndGroupCallResponse } from "./apis/call/endGroupCall.js";
241
+ export type { FinishGroupCallOptions, FinishGroupCallResponse } from "./apis/call/finishGroupCall.js";
242
+ export type { GetGroupCallStateResponse } from "./apis/call/getGroupCallState.js";
243
+ export type { HoldVoiceCallOptions, HoldVoiceCallResponse } from "./apis/call/holdVoiceCall.js";
244
+ export type { JoinGroupCallOptions, JoinGroupCallResponse } from "./apis/call/joinGroupCall.js";
245
+ export type { LogEndVoiceCallOptions, LogEndVoiceCallResponse } from "./apis/call/logEndVoiceCall.js";
246
+ export type { NotifyGroupCallOptions, NotifyGroupCallResponse } from "./apis/call/notifyGroupCall.js";
247
+ export type { PingGroupCallOptions, PingGroupCallResponse } from "./apis/call/pingGroupCall.js";
248
+ export type { RequestAudioToVideoCallOptions, RequestAudioToVideoCallResponse } from "./apis/call/requestAudioToVideoCall.js";
249
+ export type { RequestGroupCallOptions, RequestGroupCallResponse } from "./apis/call/requestGroupCall.js";
250
+ export type { RequestShareScreenCallOptions, RequestShareScreenCallResponse } from "./apis/call/requestShareScreenCall.js";
251
+ export type { RequestVoiceCallOptions, RequestVoiceCallResponse } from "./apis/call/requestVoiceCall.js";
252
+ export type { RingRingGroupCallOptions, RingRingGroupCallResponse } from "./apis/call/ringRingGroupCall.js";
253
+ export type { RingRingVoiceCallOptions, RingRingVoiceCallResponse } from "./apis/call/ringRingVoiceCall.js";
254
+ export type { SendRequestGroupCallOptions, SendRequestGroupCallResponse } from "./apis/call/sendRequestGroupCall.js";
255
+ export type { SendRequestVoiceCallOptions, SendRequestVoiceCallResponse } from "./apis/call/sendRequestVoiceCall.js";
256
+ export type { ShareScreenGroupCallOptions, ShareScreenGroupCallResponse } from "./apis/call/shareScreenGroupCall.js";
257
+ export type { UnholdVoiceCallOptions, UnholdVoiceCallResponse } from "./apis/call/unholdVoiceCall.js";
258
+ export type { UpdateCallMediaStateOptions, UpdateCallMediaStateResponse } from "./apis/call/updateCallMediaState.js";
232
259
  export { CloseReason } from "./apis/listen.js";
233
260
  export { LoginQRCallbackEventType } from "./apis/loginQR.js";
234
261
  export { FriendRecommendationsType } from "./apis/friend/getFriendRecommendations.js";
@@ -240,4 +267,5 @@ export { ChatTTL } from "./apis/chat/updateAutoDeleteChat.js";
240
267
  export { UpdateLangAvailableLanguages } from "./apis/auth/updateLang.js";
241
268
  export { UpdateSettingsType } from "./apis/profile/updateSettings.js";
242
269
  export { CallType } from "./apis/call/sendVoiceCall.js";
270
+ export { DEFAULT_ZALOCALL_IPC_KEY_BASE64, DEFAULT_ZALO_AUDIO_CODEC, DEFAULT_ZALO_VIDEO_CODEC, ZRTCMediaSubCommand, ZRTPControlCommand, ZRTPForwardSubCommand, ZRTPLegacyMediaType, ZRTCRole, ZaloCallController, ZaloCallTransport, ZaloRtcSession, ZaloSrtpSession, buildEchoRequest, buildEndCallRequest, buildInitCallRequest, buildInitCallResponse, buildPingRequest, buildPingResponse, buildRelayPingRequest, buildRequestForwardPacket, buildRtpPacket, buildZrtcExtendData, deriveSrtpSessionKey, generateSrtpMasterKeyBase64, parseIncomingCallEvent, parseRtpPacket, parseZRTPPacket, uidToUint32, wrapLegacyMediaPacket, wrapZrtcMediaPacket, type AcceptIncomingCallOptions, type BuildRtpPacketOptions, type IncomingAudioFrameEvent, type IncomingRtcpEvent, type IncomingRtpEvent, type IncomingVideoAnnexBFrameEvent, type IncomingVideoFrameEvent, type JoinGroupCallSessionOptions, type MakeDesktopCallOptions, type MakeDesktopGroupCallOptions, type ParsedIncomingCallInfo, type ParsedRtpPacket, type ParsedZRTPPacket, type RejectIncomingCallOptions, type SrtpCryptoSuite, type StartGroupCallOptions, type StartOutgoingCallOptions, type ZRTCMultiplexedMediaPacket, type ZRTCP2PPacket, type ZRTPControlPacket, type ZRTPEchoRequestOptions, type ZRTPEndCallRequestOptions, type ZRTPInitCallRequestOptions, type ZRTPInitCallResponseOptions, type ZRTPLegacyMediaPacket, type ZRTPPingRequestOptions, type ZRTPRawPacket, type ZRTPRelayPingRequestOptions, type ZRTPRequestForwardOptions, type ZaloCallConnectionParams, type ZaloCallControllerEvents, type ZaloCallControllerOptions, type ZaloCallIpcMessage, type ZaloCallMediaStateEvent, type ZaloCallSignalPayload, type ZaloCallTransportEvents, type ZaloCallTransportOptions, type ZaloMobileDirectHandoffBundle, type ZaloRtcSessionEvents, type ZaloRtcSessionOptions, type ZaloRtcSessionState, type ZrtcExtendDataOptions, } from "./call-engine/index.js";
243
271
  export { generateRSAKeyPair, decryptWithPrivateKey, deriveZdbAesKey, decryptZdbBuffer, parseZdbHeader, encryptZCloudAES, decryptZCloudAES, preParseJsonIds, type ZdbTocEntry, } from "./utils.js";
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ export * from "./models/index.js";
3
3
  export * from "./constants/index.js";
4
4
  export * from "./crypto/index.js";
5
5
  export * from "./core/index.js";
6
+ export * from "./realtime/index.js";
6
7
  export * from "./zalo.js";
7
8
  // Others (Enum)
8
9
  export { CloseReason } from "./apis/listen.js";
@@ -16,4 +17,5 @@ export { ChatTTL } from "./apis/chat/updateAutoDeleteChat.js";
16
17
  export { UpdateLangAvailableLanguages } from "./apis/auth/updateLang.js";
17
18
  export { UpdateSettingsType } from "./apis/profile/updateSettings.js";
18
19
  export { CallType } from "./apis/call/sendVoiceCall.js";
20
+ export { DEFAULT_ZALOCALL_IPC_KEY_BASE64, DEFAULT_ZALO_AUDIO_CODEC, DEFAULT_ZALO_VIDEO_CODEC, ZRTCMediaSubCommand, ZRTPControlCommand, ZRTPForwardSubCommand, ZRTPLegacyMediaType, ZRTCRole, ZaloCallController, ZaloCallTransport, ZaloRtcSession, ZaloSrtpSession, buildEchoRequest, buildEndCallRequest, buildInitCallRequest, buildInitCallResponse, buildPingRequest, buildPingResponse, buildRelayPingRequest, buildRequestForwardPacket, buildRtpPacket, buildZrtcExtendData, deriveSrtpSessionKey, generateSrtpMasterKeyBase64, parseIncomingCallEvent, parseRtpPacket, parseZRTPPacket, uidToUint32, wrapLegacyMediaPacket, wrapZrtcMediaPacket, } from "./call-engine/index.js";
19
21
  export { generateRSAKeyPair, decryptWithPrivateKey, deriveZdbAesKey, decryptZdbBuffer, parseZdbHeader, encryptZCloudAES, decryptZCloudAES, preParseJsonIds, } from "./utils.js";
@@ -1,11 +1,24 @@
1
1
  export declare enum CallEventType {
2
2
  REQUEST = "request",
3
3
  ANSWER = "answer",
4
+ ANSWER_ACK = "answer_ack",
4
5
  CANCEL = "cancel",
5
6
  END = "end",
6
7
  RINGRING = "ringring",
8
+ ONOFF_CAMERA = "onoff_camera",
9
+ MUTE_AUDIO = "mute_audio",
10
+ AUDIO_TO_VIDEO = "audio_to_video",
11
+ SHARE_SCREEN = "share_screen",
7
12
  GROUP_REQUEST = "group_request",
13
+ GROUP_RINGRING = "group_ring_ring",
8
14
  GROUP_ANSWER = "group_answer",
15
+ GROUP_ANSWER_ACK = "group_answer_ack",
16
+ GROUP_CANCEL = "group_cancel",
17
+ GROUP_END = "group_end_call",
18
+ GROUP_ADD_USER = "group_add_user",
19
+ GROUP_NOTIFY = "group_notify",
20
+ GROUP_BROADCAST = "group_broadcast",
21
+ GROUP_BROADCAST_CONFIG = "group_broadcast_config",
9
22
  UNKNOWN = "unknown"
10
23
  }
11
24
  export type TCallEventData = {
@@ -18,6 +31,8 @@ export type TCallEventData = {
18
31
  sessId?: string;
19
32
  status?: number;
20
33
  callType?: number;
34
+ codec?: string;
35
+ params?: string | Record<string, unknown>;
21
36
  ts?: number | string;
22
37
  [key: string]: unknown;
23
38
  };
@@ -2,11 +2,24 @@ export var CallEventType;
2
2
  (function (CallEventType) {
3
3
  CallEventType["REQUEST"] = "request";
4
4
  CallEventType["ANSWER"] = "answer";
5
+ CallEventType["ANSWER_ACK"] = "answer_ack";
5
6
  CallEventType["CANCEL"] = "cancel";
6
7
  CallEventType["END"] = "end";
7
8
  CallEventType["RINGRING"] = "ringring";
9
+ CallEventType["ONOFF_CAMERA"] = "onoff_camera";
10
+ CallEventType["MUTE_AUDIO"] = "mute_audio";
11
+ CallEventType["AUDIO_TO_VIDEO"] = "audio_to_video";
12
+ CallEventType["SHARE_SCREEN"] = "share_screen";
8
13
  CallEventType["GROUP_REQUEST"] = "group_request";
14
+ CallEventType["GROUP_RINGRING"] = "group_ring_ring";
9
15
  CallEventType["GROUP_ANSWER"] = "group_answer";
16
+ CallEventType["GROUP_ANSWER_ACK"] = "group_answer_ack";
17
+ CallEventType["GROUP_CANCEL"] = "group_cancel";
18
+ CallEventType["GROUP_END"] = "group_end_call";
19
+ CallEventType["GROUP_ADD_USER"] = "group_add_user";
20
+ CallEventType["GROUP_NOTIFY"] = "group_notify";
21
+ CallEventType["GROUP_BROADCAST"] = "group_broadcast";
22
+ CallEventType["GROUP_BROADCAST_CONFIG"] = "group_broadcast_config";
10
23
  CallEventType["UNKNOWN"] = "unknown";
11
24
  })(CallEventType || (CallEventType = {}));
12
25
  export function initializeCallEvent(data, act, act_type) {
@@ -18,30 +31,111 @@ export function initializeCallEvent(data, act, act_type) {
18
31
  case "answer":
19
32
  type = CallEventType.ANSWER;
20
33
  break;
34
+ case "answer_ack":
35
+ case "answerack":
36
+ type = CallEventType.ANSWER_ACK;
37
+ break;
21
38
  case "cancel":
22
39
  type = CallEventType.CANCEL;
23
40
  break;
24
41
  case "end":
25
42
  case "endcall":
43
+ case "end_call":
26
44
  type = CallEventType.END;
27
45
  break;
28
46
  case "ringring":
47
+ case "ring_ring":
29
48
  type = CallEventType.RINGRING;
30
49
  break;
50
+ case "onoff_camera":
51
+ type = CallEventType.ONOFF_CAMERA;
52
+ break;
53
+ case "mute_audio":
54
+ type = CallEventType.MUTE_AUDIO;
55
+ break;
56
+ case "audio_to_video":
57
+ type = CallEventType.AUDIO_TO_VIDEO;
58
+ break;
59
+ case "share_screen":
60
+ type = CallEventType.SHARE_SCREEN;
61
+ break;
31
62
  case "group_request":
32
63
  type = CallEventType.GROUP_REQUEST;
33
64
  break;
65
+ case "group_ring_ring":
66
+ case "group_ringring":
67
+ type = CallEventType.GROUP_RINGRING;
68
+ break;
34
69
  case "group_answer":
35
70
  type = CallEventType.GROUP_ANSWER;
36
71
  break;
72
+ case "group_answer_ack":
73
+ type = CallEventType.GROUP_ANSWER_ACK;
74
+ break;
75
+ case "group_cancel":
76
+ type = CallEventType.GROUP_CANCEL;
77
+ break;
78
+ case "group_end_call":
79
+ case "group_endcall":
80
+ case "group_end":
81
+ type = CallEventType.GROUP_END;
82
+ break;
83
+ case "group_add_user":
84
+ type = CallEventType.GROUP_ADD_USER;
85
+ break;
86
+ case "group_notify":
87
+ type = CallEventType.GROUP_NOTIFY;
88
+ break;
89
+ case "group_broadcast":
90
+ type = CallEventType.GROUP_BROADCAST;
91
+ break;
92
+ case "group_broadcast_config":
93
+ type = CallEventType.GROUP_BROADCAST_CONFIG;
94
+ break;
37
95
  default:
38
96
  type = CallEventType.UNKNOWN;
39
97
  break;
40
98
  }
99
+ const enrichedData = { ...data };
100
+ let parsedParams;
101
+ if (typeof enrichedData.params === "string") {
102
+ try {
103
+ const p = JSON.parse(enrichedData.params);
104
+ if (p && typeof p === "object")
105
+ parsedParams = p;
106
+ }
107
+ catch {
108
+ // Ignore invalid JSON
109
+ }
110
+ }
111
+ else if (enrichedData.params && typeof enrichedData.params === "object") {
112
+ parsedParams = enrichedData.params;
113
+ }
114
+ if (enrichedData.callId === undefined) {
115
+ const extractedCallId = Number(enrichedData.call_id ??
116
+ enrichedData.id ??
117
+ parsedParams?.callId ??
118
+ parsedParams?.call_id ??
119
+ parsedParams?.id ??
120
+ 0);
121
+ if (extractedCallId > 0) {
122
+ enrichedData.callId = extractedCallId;
123
+ }
124
+ }
125
+ if (enrichedData.callerId === undefined) {
126
+ const extractedCallerId = enrichedData.uidN ??
127
+ parsedParams?.uidN ??
128
+ enrichedData.uidFrom ??
129
+ enrichedData.fromId ??
130
+ parsedParams?.uidFrom;
131
+ if (extractedCallerId !== undefined) {
132
+ enrichedData.callerId = String(extractedCallerId);
133
+ }
134
+ }
41
135
  return {
42
136
  type,
43
137
  act,
44
138
  act_type,
45
- data,
139
+ data: enrichedData,
46
140
  };
47
141
  }
@@ -4,10 +4,15 @@ import { initializeGroupEvent } from "../../models/GroupEvent.js";
4
4
  import { initializeSyncEvent } from "../../models/SyncEvent.js";
5
5
  import { decodeEventData, getFriendEventType, getGroupEventType } from "../../utils.js";
6
6
  export async function handleRealtimeControlPacket(listener, ctx, selfListen, version, cmd, subCmd, parsed, cipherKey) {
7
- if (version == 1 && cmd == 601 && subCmd == 0) {
8
- const parsedData = (await decodeEventData(parsed, cipherKey)).data;
9
- const { controls } = parsedData;
7
+ if (version == 1 && (cmd == 601 || cmd == 603 || cmd == 604) && subCmd == 0) {
8
+ const decoded = await decodeEventData(parsed, cipherKey);
9
+ const parsedData = decoded?.data;
10
+ const controls = parsedData?.controls;
11
+ if (!Array.isArray(controls))
12
+ return false;
10
13
  for (const control of controls) {
14
+ if (!control?.content)
15
+ continue;
11
16
  if (control.content.act_type == "file_done") {
12
17
  const data = {
13
18
  fileUrl: control.content.data.url,
@@ -58,6 +63,15 @@ export async function handleRealtimeControlPacket(listener, ctx, selfListen, ver
58
63
  const callEventData = typeof control.content.data == "string"
59
64
  ? JSON.parse(control.content.data)
60
65
  : control.content.data;
66
+ // Bỏ qua các gói mời gọi cũ (> 60s) nằm trong hàng đợi offline (cmd 603 / 604)
67
+ if ((cmd == 603 || cmd == 604) &&
68
+ (control.content.act == "request" || control.content.act == "group_request") &&
69
+ callEventData?.ts) {
70
+ const eventTs = Number.parseInt(String(callEventData.ts), 10);
71
+ if (Number.isFinite(eventTs) && Date.now() - eventTs > 60_000) {
72
+ continue;
73
+ }
74
+ }
61
75
  const callEvent = initializeCallEvent(callEventData, control.content.act, control.content.act_type);
62
76
  listener.emit("call_event", callEvent);
63
77
  }
@@ -66,5 +66,10 @@ export declare class Listener extends EventEmitter<ListenerEvents> {
66
66
  * @param lastMsgId Optional cursor message ID
67
67
  */
68
68
  requestOldReactions(threadType: ThreadType, lastMsgId?: string | null): void;
69
+ /**
70
+ * Kích hoạt và kéo hàng đợi sự kiện điều khiển / VoIP (`cmd 603` CTRL_PULL_CTRL và `cmd 604` CTRL_PULL_VOIP).
71
+ * Giúp nhận ngay các cuộc gọi đến đang đổ chuông ngay cả khi vừa mở kết nối WebSocket.
72
+ */
73
+ requestOfflineVoipControls(): void;
69
74
  private reset;
70
75
  }
@@ -253,6 +253,7 @@ export class Listener extends EventEmitter {
253
253
  if (version == 1 && cmd == 1 && subCmd == 1 && hasOwn(parsed, "key")) {
254
254
  this.cipherKey = parsed.key;
255
255
  this.emit("cipher_key", this.cipherKey);
256
+ this.requestOfflineVoipControls();
256
257
  if (this.pingInterval)
257
258
  clearInterval(this.pingInterval);
258
259
  const ping = () => {
@@ -358,6 +359,24 @@ export class Listener extends EventEmitter {
358
359
  };
359
360
  this.sendWs(payload);
360
361
  }
362
+ /**
363
+ * Kích hoạt và kéo hàng đợi sự kiện điều khiển / VoIP (`cmd 603` CTRL_PULL_CTRL và `cmd 604` CTRL_PULL_VOIP).
364
+ * Giúp nhận ngay các cuộc gọi đến đang đổ chuông ngay cả khi vừa mở kết nối WebSocket.
365
+ */
366
+ requestOfflineVoipControls() {
367
+ this.sendWs({
368
+ version: 1,
369
+ cmd: 604,
370
+ subCmd: 0,
371
+ data: { first: true, lastId: 1, preIds: [] },
372
+ });
373
+ this.sendWs({
374
+ version: 1,
375
+ cmd: 603,
376
+ subCmd: 0,
377
+ data: { first: true, lastId: "1", preIds: [] },
378
+ });
379
+ }
361
380
  reset() {
362
381
  this.ws = null;
363
382
  this.cipherKey = undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softtynet/zca-js",
3
- "version": "2.3.4",
3
+ "version": "2.3.6",
4
4
  "description": "Zalo API client library for Node.js and Bun, maintained by Softtynet.",
5
5
  "main": "dist/cjs/index.cjs",
6
6
  "module": "dist/index.js",
@@ -29,6 +29,7 @@
29
29
  "typecheck": "tsc --noEmit && tsc -p test/tsconfig.json --noEmit && tsc -p examples/tsconfig.json --noEmit && tsc -p docs/tsconfig.json --noEmit",
30
30
  "test:verify": "npm run typecheck && npx --yes tsx test/verify_upgrades.ts",
31
31
  "test:live": "npx --yes tsx test/verify_live.ts",
32
+ "test:call-studio": "npm run build && npx --yes tsx test/call_studio_server.ts",
32
33
  "docs:gen": "node scripts/generateDocs.js",
33
34
  "docs:dev": "node scripts/generateDocs.js && vitepress dev docs",
34
35
  "docs:build": "node scripts/generateDocs.js && vitepress build docs",