@stone-wpp/ofc 1.0.3 → 1.0.4
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/README.md +3 -3
- package/lib/Defaults/index.d.ts +1 -1
- package/lib/Defaults/index.js +1 -1
- package/lib/Signal/Group/sender-key-distribution-message.js +1 -1
- package/lib/Signal/Group/sender-key-message.js +1 -1
- package/lib/Socket/chats.d.ts +1 -1
- package/lib/Socket/chats.js +1 -1
- package/lib/Socket/chats.js.bak +1 -1
- package/lib/Socket/communities.d.ts +1 -1
- package/lib/Socket/communities.js +1 -1
- package/lib/Socket/groups.d.ts +1 -1
- package/lib/Socket/groups.js +1 -1
- package/lib/Socket/index.d.ts +1 -1
- package/lib/Socket/index.js +3 -1
- package/lib/Socket/messages-recv.d.ts +1 -1
- package/lib/Socket/messages-recv.js +1 -1
- package/lib/Socket/messages-send.d.ts +1 -1
- package/lib/Socket/messages-send.js +1 -1
- package/lib/Socket/socket.js +1 -1
- package/lib/Socket/stone-features.d.ts +30 -0
- package/lib/Socket/stone-features.js +255 -0
- package/lib/Types/Auth.d.ts +1 -1
- package/lib/Types/Chat.d.ts +1 -1
- package/lib/Types/Events.d.ts +8 -1
- package/lib/Types/Events.js +1 -1
- package/lib/Types/Message.d.ts +1 -1
- package/lib/Types/Message.js +1 -1
- package/lib/Types/Signal.d.ts +1 -1
- package/lib/Types/Signal.js +1 -1
- package/lib/Types/Socket.d.ts +1 -1
- package/lib/Types/Socket.js +1 -1
- package/lib/Utils/browser-utils.js +1 -1
- package/lib/Utils/chat-utils.d.ts +1 -1
- package/lib/Utils/chat-utils.js +32 -1
- package/lib/Utils/decode-wa-message.js +1 -1
- package/lib/Utils/generics.d.ts +1 -1
- package/lib/Utils/generics.js +1 -1
- package/lib/Utils/history.d.ts +1 -1
- package/lib/Utils/history.js +1 -1
- package/lib/Utils/message-retry-manager.d.ts +1 -1
- package/lib/Utils/messages-media.d.ts +1 -1
- package/lib/Utils/messages-media.js +1 -1
- package/lib/Utils/messages.d.ts +1 -1
- package/lib/Utils/messages.js +9 -3
- package/lib/Utils/noise-handler.d.ts +1 -1
- package/lib/Utils/noise-handler.js +1 -1
- package/lib/Utils/process-message.d.ts +1 -1
- package/lib/Utils/process-message.js +1 -1
- package/lib/Utils/reporting-utils.d.ts +1 -1
- package/lib/Utils/reporting-utils.js +1 -1
- package/lib/Utils/sync-action-utils.d.ts +1 -1
- package/lib/Utils/sync-action-utils.js +1 -1
- package/lib/Utils/use-multi-file-auth-state.js +1 -1
- package/lib/Utils/validate-connection.d.ts +1 -1
- package/lib/Utils/validate-connection.js +1 -1
- package/lib/WABinary/generic-utils.d.ts +1 -1
- package/lib/WABinary/generic-utils.js +1 -1
- package/lib/index.d.ts +3 -4
- package/lib/index.js +3 -4
- package/package.json +6 -5
- package/lib/Recursos/Bots/index.js +0 -1
- package/lib/Recursos/Bots/mensagens.js +0 -21
- package/lib/Recursos/Canais/buscar.js +0 -12
- package/lib/Recursos/Canais/enquetes.js +0 -12
- package/lib/Recursos/Canais/estatisticas.js +0 -15
- package/lib/Recursos/Canais/index.js +0 -25
- package/lib/Recursos/Canais/reacoes.js +0 -13
- package/lib/Recursos/Chamadas/audio.js +0 -4
- package/lib/Recursos/Chamadas/index.js +0 -15
- package/lib/Recursos/Chamadas/video.js +0 -4
- package/lib/Recursos/Grupos/historico.js +0 -24
- package/lib/Recursos/Grupos/index.js +0 -7
- package/lib/Recursos/Grupos/permissoes.js +0 -21
- package/lib/Recursos/Listas/index.js +0 -1
- package/lib/Recursos/Listas/transmissao.js +0 -59
- package/lib/Recursos/index.d.ts +0 -58
- package/lib/Recursos/index.js +0 -8
- /package/{WAProto → Protocol}/GenerateStatics.sh +0 -0
- /package/{WAProto → Protocol}/WAProto.proto +0 -0
- /package/{WAProto → Protocol}/fix-imports.js +0 -0
- /package/{WAProto → Protocol}/index.d.ts +0 -0
- /package/{WAProto → Protocol}/index.js +0 -0
- /package/lib/{Store → DataLayer}/index.d.ts +0 -0
- /package/lib/{Store → DataLayer}/index.js +0 -0
- /package/lib/{Store → DataLayer}/json.js +0 -0
- /package/lib/{Store → DataLayer}/memory.js +0 -0
- /package/lib/{Store → DataLayer}/sqlite.js +0 -0
- /package/lib/{Plugins → Extensions}/index.d.ts +0 -0
- /package/lib/{Plugins → Extensions}/index.js +0 -0
- /package/lib/{Plugins → Extensions}/manager.js +0 -0
package/README.md
CHANGED
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
|
|
15
15
|
**STONE WPP — Biblioteca modular para WhatsApp em Node.js**
|
|
16
16
|
|
|
17
|
-
*Conexão • Autenticação • Mensagens • Botões • Grupos • Canais •
|
|
17
|
+
*Conexão • Autenticação • Mensagens • Botões • Grupos • Canais • Extensions*
|
|
18
18
|
|
|
19
19
|
<br>
|
|
20
20
|
|
|
21
|
-
<a href="https://
|
|
21
|
+
<a href="https://github.com/dylan-Modz/stone-wpp-ofc"><img src="https://img.shields.io/badge/VERS%C3%83O-1.0.4-00BFFF?style=for-the-badge&logo=github&logoColor=white&labelColor=111820" alt="Versão 1.0.4 do código no GitHub"></a>
|
|
22
22
|
<img src="https://img.shields.io/badge/NODE.JS-20%2B-111820?style=for-the-badge&logo=node.js&logoColor=00BFFF" alt="Node.js 20 ou superior">
|
|
23
23
|
<img src="https://img.shields.io/badge/LICENSE-MIT-00BFFF?style=for-the-badge&labelColor=111820" alt="Licença MIT">
|
|
24
24
|
|
|
@@ -58,7 +58,7 @@ A documentação principal da **Stone WPP** está disponível no nosso site ofic
|
|
|
58
58
|
| 🧩 **Botões** | Exemplos e referências das mensagens interativas. |
|
|
59
59
|
| 👥 **Grupos e comunidades** | Operações e gerenciamento. |
|
|
60
60
|
| 📢 **Canais** | Métodos e recursos disponíveis. |
|
|
61
|
-
| ⚙️ **Outros módulos** | API, armazenamento,
|
|
61
|
+
| ⚙️ **Outros módulos** | API, DataLayer (armazenamento), Extensions (extensões) e funcionalidades relacionadas. |
|
|
62
62
|
|
|
63
63
|
> **Importante:** a Stone WPP está em desenvolvimento. Consulte a documentação para conhecer os recursos disponíveis e suas limitações. Nem todas as funções planejadas estão implementadas.
|
|
64
64
|
|
package/lib/Defaults/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { proto } from '../../
|
|
1
|
+
import { proto } from '../../Protocol/index.js';
|
|
2
2
|
import type { SocketConfig } from '../Types/index.js';
|
|
3
3
|
export declare const UNAUTHORIZED_CODES: number[];
|
|
4
4
|
export declare const DEFAULT_ORIGIN = "https://web.whatsapp.com";
|
package/lib/Defaults/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { proto } from '../../../
|
|
1
|
+
import { proto } from '../../../Protocol/index.js';
|
|
2
2
|
import { CiphertextMessage } from './ciphertext-message.js';
|
|
3
3
|
export class SenderKeyDistributionMessage extends CiphertextMessage {
|
|
4
4
|
constructor(id, iteration, chainKey, signatureKey, serialized) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { calculateSignature, verifySignature } from 'libsignal/src/curve.js';
|
|
2
|
-
import { proto } from '../../../
|
|
2
|
+
import { proto } from '../../../Protocol/index.js';
|
|
3
3
|
import { CiphertextMessage } from './ciphertext-message.js';
|
|
4
4
|
export class SenderKeyMessage extends CiphertextMessage {
|
|
5
5
|
constructor(keyId, iteration, ciphertext, signatureKey, serialized) {
|
package/lib/Socket/chats.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom';
|
|
2
|
-
import { proto } from '../../
|
|
2
|
+
import { proto } from '../../Protocol/index.js';
|
|
3
3
|
import type { BotListInfo, CacheStore, ChatModification, MessageUpsertType, SocketConfig, WABusinessProfile, WAMediaUpload, WAMessage, WAPatchCreate, WAPresence, WAPrivacyCallValue, WAPrivacyGroupAddValue, WAPrivacyMessagesValue, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '../Types/index.js';
|
|
4
4
|
import type { QuickReplyAction } from '../Types/Bussines.js';
|
|
5
5
|
import type { LabelActionBody } from '../Types/Label.js';
|
package/lib/Socket/chats.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import NodeCache from '@cacheable/node-cache';
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
|
-
import { proto } from '../../
|
|
3
|
+
import { proto } from '../../Protocol/index.js';
|
|
4
4
|
import { DEFAULT_CACHE_TTLS, HISTORY_SYNC_PAUSED_TIMEOUT_MS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
|
|
5
5
|
import { ALL_WA_PATCH_NAMES } from '../Types/index.js';
|
|
6
6
|
import { SyncState } from '../Types/State.js';
|
package/lib/Socket/chats.js.bak
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import NodeCache from '@cacheable/node-cache';
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
|
-
import { proto } from '../../
|
|
3
|
+
import { proto } from '../../Protocol/index.js';
|
|
4
4
|
import { DEFAULT_CACHE_TTLS, HISTORY_SYNC_PAUSED_TIMEOUT_MS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
|
|
5
5
|
import { ALL_WA_PATCH_NAMES } from '../Types/index.js';
|
|
6
6
|
import { SyncState } from '../Types/State.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { proto } from '../../
|
|
1
|
+
import { proto } from '../../Protocol/index.js';
|
|
2
2
|
import { type GroupMetadata, type ParticipantAction, type SocketConfig, type WAMessageKey } from '../Types/index.js';
|
|
3
3
|
import { type BinaryNode } from '../WABinary/index.js';
|
|
4
4
|
export declare const makeCommunitiesSocket: (config: SocketConfig) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { proto } from '../../
|
|
1
|
+
import { proto } from '../../Protocol/index.js';
|
|
2
2
|
import { WAMessageStubType } from '../Types/index.js';
|
|
3
3
|
import { generateMessageID, generateMessageIDV2, unixTimestampSeconds } from '../Utils/index.js';
|
|
4
4
|
import logger from '../Utils/logger.js';
|
package/lib/Socket/groups.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom';
|
|
2
|
-
import { proto } from '../../
|
|
2
|
+
import { proto } from '../../Protocol/index.js';
|
|
3
3
|
import type { GroupMetadata, ParticipantAction, SocketConfig, WAMessageKey } from '../Types/index.js';
|
|
4
4
|
import { type BinaryNode } from '../WABinary/index.js';
|
|
5
5
|
export declare const makeGroupsSocket: (config: SocketConfig) => {
|
package/lib/Socket/groups.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom';
|
|
2
|
-
import { proto } from '../../
|
|
2
|
+
import { proto } from '../../Protocol/index.js';
|
|
3
3
|
import { WAMessageAddressingMode, WAMessageStubType } from '../Types/index.js';
|
|
4
4
|
import { generateMessageIDV2, unixTimestampSeconds } from '../Utils/index.js';
|
|
5
5
|
import { getBinaryNodeChild, getBinaryNodeChildren, getBinaryNodeChildString, isLidUser, isPnUser, jidEncode, jidNormalizedUser } from '../WABinary/index.js';
|
package/lib/Socket/index.d.ts
CHANGED
|
@@ -256,5 +256,5 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
256
256
|
}[] | undefined>;
|
|
257
257
|
fetchAccountReachoutTimelock: () => Promise<import("../index.js").ReachoutTimelockState>;
|
|
258
258
|
fetchNewChatMessageCap: () => Promise<import("../index.js").NewChatMessageCapInfo>;
|
|
259
|
-
};
|
|
259
|
+
} & import('./stone-features.js').StoneAdditionalMethods;
|
|
260
260
|
export default makeWASocket;
|
package/lib/Socket/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { DEFAULT_CONNECTION_CONFIG } from '../Defaults/index.js';
|
|
2
2
|
import { makeCommunitiesSocket } from './communities.js';
|
|
3
|
+
import { createStoneAdditionalMethods } from './stone-features.js';
|
|
3
4
|
// export the last socket layer
|
|
4
5
|
const makeWASocket = (config) => {
|
|
5
6
|
const newConfig = {
|
|
6
7
|
...DEFAULT_CONNECTION_CONFIG,
|
|
7
8
|
...config
|
|
8
9
|
};
|
|
9
|
-
|
|
10
|
+
const socket = makeCommunitiesSocket(newConfig);
|
|
11
|
+
return Object.assign(socket, createStoneAdditionalMethods(socket));
|
|
10
12
|
};
|
|
11
13
|
export default makeWASocket;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import NodeCache from '@cacheable/node-cache';
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
3
|
import Long from 'long';
|
|
4
|
-
import { proto } from '../../
|
|
4
|
+
import { proto } from '../../Protocol/index.js';
|
|
5
5
|
import type { MessageReceiptType, MessageRelayOptions, NewChatMessageCapInfo, SocketConfig, WAMessage, WAMessageKey } from '../Types/index.js';
|
|
6
6
|
import { type BinaryNode, type JidWithDevice } from '../WABinary/index.js';
|
|
7
7
|
export declare const makeMessagesRecvSocket: (config: SocketConfig) => {
|
|
@@ -2,7 +2,7 @@ import NodeCache from '@cacheable/node-cache';
|
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
3
|
import { randomBytes } from 'crypto';
|
|
4
4
|
import Long from 'long';
|
|
5
|
-
import { proto } from '../../
|
|
5
|
+
import { proto } from '../../Protocol/index.js';
|
|
6
6
|
import { DEFAULT_CACHE_TTLS, KEY_BUNDLE_TYPE, MIN_PREKEY_COUNT, PLACEHOLDER_MAX_AGE_SECONDS, STATUS_EXPIRY_SECONDS } from '../Defaults/index.js';
|
|
7
7
|
import { ReachoutTimelockEnforcementType, WAMessageStatus, WAMessageStubType } from '../Types/index.js';
|
|
8
8
|
import { ACCOUNT_RESTRICTED_TEXT, aesDecryptCTR, aesEncryptGCM, cleanMessage, Curve, decodeMediaRetryNode, decodeMessageNode, decryptMessageNode, delay, derivePairingCodeKey, encodeBigEndian, encodeSignedDeviceIdentity, extractAddressingContext, extractE2ESessionFromRetryReceipt, getCallStatusFromNode, getHistoryMsg, getNextPreKeys, getStatusFromReceiptType, handleIdentityChange, hkdf, MISSING_KEYS_ERROR_TEXT, NACK_REASONS, NO_MESSAGE_FOUND_ERROR_TEXT, SERVER_ERROR_CODES, toNumber, unixTimestampSeconds, xmppPreKey, xmppSignedPreKey } from '../Utils/index.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import NodeCache from '@cacheable/node-cache';
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
|
-
import { proto } from '../../
|
|
3
|
+
import { proto } from '../../Protocol/index.js';
|
|
4
4
|
import type { AnyMessageContent, MediaConnInfo, MessageReceiptType, MessageRelayOptions, MiscMessageGenerationOptions, SocketConfig, WAMessage, WAMessageKey } from '../Types/index.js';
|
|
5
5
|
import { MessageRetryManager } from '../Utils/index.js';
|
|
6
6
|
import { type BinaryNode, type JidWithDevice } from '../WABinary/index.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import NodeCache from '@cacheable/node-cache';
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
|
-
import { proto } from '../../
|
|
3
|
+
import { proto } from '../../Protocol/index.js';
|
|
4
4
|
import { DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
5
5
|
import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, decryptMediaRetryData, DEF_MEDIA_HOST, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
|
|
6
6
|
import { getUrlInfo } from '../Utils/link-preview.js';
|
package/lib/Socket/socket.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Boom } from '@hapi/boom';
|
|
|
2
2
|
import { randomBytes } from 'crypto';
|
|
3
3
|
import { URL } from 'url';
|
|
4
4
|
import { promisify } from 'util';
|
|
5
|
-
import { proto } from '../../
|
|
5
|
+
import { proto } from '../../Protocol/index.js';
|
|
6
6
|
import { DEF_CALLBACK_PREFIX, DEF_TAG_PREFIX, INITIAL_PREKEY_COUNT, MIN_PREKEY_COUNT, NOISE_WA_HEADER, PROCESSABLE_HISTORY_TYPES, TimeMs, UPLOAD_TIMEOUT } from '../Defaults/index.js';
|
|
7
7
|
import { QueryIds, ReachoutTimelockEnforcementType } from '../Types/index.js';
|
|
8
8
|
import { DisconnectReason, XWAPaths } from '../Types/index.js';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MiscMessageGenerationOptions, WAMessage, WAMessageKey } from '../Types/index.js'
|
|
2
|
+
import type { Label } from '../Types/Label.js'
|
|
3
|
+
|
|
4
|
+
export interface StoneAdditionalMethods {
|
|
5
|
+
/** Pesquisa username pelo USync. Não retorna números de telefone. */
|
|
6
|
+
queryUsernameExists(username: string, pin?: string): Promise<{ username: string; jid: string; wid: string; exists: true } | null>;
|
|
7
|
+
/** Cria ou altera uma nota da conta WhatsApp Business via app-state. */
|
|
8
|
+
setCustomerNote(jid: string, content: string, noteId?: string): Promise<{ id: string; chatId: string; content: string; createdAt: number; type: 'unstructured' }>;
|
|
9
|
+
/** Exclui a nota de uma conversa; exige id conhecido ou sincronizado. */
|
|
10
|
+
deleteCustomerNote(jid: string, noteId?: string): Promise<boolean>;
|
|
11
|
+
/** Nota observada pela sincronização desta conexão; pode ser null mesmo se existir no WhatsApp. */
|
|
12
|
+
getCustomerNote(jid: string): { id: string; chatId: string; content: string; createdAt: number; type: 'unstructured' } | null;
|
|
13
|
+
/** Native Flow Pix. Envia a chave, não processa pagamento; depende da conta WhatsApp. */
|
|
14
|
+
sendPixKeyMessage(
|
|
15
|
+
jid: string,
|
|
16
|
+
data: { keyType: 'CPF' | 'CNPJ' | 'PHONE' | 'EMAIL' | 'EVP'; name: string; key: string; instructions?: string },
|
|
17
|
+
options?: MiscMessageGenerationOptions
|
|
18
|
+
): Promise<WAMessage | undefined>;
|
|
19
|
+
/** Solicitação KeepInChat; exige permissões e mensagem ainda disponível. */
|
|
20
|
+
keepMessage(jid: string, messageKey: WAMessageKey, keep?: boolean): Promise<string>;
|
|
21
|
+
/** Edita a etiqueta no app-state do WhatsApp. */
|
|
22
|
+
editLabel(id: string, updates: { name?: string; color?: number }): Promise<unknown>;
|
|
23
|
+
/** Exclui uma etiqueta no app-state do WhatsApp. */
|
|
24
|
+
deleteLabel(id: string): Promise<unknown>;
|
|
25
|
+
/** Etiquetas observadas pelos eventos labels.edit desta conexão; lista pode ser parcial. */
|
|
26
|
+
getLabels(): Label[];
|
|
27
|
+
/** Etiqueta observada no app-state nesta conexão, ou undefined. */
|
|
28
|
+
getLabelById(id: string): Label | undefined;
|
|
29
|
+
}
|
|
30
|
+
export declare function createStoneAdditionalMethods(socket: unknown): StoneAdditionalMethods
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { USyncQuery, USyncUser } from '../WAUSync/index.js'
|
|
3
|
+
|
|
4
|
+
const PIX_KEY_TYPES = new Set(['CPF', 'CNPJ', 'PHONE', 'EMAIL', 'EVP'])
|
|
5
|
+
|
|
6
|
+
const requireJid = (jid) => {
|
|
7
|
+
if (typeof jid !== 'string' || !jid.includes('@')) {
|
|
8
|
+
throw new TypeError('Informe um JID válido')
|
|
9
|
+
}
|
|
10
|
+
return jid
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const requireId = (id, label = 'ID') => {
|
|
14
|
+
if (typeof id !== 'string' || !id.trim()) {
|
|
15
|
+
throw new TypeError(`Informe um ${label} válido`)
|
|
16
|
+
}
|
|
17
|
+
return id.trim()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Stone socket extensions. The underlying connection and auth are unchanged.
|
|
22
|
+
* Methods added here must use the existing WhatsApp transport (never mock success).
|
|
23
|
+
*/
|
|
24
|
+
export function createStoneAdditionalMethods(socket) {
|
|
25
|
+
const seenLabels = new Map()
|
|
26
|
+
const seenCustomerNotes = new Map()
|
|
27
|
+
const customerNoteByChat = new Map()
|
|
28
|
+
|
|
29
|
+
socket.ev.on('notes.edit', (note) => {
|
|
30
|
+
if (!note?.id || !note?.chatId) return
|
|
31
|
+
if (note.deleted) {
|
|
32
|
+
seenCustomerNotes.delete(note.id)
|
|
33
|
+
if (customerNoteByChat.get(note.chatId) === note.id) customerNoteByChat.delete(note.chatId)
|
|
34
|
+
} else {
|
|
35
|
+
const updated = {
|
|
36
|
+
...(seenCustomerNotes.get(note.id) || {}),
|
|
37
|
+
id: note.id,
|
|
38
|
+
chatId: note.chatId,
|
|
39
|
+
content: note.content ?? '',
|
|
40
|
+
createdAt: note.createdAt,
|
|
41
|
+
type: 'unstructured'
|
|
42
|
+
}
|
|
43
|
+
seenCustomerNotes.set(note.id, updated)
|
|
44
|
+
customerNoteByChat.set(note.chatId, note.id)
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// labels.edit is emitted from WhatsApp's app-state synchronization.
|
|
49
|
+
// This is an observed cache, NOT an authoritative account-wide label fetch.
|
|
50
|
+
socket.ev.on('labels.edit', (label) => {
|
|
51
|
+
if (!label?.id) return
|
|
52
|
+
if (label.deleted) {
|
|
53
|
+
seenLabels.delete(label.id)
|
|
54
|
+
} else {
|
|
55
|
+
seenLabels.set(label.id, { ...seenLabels.get(label.id), ...label })
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
/**
|
|
61
|
+
* Consulta um @username pelo USync do WhatsApp, com PIN opcional.
|
|
62
|
+
* Não revela nem infere o número de telefone.
|
|
63
|
+
*/
|
|
64
|
+
async queryUsernameExists(username, pin) {
|
|
65
|
+
if (typeof username !== 'string') throw new TypeError('Informe o @username')
|
|
66
|
+
const normalized = username.trim().replace(/^@/, '')
|
|
67
|
+
if (!/^[A-Za-z0-9_.]{3,30}$/.test(normalized)) {
|
|
68
|
+
throw new TypeError('Username inválido')
|
|
69
|
+
}
|
|
70
|
+
if (pin !== undefined && !/^\d{4}$/.test(pin)) {
|
|
71
|
+
throw new TypeError('O PIN deve conter exatamente 4 dígitos')
|
|
72
|
+
}
|
|
73
|
+
const user = new USyncUser().withUsername(normalized)
|
|
74
|
+
if (pin !== undefined) user.withUsernameKey(pin)
|
|
75
|
+
const query = new USyncQuery().withContactProtocol().withUser(user)
|
|
76
|
+
const response = await socket.executeUSyncQuery(query)
|
|
77
|
+
const contact = response?.list?.find(entry => entry?.contact === true && typeof entry.id === 'string')
|
|
78
|
+
return contact ? { username: normalized, jid: contact.id, wid: contact.id, exists: true } : null
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Cria ou altera uma nota comercial via app-state do WhatsApp.
|
|
83
|
+
* Receber uma nota depende de a conta oferecer o recurso comercial.
|
|
84
|
+
*/
|
|
85
|
+
async setCustomerNote(jid, content, noteId) {
|
|
86
|
+
requireJid(jid)
|
|
87
|
+
if (jid.endsWith('@g.us') || jid.endsWith('@newsletter')) {
|
|
88
|
+
throw new TypeError('Notas são permitidas apenas em conversas individuais')
|
|
89
|
+
}
|
|
90
|
+
if (typeof content !== 'string' || !content.trim()) {
|
|
91
|
+
throw new TypeError('Informe o conteúdo da nota')
|
|
92
|
+
}
|
|
93
|
+
const id = noteId == null ? customerNoteByChat.get(jid) || randomUUID() : requireId(noteId, 'ID da nota')
|
|
94
|
+
const existing = seenCustomerNotes.get(id)
|
|
95
|
+
const createdAt = existing?.createdAt || Math.floor(Date.now() / 1000)
|
|
96
|
+
const note = { id, chatId: jid, content: content.trim(), createdAt, type: 'unstructured' }
|
|
97
|
+
await socket.chatModify({ noteEdit: { ...note, deleted: false } }, jid)
|
|
98
|
+
seenCustomerNotes.set(id, note)
|
|
99
|
+
customerNoteByChat.set(jid, id)
|
|
100
|
+
return { ...note }
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
/** Remove uma nota comercial, identificada pelo JID e/ou ID previamente sincronizado. */
|
|
104
|
+
async deleteCustomerNote(jid, noteId) {
|
|
105
|
+
requireJid(jid)
|
|
106
|
+
const id = noteId == null ? customerNoteByChat.get(jid) : requireId(noteId, 'ID da nota')
|
|
107
|
+
if (!id) throw new Error('Nota não encontrada nesta conexão: informe o ID para excluir')
|
|
108
|
+
const existing = seenCustomerNotes.get(id)
|
|
109
|
+
await socket.chatModify({
|
|
110
|
+
noteEdit: {
|
|
111
|
+
id, chatId: jid, createdAt: existing?.createdAt || Math.floor(Date.now() / 1000),
|
|
112
|
+
content: '', deleted: true
|
|
113
|
+
}
|
|
114
|
+
}, jid)
|
|
115
|
+
seenCustomerNotes.delete(id)
|
|
116
|
+
if (customerNoteByChat.get(jid) === id) customerNoteByChat.delete(jid)
|
|
117
|
+
return true
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Nota observada pela sincronização desta conexão ou criada agora.
|
|
122
|
+
* Retorna null se a nota ainda não tiver sido sincronizada.
|
|
123
|
+
*/
|
|
124
|
+
getCustomerNote(jid) {
|
|
125
|
+
requireJid(jid)
|
|
126
|
+
const id = customerNoteByChat.get(jid)
|
|
127
|
+
const note = id && seenCustomerNotes.get(id)
|
|
128
|
+
return note ? { ...note } : null
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Envia o Native Flow de pagamento Pix para contas WhatsApp compatíveis.
|
|
133
|
+
* Não efetua nem verifica pagamentos.
|
|
134
|
+
*/
|
|
135
|
+
async sendPixKeyMessage(jid, data, options = {}) {
|
|
136
|
+
requireJid(jid)
|
|
137
|
+
if (!data || typeof data !== 'object') {
|
|
138
|
+
throw new TypeError('Informe os dados do Pix')
|
|
139
|
+
}
|
|
140
|
+
const { keyType, name, key, instructions = '' } = data
|
|
141
|
+
if (!PIX_KEY_TYPES.has(keyType)) {
|
|
142
|
+
throw new TypeError('keyType deve ser CPF, CNPJ, PHONE, EMAIL ou EVP')
|
|
143
|
+
}
|
|
144
|
+
if (typeof name !== 'string' || !name.trim()) {
|
|
145
|
+
throw new TypeError('Informe o nome do recebedor')
|
|
146
|
+
}
|
|
147
|
+
if (typeof key !== 'string' || !key.trim()) {
|
|
148
|
+
throw new TypeError('Informe a chave Pix')
|
|
149
|
+
}
|
|
150
|
+
if (typeof instructions !== 'string') {
|
|
151
|
+
throw new TypeError('instructions deve ser texto')
|
|
152
|
+
}
|
|
153
|
+
const ref = randomUUID().replace(/-/g, '')
|
|
154
|
+
const zero = { value: 0, offset: 1 }
|
|
155
|
+
const payment = {
|
|
156
|
+
order: {
|
|
157
|
+
items: [{ name: '', retailer_id: `stone-${ref}`, amount: { ...zero }, quantity: 0 }],
|
|
158
|
+
order_type: 'ORDER_WITHOUT_AMOUNT',
|
|
159
|
+
status: 'payment_requested',
|
|
160
|
+
subtotal: { ...zero }
|
|
161
|
+
},
|
|
162
|
+
total_amount: { ...zero },
|
|
163
|
+
reference_id: ref,
|
|
164
|
+
payment_settings: [
|
|
165
|
+
{ type: 'pix_static_code', pix_static_code: { key_type: keyType, merchant_name: name.trim(), key: key.trim() } },
|
|
166
|
+
{ type: 'cards', cards: { enabled: false } }
|
|
167
|
+
],
|
|
168
|
+
external_payment_configurations: [
|
|
169
|
+
{ type: 'payment_instruction', payment_instruction: instructions }
|
|
170
|
+
],
|
|
171
|
+
additional_note: '',
|
|
172
|
+
currency: 'BRL',
|
|
173
|
+
type: 'physical-goods'
|
|
174
|
+
}
|
|
175
|
+
return socket.sendMessage(jid, {
|
|
176
|
+
interactive: {
|
|
177
|
+
text: '',
|
|
178
|
+
buttons: [{ name: 'payment_info', buttonParamsJson: JSON.stringify(payment) }],
|
|
179
|
+
messageVersion: 1
|
|
180
|
+
}
|
|
181
|
+
}, options)
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Solicita manter/desfazer uma mensagem temporária via KeepInChatMessage.
|
|
186
|
+
* A confirmação depende do servidor e das permissões da conversa.
|
|
187
|
+
*/
|
|
188
|
+
async keepMessage(jid, messageKey, keep = true) {
|
|
189
|
+
requireJid(jid)
|
|
190
|
+
if (!messageKey || typeof messageKey !== 'object' || !messageKey.id) {
|
|
191
|
+
throw new TypeError('Informe a chave da mensagem original (messageKey)')
|
|
192
|
+
}
|
|
193
|
+
if (messageKey.remoteJid && messageKey.remoteJid !== jid) {
|
|
194
|
+
throw new TypeError('A mensagem não pertence ao JID informado')
|
|
195
|
+
}
|
|
196
|
+
if (typeof keep !== 'boolean') {
|
|
197
|
+
throw new TypeError('keep deve ser true ou false')
|
|
198
|
+
}
|
|
199
|
+
return socket.relayMessage(jid, {
|
|
200
|
+
keepInChatMessage: {
|
|
201
|
+
key: messageKey,
|
|
202
|
+
keepType: keep ? 1 : 2,
|
|
203
|
+
timestampMs: Date.now()
|
|
204
|
+
}
|
|
205
|
+
}, {})
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Atualiza uma etiqueta usando a app-state API já existente na Stone.
|
|
210
|
+
*/
|
|
211
|
+
async editLabel(id, updates) {
|
|
212
|
+
requireId(id, 'ID da etiqueta')
|
|
213
|
+
if (!updates || typeof updates !== 'object' || Array.isArray(updates)) {
|
|
214
|
+
throw new TypeError('Informe as alterações da etiqueta')
|
|
215
|
+
}
|
|
216
|
+
const { name, color } = updates
|
|
217
|
+
if (name === undefined && color === undefined) {
|
|
218
|
+
throw new TypeError('Informe name e/ou color')
|
|
219
|
+
}
|
|
220
|
+
if (name !== undefined && (typeof name !== 'string' || !name.trim())) {
|
|
221
|
+
throw new TypeError('name deve ser texto não vazio')
|
|
222
|
+
}
|
|
223
|
+
if (color !== undefined && (!Number.isInteger(color) || color < 0 || color > 19)) {
|
|
224
|
+
throw new TypeError('color deve ser um inteiro de 0 a 19')
|
|
225
|
+
}
|
|
226
|
+
return socket.addLabel('', {
|
|
227
|
+
id: id.trim(),
|
|
228
|
+
...(name === undefined ? {} : { name: name.trim() }),
|
|
229
|
+
...(color === undefined ? {} : { color }),
|
|
230
|
+
deleted: false
|
|
231
|
+
})
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
/** Exclui uma etiqueta real via app-state. */
|
|
235
|
+
async deleteLabel(id) {
|
|
236
|
+
requireId(id, 'ID da etiqueta')
|
|
237
|
+
return socket.addLabel('', { id: id.trim(), deleted: true })
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Apenas etiquetas recebidas em eventos labels.edit desde que o socket iniciou.
|
|
242
|
+
* Não garante listagem completa da conta. Consulte a documentação.
|
|
243
|
+
*/
|
|
244
|
+
getLabels() {
|
|
245
|
+
return [...seenLabels.values()].map(label => ({ ...label }))
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
/** Consulta a etiqueta que passou pelo sync desta conexão. */
|
|
249
|
+
getLabelById(id) {
|
|
250
|
+
requireId(id, 'ID da etiqueta')
|
|
251
|
+
const label = seenLabels.get(id.trim())
|
|
252
|
+
return label ? { ...label } : undefined
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
package/lib/Types/Auth.d.ts
CHANGED
package/lib/Types/Chat.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { proto } from '../../
|
|
1
|
+
import type { proto } from '../../Protocol/index.js';
|
|
2
2
|
import type { AccountSettings } from './Auth.js';
|
|
3
3
|
import type { QuickReplyAction } from './Bussines.js';
|
|
4
4
|
import type { BufferedEventData } from './Events.js';
|
package/lib/Types/Events.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Boom } from '@hapi/boom';
|
|
2
|
-
import { proto } from '../../
|
|
2
|
+
import { proto } from '../../Protocol/index.js';
|
|
3
3
|
import type { AuthenticationCreds, LIDMapping } from './Auth.js';
|
|
4
4
|
import type { WACallEvent } from './Call.js';
|
|
5
5
|
import type { Chat, ChatUpdate, PresenceData } from './Chat.js';
|
|
@@ -123,6 +123,13 @@ export type StoneWPPEventMap = {
|
|
|
123
123
|
};
|
|
124
124
|
/** Receive an update on a call, including when the call was received, rejected, accepted */
|
|
125
125
|
call: WACallEvent[];
|
|
126
|
+
'notes.edit': {
|
|
127
|
+
id: string;
|
|
128
|
+
chatId: string;
|
|
129
|
+
content?: string;
|
|
130
|
+
createdAt?: number;
|
|
131
|
+
deleted: boolean;
|
|
132
|
+
};
|
|
126
133
|
'labels.edit': Label;
|
|
127
134
|
'labels.association': {
|
|
128
135
|
association: LabelAssociation;
|
package/lib/Types/Events.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { proto } from '../../
|
|
1
|
+
import { proto } from '../../Protocol/index.js';
|
|
2
2
|
//# sourceMappingURL=Events.js.map
|
package/lib/Types/Message.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Readable } from 'stream';
|
|
2
2
|
import type { URL } from 'url';
|
|
3
|
-
import { proto } from '../../
|
|
3
|
+
import { proto } from '../../Protocol/index.js';
|
|
4
4
|
import type { MediaType } from '../Defaults/index.js';
|
|
5
5
|
import type { BinaryNode } from '../WABinary/index.js';
|
|
6
6
|
import type { GroupMetadata } from './GroupMetadata.js';
|
package/lib/Types/Message.js
CHANGED
package/lib/Types/Signal.d.ts
CHANGED
package/lib/Types/Signal.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { proto } from '../../
|
|
1
|
+
import { proto } from '../../Protocol/index.js';
|
|
2
2
|
//# sourceMappingURL=Signal.js.map
|
package/lib/Types/Socket.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Agent } from 'https';
|
|
2
2
|
import type { URL } from 'url';
|
|
3
|
-
import { proto } from '../../
|
|
3
|
+
import { proto } from '../../Protocol/index.js';
|
|
4
4
|
import type { ILogger } from '../Utils/logger.js';
|
|
5
5
|
import type { AuthenticationState, LIDMapping, SignalAuthState, TransactionCapabilityOptions } from './Auth.js';
|
|
6
6
|
import type { GroupMetadata } from './GroupMetadata.js';
|
package/lib/Types/Socket.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { proto } from '../../
|
|
1
|
+
import { proto } from '../../Protocol/index.js';
|
|
2
2
|
import type { StoneWPPEventEmitter, ChatModification, ChatMutation, Contact, InitialAppStateSyncOptions, LTHashState, WAPatchCreate, WAPatchName } from '../Types/index.js';
|
|
3
3
|
import { type BinaryNode } from '../WABinary/index.js';
|
|
4
4
|
import type { ILogger } from './logger.js';
|
package/lib/Utils/chat-utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom';
|
|
2
2
|
import { expandAppStateKeys } from 'whatsapp-rust-bridge';
|
|
3
|
-
import { proto } from '../../
|
|
3
|
+
import { proto } from '../../Protocol/index.js';
|
|
4
4
|
import { LabelAssociationType } from '../Types/LabelAssociation.js';
|
|
5
5
|
import { getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, jidNormalizedUser } from '../WABinary/index.js';
|
|
6
6
|
import { aesDecrypt, aesEncrypt, hmacSign } from './crypto.js';
|
|
@@ -576,6 +576,27 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
576
576
|
operation: OP.SET
|
|
577
577
|
};
|
|
578
578
|
}
|
|
579
|
+
else if ('noteEdit' in mod) {
|
|
580
|
+
const note = mod.noteEdit;
|
|
581
|
+
if (!note?.id || !note?.chatId) {
|
|
582
|
+
throw new Boom('Note id and chatId are required', { statusCode: 400 });
|
|
583
|
+
}
|
|
584
|
+
patch = {
|
|
585
|
+
syncAction: {
|
|
586
|
+
noteEditAction: {
|
|
587
|
+
type: 1,
|
|
588
|
+
chatJid: note.chatId,
|
|
589
|
+
createdAt: note.createdAt,
|
|
590
|
+
deleted: !!note.deleted,
|
|
591
|
+
unstructuredContent: note.content ?? ''
|
|
592
|
+
}
|
|
593
|
+
},
|
|
594
|
+
index: ['note_edit', note.id],
|
|
595
|
+
type: 'regular_low',
|
|
596
|
+
apiVersion: 7,
|
|
597
|
+
operation: OP.SET
|
|
598
|
+
};
|
|
599
|
+
}
|
|
579
600
|
else if ('addLabel' in mod) {
|
|
580
601
|
patch = {
|
|
581
602
|
syncAction: {
|
|
@@ -768,6 +789,16 @@ export const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) =
|
|
|
768
789
|
ev.emit('chats.delete', [id]);
|
|
769
790
|
}
|
|
770
791
|
}
|
|
792
|
+
else if (action?.noteEditAction) {
|
|
793
|
+
const note = action.noteEditAction;
|
|
794
|
+
ev.emit('notes.edit', {
|
|
795
|
+
id: syncAction.index?.[1],
|
|
796
|
+
chatId: note.chatJid,
|
|
797
|
+
content: note.unstructuredContent,
|
|
798
|
+
createdAt: note.createdAt ? toNumber(note.createdAt) : undefined,
|
|
799
|
+
deleted: !!note.deleted
|
|
800
|
+
});
|
|
801
|
+
}
|
|
771
802
|
else if (action?.labelEditAction) {
|
|
772
803
|
const { name, color, deleted, predefinedId } = action.labelEditAction;
|
|
773
804
|
ev.emit('labels.edit', {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom';
|
|
2
|
-
import { proto } from '../../
|
|
2
|
+
import { proto } from '../../Protocol/index.js';
|
|
3
3
|
import { areJidsSameUser, isHostedLidUser, isHostedPnUser, isJidBroadcast, isJidGroup, isJidMetaAI, isJidNewsletter, isJidStatusBroadcast, isLidUser, isPnUser
|
|
4
4
|
// transferDevice
|
|
5
5
|
} from '../WABinary/index.js';
|