@whanext/core 0.19.2 → 0.19.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/CHANGELOG.md +13 -0
- package/dist/index.js +119 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.3
|
|
4
|
+
### Corrigido
|
|
5
|
+
- Carregamento lazy do plugin VoIP do Zapo para evitar importar o runtime WebRTC em consumidores e testes que não inicializam o provider.
|
|
6
|
+
- Ajustes de tipagem dos testes com `exactOptionalPropertyTypes`.
|
|
7
|
+
- Provider Zapo agora usa `@zapo-js/voip` como único caminho de chamadas: eventos `voip_*` e `client.voip.rejectCall()`, sem fallback silencioso.
|
|
8
|
+
- `messageEdited` também reconhece edições criptografadas descriptografadas pelo Zapo em `message_addon`, além de `message_protocol`.
|
|
9
|
+
- `messageDeleted` e `messageEdited` ignoram protocolo de backlog durante bootstrap quando `processOfflineMessages` está desativado.
|
|
10
|
+
- Mensagens recebidas antes de `connection: open` deixam de ser publicadas como mensagens ao vivo; ainda entram no cache limitado para permitir recuperação posterior.
|
|
11
|
+
- Eventos `message` duplicados no mesmo runtime são descartados antes de chegar aos consumidores, evitando downloads repetidos de mídia/ViewOnce.
|
|
12
|
+
|
|
13
|
+
### Compatibilidade
|
|
14
|
+
- Mudança corretiva e aditiva; a API pública de `CallEvent`, `messageDeleted` e `messageEdited` permanece inalterada.
|
|
15
|
+
|
|
3
16
|
## 0.19.2
|
|
4
17
|
|
|
5
18
|
- Corrigido o download real de mídias citadas no provider Zapo: `downloadMedia()` agora entrega o `Proto.IMessage` bruto diretamente ao `downloadBytes()`, como suportado pela API do Zapo.
|
package/dist/index.js
CHANGED
|
@@ -2708,9 +2708,10 @@ var ZapoProvider = class {
|
|
|
2708
2708
|
#logger;
|
|
2709
2709
|
#messageStore = /* @__PURE__ */ new Map();
|
|
2710
2710
|
#messageKeyStore = /* @__PURE__ */ new WeakMap();
|
|
2711
|
+
#deliveredMessageStore = /* @__PURE__ */ new Set();
|
|
2712
|
+
#handledProtocolStore = /* @__PURE__ */ new Set();
|
|
2711
2713
|
#messageCacheSize;
|
|
2712
2714
|
#client;
|
|
2713
|
-
#voip;
|
|
2714
2715
|
#intentionalClose = false;
|
|
2715
2716
|
#reconnectAttempt = 0;
|
|
2716
2717
|
#reconnectTimer;
|
|
@@ -2965,15 +2966,8 @@ var ZapoProvider = class {
|
|
|
2965
2966
|
await presence.sendChatstate(chatId, { state: value });
|
|
2966
2967
|
}
|
|
2967
2968
|
async rejectCall(callId, _from) {
|
|
2968
|
-
this.#requireClient();
|
|
2969
|
-
|
|
2970
|
-
throw new WhaNextError(
|
|
2971
|
-
"PROVIDER_ERROR",
|
|
2972
|
-
"WhatsApp call support is unavailable because the Zapo VoIP plugin could not be loaded.",
|
|
2973
|
-
{ recoverable: true }
|
|
2974
|
-
);
|
|
2975
|
-
}
|
|
2976
|
-
await this.#voip.rejectCall(callId);
|
|
2969
|
+
const client = this.#requireClient();
|
|
2970
|
+
await client.voip.rejectCall(callId);
|
|
2977
2971
|
}
|
|
2978
2972
|
async #ensureClient() {
|
|
2979
2973
|
if (this.#client) return this.#client;
|
|
@@ -3002,15 +2996,8 @@ var ZapoProvider = class {
|
|
|
3002
2996
|
messageSecret: "sqlite"
|
|
3003
2997
|
}
|
|
3004
2998
|
});
|
|
3005
|
-
const
|
|
3006
|
-
|
|
3007
|
-
const { voipPlugin } = await import("@zapo-js/voip");
|
|
3008
|
-
plugins.push(voipPlugin({ logLevel: "warn" }));
|
|
3009
|
-
} catch (error) {
|
|
3010
|
-
this.#logger.warn("Zapo VoIP support is unavailable; call events and rejection are disabled.", {
|
|
3011
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3012
|
-
});
|
|
3013
|
-
}
|
|
2999
|
+
const { voipPlugin } = await import("@zapo-js/voip");
|
|
3000
|
+
const voip = voipPlugin({ logLevel: "warn" });
|
|
3014
3001
|
const client = new WaClient({
|
|
3015
3002
|
store,
|
|
3016
3003
|
sessionId: this.#options.sessionId ?? "default",
|
|
@@ -3023,10 +3010,9 @@ var ZapoProvider = class {
|
|
|
3023
3010
|
persistAllSecrets: true
|
|
3024
3011
|
},
|
|
3025
3012
|
media: { processor: createMediaProcessor() },
|
|
3026
|
-
plugins
|
|
3013
|
+
plugins: [voip]
|
|
3027
3014
|
}, new WhaNextZapoLogger(this.#logger));
|
|
3028
3015
|
this.#client = client;
|
|
3029
|
-
this.#voip = client.voip;
|
|
3030
3016
|
this.#bind(client);
|
|
3031
3017
|
return client;
|
|
3032
3018
|
}
|
|
@@ -3058,49 +3044,60 @@ var ZapoProvider = class {
|
|
|
3058
3044
|
client.on("message_protocol", (event) => {
|
|
3059
3045
|
this.#handleProtocolEvent(event);
|
|
3060
3046
|
});
|
|
3047
|
+
client.on("message_addon", (event) => {
|
|
3048
|
+
this.#handleAddonEvent(event);
|
|
3049
|
+
});
|
|
3061
3050
|
client.on("group", (event) => {
|
|
3062
3051
|
this.#handleGroupEvent(event);
|
|
3063
3052
|
});
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
}
|
|
3053
|
+
const voipClient = client;
|
|
3054
|
+
voipClient.on("voip_call_incoming", (event) => {
|
|
3055
|
+
const call = this.#normalizeVoipCall(event, "offer");
|
|
3056
|
+
if (call) void this.#events.emit("call", call);
|
|
3057
|
+
});
|
|
3058
|
+
voipClient.on("voip_call_state", (event) => {
|
|
3059
|
+
const state = event.stateData?.state;
|
|
3060
|
+
if (state === "incoming_ringing" || state === "ended") return;
|
|
3061
|
+
const call = this.#normalizeVoipCall(event);
|
|
3062
|
+
if (call) void this.#events.emit("call", call);
|
|
3063
|
+
});
|
|
3064
|
+
voipClient.on("voip_call_ended", (event) => {
|
|
3065
|
+
const call = this.#normalizeVoipCall(
|
|
3066
|
+
event,
|
|
3067
|
+
this.#callEndStatus(event.stateData?.endReason)
|
|
3068
|
+
);
|
|
3069
|
+
if (call) void this.#events.emit("call", call);
|
|
3070
|
+
});
|
|
3083
3071
|
client.on("connection", (event) => {
|
|
3084
3072
|
void this.#handleConnectionEvent(client, event);
|
|
3085
3073
|
});
|
|
3086
3074
|
}
|
|
3087
3075
|
#handleMessage(event) {
|
|
3088
3076
|
const stored = event;
|
|
3077
|
+
if (stored.key?.id && stored.message) this.#remember(stored);
|
|
3078
|
+
const quoted = extractQuotedZapoMessage(event);
|
|
3079
|
+
if (quoted?.key.id && quoted.message) {
|
|
3080
|
+
this.#remember(quoted);
|
|
3081
|
+
}
|
|
3089
3082
|
if (this.#isOfflineMessage(stored)) {
|
|
3090
|
-
this.#logger.debug("Ignored message queued before the current connection.", {
|
|
3083
|
+
this.#logger.debug("Ignored message queued before the current live connection.", {
|
|
3091
3084
|
messageId: stored.key.id ?? void 0,
|
|
3092
3085
|
chatId: stored.key.remoteJid ?? void 0,
|
|
3093
3086
|
timestampSeconds: stored.timestampSeconds ?? void 0
|
|
3094
3087
|
});
|
|
3095
3088
|
return;
|
|
3096
3089
|
}
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3090
|
+
const deliveryKey = this.#messageDeliveryKey(stored.key);
|
|
3091
|
+
if (stored.key.id && this.#deliveredMessageStore.has(deliveryKey)) {
|
|
3092
|
+
this.#logger.debug("Ignored duplicate Zapo message event.", {
|
|
3093
|
+
messageId: stored.key.id,
|
|
3094
|
+
chatId: stored.key.remoteJid ?? void 0
|
|
3095
|
+
});
|
|
3096
|
+
return;
|
|
3101
3097
|
}
|
|
3102
3098
|
const message = normalizeZapoMessage(event);
|
|
3103
3099
|
if (!message) return;
|
|
3100
|
+
if (stored.key.id) this.#rememberDeliveredMessage(deliveryKey);
|
|
3104
3101
|
this.#messageKeyStore.set(message.keys, stored);
|
|
3105
3102
|
if (message.quoted && quoted?.message) {
|
|
3106
3103
|
this.#messageKeyStore.set(
|
|
@@ -3110,7 +3107,50 @@ var ZapoProvider = class {
|
|
|
3110
3107
|
}
|
|
3111
3108
|
void this.#events.emit("message", message);
|
|
3112
3109
|
}
|
|
3110
|
+
#handleAddonEvent(event) {
|
|
3111
|
+
if (event.kind !== "message_edit" || !event.targetMessageId) return;
|
|
3112
|
+
const editedMessage = this.#addonEditedMessage(event.decrypted);
|
|
3113
|
+
if (!editedMessage) return;
|
|
3114
|
+
const target = {
|
|
3115
|
+
id: event.targetMessageId,
|
|
3116
|
+
...event.key.remoteJid !== void 0 ? { remoteJid: event.key.remoteJid } : {},
|
|
3117
|
+
...event.key.fromMe !== void 0 ? { fromMe: event.key.fromMe } : {},
|
|
3118
|
+
...event.key.participant !== void 0 ? { participant: event.key.participant } : {},
|
|
3119
|
+
...event.key.participantAlt !== void 0 ? { participantAlt: event.key.participantAlt } : {}
|
|
3120
|
+
};
|
|
3121
|
+
this.#handleProtocolEvent({
|
|
3122
|
+
key: event.key,
|
|
3123
|
+
...event.offline !== void 0 ? { offline: event.offline } : {},
|
|
3124
|
+
protocolMessage: {
|
|
3125
|
+
type: proto.Message.ProtocolMessage.Type.MESSAGE_EDIT,
|
|
3126
|
+
key: target,
|
|
3127
|
+
editedMessage
|
|
3128
|
+
}
|
|
3129
|
+
});
|
|
3130
|
+
}
|
|
3131
|
+
#addonEditedMessage(value) {
|
|
3132
|
+
if (!value || typeof value !== "object") return void 0;
|
|
3133
|
+
const record = value;
|
|
3134
|
+
const protocol = record.protocolMessage;
|
|
3135
|
+
if (protocol && typeof protocol === "object") {
|
|
3136
|
+
const edited2 = protocol.editedMessage;
|
|
3137
|
+
if (edited2 && typeof edited2 === "object") return edited2;
|
|
3138
|
+
}
|
|
3139
|
+
const edited = record.editedMessage;
|
|
3140
|
+
if (edited && typeof edited === "object") return edited;
|
|
3141
|
+
const message = record.message;
|
|
3142
|
+
if (message && typeof message === "object") return message;
|
|
3143
|
+
return value;
|
|
3144
|
+
}
|
|
3113
3145
|
#handleProtocolEvent(event) {
|
|
3146
|
+
if (this.#isOfflineMessage(event)) {
|
|
3147
|
+
this.#logger.debug("Ignored protocol event queued before the current live connection.", {
|
|
3148
|
+
messageId: event.key.id ?? void 0,
|
|
3149
|
+
chatId: event.key.remoteJid ?? void 0,
|
|
3150
|
+
timestampSeconds: event.timestampSeconds ?? void 0
|
|
3151
|
+
});
|
|
3152
|
+
return;
|
|
3153
|
+
}
|
|
3114
3154
|
const protocol = event.protocolMessage ?? event.message?.protocolMessage;
|
|
3115
3155
|
if (!protocol) return;
|
|
3116
3156
|
const protocolKey = protocol.key;
|
|
@@ -3127,7 +3167,16 @@ var ZapoProvider = class {
|
|
|
3127
3167
|
if (!target.remoteJid) return;
|
|
3128
3168
|
const stored = this.#findStoredMessage(target);
|
|
3129
3169
|
const type = protocol?.type;
|
|
3170
|
+
const mutationKey = this.#protocolDeliveryKey(event, target, type);
|
|
3171
|
+
if (mutationKey && this.#handledProtocolStore.has(mutationKey)) {
|
|
3172
|
+
this.#logger.debug("Ignored duplicate Zapo protocol event.", {
|
|
3173
|
+
messageId: event.key.id ?? void 0,
|
|
3174
|
+
targetMessageId: target.id ?? void 0
|
|
3175
|
+
});
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
3130
3178
|
if (type === proto.Message.ProtocolMessage.Type.REVOKE) {
|
|
3179
|
+
if (mutationKey) this.#rememberHandledProtocol(mutationKey);
|
|
3131
3180
|
const previous2 = stored ? normalizeZapoMessage(stored) : void 0;
|
|
3132
3181
|
const deletedByMe = event.key.fromMe === true;
|
|
3133
3182
|
const deletedById = event.key.participant ?? event.key.participantAlt ?? (deletedByMe ? this.getCurrentUserIds()[0] : event.key.remoteJid ?? void 0);
|
|
@@ -3157,6 +3206,7 @@ var ZapoProvider = class {
|
|
|
3157
3206
|
const message = normalizeZapoMessage(edited);
|
|
3158
3207
|
if (!message) return;
|
|
3159
3208
|
const previous = stored ? normalizeZapoMessage(stored) : void 0;
|
|
3209
|
+
if (mutationKey) this.#rememberHandledProtocol(mutationKey);
|
|
3160
3210
|
this.#remember(edited);
|
|
3161
3211
|
const editedByMe = event.key.fromMe === true;
|
|
3162
3212
|
const editedById = event.key.participant ?? event.key.participantAlt ?? (editedByMe ? this.getCurrentUserIds()[0] : event.key.remoteJid ?? void 0);
|
|
@@ -3607,9 +3657,33 @@ var ZapoProvider = class {
|
|
|
3607
3657
|
#messageStoreKey(key) {
|
|
3608
3658
|
return `${key.remoteJid ?? ""}:${key.id ?? ""}:${key.participant ?? key.participantAlt ?? ""}`;
|
|
3609
3659
|
}
|
|
3660
|
+
#messageDeliveryKey(key) {
|
|
3661
|
+
return `${key.remoteJid ?? ""}:${key.id ?? ""}`;
|
|
3662
|
+
}
|
|
3663
|
+
#protocolDeliveryKey(event, target, type) {
|
|
3664
|
+
if (type == null || !event.key.id || !target.id) return void 0;
|
|
3665
|
+
return `${type}:${event.key.remoteJid ?? target.remoteJid ?? ""}:${event.key.id}:${target.id}`;
|
|
3666
|
+
}
|
|
3667
|
+
#rememberHandledProtocol(key) {
|
|
3668
|
+
this.#handledProtocolStore.delete(key);
|
|
3669
|
+
this.#handledProtocolStore.add(key);
|
|
3670
|
+
while (this.#handledProtocolStore.size > this.#messageCacheSize) {
|
|
3671
|
+
const oldest = this.#handledProtocolStore.values().next().value;
|
|
3672
|
+
if (oldest) this.#handledProtocolStore.delete(oldest);
|
|
3673
|
+
}
|
|
3674
|
+
}
|
|
3675
|
+
#rememberDeliveredMessage(key) {
|
|
3676
|
+
this.#deliveredMessageStore.delete(key);
|
|
3677
|
+
this.#deliveredMessageStore.add(key);
|
|
3678
|
+
while (this.#deliveredMessageStore.size > this.#messageCacheSize) {
|
|
3679
|
+
const oldest = this.#deliveredMessageStore.values().next().value;
|
|
3680
|
+
if (oldest) this.#deliveredMessageStore.delete(oldest);
|
|
3681
|
+
}
|
|
3682
|
+
}
|
|
3610
3683
|
#isOfflineMessage(message) {
|
|
3611
3684
|
if (this.#options.processOfflineMessages === true) return false;
|
|
3612
3685
|
if (message.offline === true) return true;
|
|
3686
|
+
if (!this.#connected) return true;
|
|
3613
3687
|
if (!this.#connectedAtSeconds || message.timestampSeconds == null) return false;
|
|
3614
3688
|
const timestamp = toSeconds(message.timestampSeconds);
|
|
3615
3689
|
if (timestamp === void 0) return false;
|