├── lib
├── Defaults
│ ├── baileys-version.json
│ ├── phonenumber-mcc.json
│ └── index.js
├── Types
│ ├── Auth.js
│ ├── Call.js
│ ├── State.js
│ ├── Contact.js
│ ├── Events.js
│ ├── Product.js
│ ├── Signal.js
│ ├── Socket.js
│ ├── GroupMetadata.js
│ ├── Chat.js
│ ├── Call.d.ts
│ ├── LabelAssociation.js
│ ├── Message.js
│ ├── Contact.d.ts
│ ├── Label.d.ts
│ ├── State.d.ts
│ ├── LabelAssociation.d.ts
│ ├── Label.js
│ ├── Newsletter.js
│ ├── index.d.ts
│ ├── Signal.d.ts
│ ├── GroupMetadata.d.ts
│ ├── Product.d.ts
│ ├── index.js
│ ├── Newsletter.d.ts
│ ├── Auth.d.ts
│ ├── Chat.d.ts
│ ├── Socket.d.ts
│ └── Events.d.ts
├── WABinary
│ ├── types.js
│ ├── index.d.ts
│ ├── encode.d.ts
│ ├── decode.d.ts
│ ├── types.d.ts
│ ├── constants.d.ts
│ ├── index.js
│ ├── generic-utils.d.ts
│ ├── jid-utils.d.ts
│ ├── jid-utils.js
│ └── generic-utils.js
├── WAM
│ ├── index.d.ts
│ ├── encode.d.ts
│ ├── BinaryInfo.js
│ ├── BinaryInfo.d.ts
│ ├── index.js
│ ├── constants.d.ts
│ └── encode.js
├── Utils
│ ├── logger.d.ts
│ ├── make-mutex.d.ts
│ ├── logger.js
│ ├── lt-hash.d.ts
│ ├── use-multi-file-auth-state.d.ts
│ ├── index.d.ts
│ ├── baileys-event-stream.d.ts
│ ├── decode-wa-message.d.ts
│ ├── history.d.ts
│ ├── link-preview.d.ts
│ ├── validate-connection.d.ts
│ ├── noise-handler.d.ts
│ ├── auth-utils.d.ts
│ ├── business.d.ts
│ ├── make-mutex.js
│ ├── event-buffer.d.ts
│ ├── signal.d.ts
│ ├── index.js
│ ├── lt-hash.js
│ ├── process-message.d.ts
│ ├── crypto.d.ts
│ ├── baileys-event-stream.js
│ ├── use-multi-file-auth-state.js
│ ├── chat-utils.d.ts
│ ├── link-preview.js
│ ├── history.js
│ ├── generics.d.ts
│ ├── messages.d.ts
│ ├── messages-media.d.ts
│ └── noise-handler.js
├── Socket
│ ├── Client
│ │ ├── index.d.ts
│ │ ├── abstract-socket-client.js
│ │ ├── web-socket-client.d.ts
│ │ ├── mobile-socket-client.d.ts
│ │ ├── abstract-socket-client.d.ts
│ │ ├── index.js
│ │ ├── mobile-socket-client.js
│ │ └── web-socket-client.js
│ ├── index.js
│ ├── socket.d.ts
│ ├── chats.d.ts
│ └── groups.d.ts
├── Store
│ ├── index.d.ts
│ ├── object-repository.d.ts
│ ├── make-cache-manager-store.d.ts
│ ├── make-ordered-dictionary.d.ts
│ ├── index.js
│ ├── object-repository.js
│ ├── make-ordered-dictionary.js
│ ├── make-cache-manager-store.js
│ └── make-in-memory-store.d.ts
├── Signal
│ └── libsignal.d.ts
├── index.d.ts
└── index.js
├── WASignalGroup
├── protobufs.js
├── ciphertext_message.js
├── index.js
├── keyhelper.js
├── sender_message_key.js
├── sender_chain_key.js
├── sender_key_name.js
├── sender_key_record.js
├── group_session_builder.js
├── queue_job.js
├── sender_key_distribution_message.js
├── sender_key_message.js
├── group_cipher.js
└── sender_key_state.js
├── typedoc.json
├── WAProto
└── GenerateStatics.sh
├── tsconfig.json
└── package.json
/lib/Defaults/baileys-version.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": [2, 2413, 1]
3 | }
4 |
--------------------------------------------------------------------------------
/lib/Types/Auth.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/lib/Types/Call.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/lib/Types/State.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/lib/Types/Contact.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/lib/Types/Events.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/lib/Types/Product.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/lib/Types/Signal.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/lib/Types/Socket.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/lib/WABinary/types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/WASignalGroup/protobufs.js:
--------------------------------------------------------------------------------
1 | const { groupproto } = require('./GroupProtocol')
2 |
3 | module.exports = groupproto
--------------------------------------------------------------------------------
/lib/Types/GroupMetadata.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/lib/WAM/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './constants';
2 | export * from './encode';
3 | export * from './BinaryInfo';
4 |
--------------------------------------------------------------------------------
/lib/Utils/logger.d.ts:
--------------------------------------------------------------------------------
1 | declare const _default: import("pino").Logger<{
2 | timestamp: () => string;
3 | }>;
4 | export default _default;
5 |
--------------------------------------------------------------------------------
/lib/Socket/Client/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './abstract-socket-client';
2 | export * from './mobile-socket-client';
3 | export * from './web-socket-client';
4 |
--------------------------------------------------------------------------------
/lib/WAM/encode.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { BinaryInfo } from './BinaryInfo';
3 | export declare const encodeWAM: (binaryInfo: BinaryInfo) => Buffer;
4 |
--------------------------------------------------------------------------------
/lib/WABinary/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './encode';
2 | export * from './decode';
3 | export * from './generic-utils';
4 | export * from './jid-utils';
5 | export * from './types';
6 |
--------------------------------------------------------------------------------
/lib/Store/index.d.ts:
--------------------------------------------------------------------------------
1 | import makeCacheManagerAuthState from './make-cache-manager-store';
2 | import makeInMemoryStore from './make-in-memory-store';
3 | export { makeInMemoryStore, makeCacheManagerAuthState };
4 |
--------------------------------------------------------------------------------
/lib/Signal/libsignal.d.ts:
--------------------------------------------------------------------------------
1 | import { SignalAuthState } from '../Types';
2 | import { SignalRepository } from '../Types/Signal';
3 | export declare function makeLibSignalRepository(auth: SignalAuthState): SignalRepository;
4 |
--------------------------------------------------------------------------------
/lib/Types/Chat.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.ALL_WA_PATCH_NAMES = void 0;
4 | exports.ALL_WA_PATCH_NAMES = ['critical_block', 'critical_unblock_low', 'regular_high', 'regular_low', 'regular'];
5 |
--------------------------------------------------------------------------------
/typedoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "entryPoints": ["./lib/index.ts"],
3 | "excludePrivate": true,
4 | "excludeProtected": true,
5 | "excludeExternals": true,
6 | "includeVersion": false,
7 | "out": "docs",
8 | "gaID": "G-WBY63HR4VS"
9 | }
10 |
--------------------------------------------------------------------------------
/lib/WABinary/encode.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import type { BinaryNode, BinaryNodeCodingOptions } from './types';
3 | export declare const encodeBinaryNode: ({ tag, attrs, content }: BinaryNode, opts?: Pick, buffer?: number[]) => Buffer;
4 |
--------------------------------------------------------------------------------
/lib/Utils/make-mutex.d.ts:
--------------------------------------------------------------------------------
1 | export declare const makeMutex: () => {
2 | mutex(code: () => T | Promise): Promise;
3 | };
4 | export type Mutex = ReturnType;
5 | export declare const makeKeyedMutex: () => {
6 | mutex(key: string, task: () => T | Promise): Promise;
7 | };
8 |
--------------------------------------------------------------------------------
/WAProto/GenerateStatics.sh:
--------------------------------------------------------------------------------
1 | yarn pbjs -t static-module -w commonjs -o ./WAProto/index.js ./WAProto/WAProto.proto;
2 | yarn pbts -o ./WAProto/index.d.ts ./WAProto/index.js;
3 |
4 | #protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_opt=env=node,useOptionals=true,forceLong=long --ts_proto_out=. ./src/Binary/WAMessage.proto;
--------------------------------------------------------------------------------
/WASignalGroup/ciphertext_message.js:
--------------------------------------------------------------------------------
1 | class CiphertextMessage {
2 | UNSUPPORTED_VERSION = 1;
3 |
4 | CURRENT_VERSION = 3;
5 |
6 | WHISPER_TYPE = 2;
7 |
8 | PREKEY_TYPE = 3;
9 |
10 | SENDERKEY_TYPE = 4;
11 |
12 | SENDERKEY_DISTRIBUTION_TYPE = 5;
13 |
14 | ENCRYPTED_MESSAGE_OVERHEAD = 53;
15 | }
16 | module.exports = CiphertextMessage;
--------------------------------------------------------------------------------
/WASignalGroup/index.js:
--------------------------------------------------------------------------------
1 | module.exports.GroupSessionBuilder = require('./group_session_builder')
2 | module.exports.SenderKeyDistributionMessage = require('./sender_key_distribution_message')
3 | module.exports.SenderKeyRecord = require('./sender_key_record')
4 | module.exports.SenderKeyName = require('./sender_key_name')
5 | module.exports.GroupCipher = require('./group_cipher')
--------------------------------------------------------------------------------
/lib/index.d.ts:
--------------------------------------------------------------------------------
1 | import makeWASocket from './Socket';
2 | export * from '../WAProto';
3 | export * from './Utils';
4 | export * from './Types';
5 | export * from './Store';
6 | export * from './Defaults';
7 | export * from './WABinary';
8 | export * from './WAM';
9 | export type WASocket = ReturnType;
10 | export { makeWASocket };
11 | export default makeWASocket;
12 |
--------------------------------------------------------------------------------
/lib/Utils/logger.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | const pino_1 = __importDefault(require("pino"));
7 | exports.default = (0, pino_1.default)({ timestamp: () => `,"time":"${new Date().toJSON()}"` });
8 |
--------------------------------------------------------------------------------
/lib/Types/Call.d.ts:
--------------------------------------------------------------------------------
1 | export type WACallUpdateType = 'offer' | 'ringing' | 'timeout' | 'reject' | 'accept';
2 | export type WACallEvent = {
3 | chatId: string;
4 | from: string;
5 | isGroup?: boolean;
6 | groupJid?: string;
7 | id: string;
8 | date: Date;
9 | isVideo?: boolean;
10 | status: WACallUpdateType;
11 | offline: boolean;
12 | latencyMs?: number;
13 | };
14 |
--------------------------------------------------------------------------------
/lib/Store/object-repository.d.ts:
--------------------------------------------------------------------------------
1 | export declare class ObjectRepository {
2 | readonly entityMap: Map;
3 | constructor(entities?: Record);
4 | findById(id: string): T | undefined;
5 | findAll(): T[];
6 | upsertById(id: string, entity: T): Map;
7 | deleteById(id: string): boolean;
8 | count(): number;
9 | toJSON(): T[];
10 | }
11 |
--------------------------------------------------------------------------------
/lib/WAM/BinaryInfo.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.BinaryInfo = void 0;
4 | class BinaryInfo {
5 | constructor(options = {}) {
6 | this.protocolVersion = 5;
7 | this.sequence = 0;
8 | this.events = [];
9 | this.buffer = [];
10 | Object.assign(this, options);
11 | }
12 | }
13 | exports.BinaryInfo = BinaryInfo;
14 |
--------------------------------------------------------------------------------
/lib/Socket/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | const Defaults_1 = require("../Defaults");
4 | const registration_1 = require("./registration");
5 | // export the last socket layer
6 | const makeWASocket = (config) => ((0, registration_1.makeRegistrationSocket)({
7 | ...Defaults_1.DEFAULT_CONNECTION_CONFIG,
8 | ...config
9 | }));
10 | exports.default = makeWASocket;
11 |
--------------------------------------------------------------------------------
/lib/Types/LabelAssociation.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.LabelAssociationType = void 0;
4 | /** Association type */
5 | var LabelAssociationType;
6 | (function (LabelAssociationType) {
7 | LabelAssociationType["Chat"] = "label_jid";
8 | LabelAssociationType["Message"] = "label_message";
9 | })(LabelAssociationType = exports.LabelAssociationType || (exports.LabelAssociationType = {}));
10 |
--------------------------------------------------------------------------------
/lib/Utils/lt-hash.d.ts:
--------------------------------------------------------------------------------
1 | declare class d {
2 | salt: string;
3 | constructor(e: string);
4 | add(e: any, t: any): any;
5 | subtract(e: any, t: any): any;
6 | subtractThenAdd(e: any, t: any, r: any): any;
7 | _addSingle(e: any, t: any): ArrayBuffer;
8 | _subtractSingle(e: any, t: any): ArrayBuffer;
9 | performPointwiseWithOverflow(e: any, t: any, r: any): ArrayBuffer;
10 | }
11 | export declare const LT_HASH_ANTI_TAMPERING: d;
12 | export {};
13 |
--------------------------------------------------------------------------------
/lib/WAM/BinaryInfo.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare class BinaryInfo {
3 | protocolVersion: number;
4 | sequence: number;
5 | events: {
6 | [x: string]: {
7 | props: {
8 | [x: string]: any;
9 | };
10 | globals: {
11 | [x: string]: any;
12 | };
13 | };
14 | }[];
15 | buffer: Buffer[];
16 | constructor(options?: Partial);
17 | }
18 |
--------------------------------------------------------------------------------
/lib/WABinary/decode.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import type { BinaryNode, BinaryNodeCodingOptions } from './types';
3 | export declare const decompressingIfRequired: (buffer: Buffer) => Buffer;
4 | export declare const decodeDecompressedBinaryNode: (buffer: Buffer, opts: Pick, indexRef?: {
5 | index: number;
6 | }) => BinaryNode;
7 | export declare const decodeBinaryNode: (buff: Buffer) => BinaryNode;
8 |
--------------------------------------------------------------------------------
/lib/Socket/Client/abstract-socket-client.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.AbstractSocketClient = void 0;
4 | const events_1 = require("events");
5 | class AbstractSocketClient extends events_1.EventEmitter {
6 | constructor(url, config) {
7 | super();
8 | this.url = url;
9 | this.config = config;
10 | this.setMaxListeners(0);
11 | }
12 | }
13 | exports.AbstractSocketClient = AbstractSocketClient;
14 |
--------------------------------------------------------------------------------
/lib/Socket/Client/web-socket-client.d.ts:
--------------------------------------------------------------------------------
1 | import WebSocket from 'ws';
2 | import { AbstractSocketClient } from './abstract-socket-client';
3 | export declare class WebSocketClient extends AbstractSocketClient {
4 | protected socket: WebSocket | null;
5 | get isOpen(): boolean;
6 | get isClosed(): boolean;
7 | get isClosing(): boolean;
8 | get isConnecting(): boolean;
9 | connect(): Promise;
10 | close(): Promise;
11 | send(str: string | Uint8Array, cb?: (err?: Error) => void): boolean;
12 | }
13 |
--------------------------------------------------------------------------------
/lib/Store/make-cache-manager-store.d.ts:
--------------------------------------------------------------------------------
1 | import { AuthenticationCreds } from '../Types';
2 | declare const makeCacheManagerAuthState: (store: Storage, sessionKey: string) => Promise<{
3 | clearState: () => Promise;
4 | saveCreds: () => Promise;
5 | state: {
6 | creds: AuthenticationCreds;
7 | keys: {
8 | get: (type: string, ids: string[]) => Promise<{}>;
9 | set: (data: any) => Promise;
10 | };
11 | };
12 | }>;
13 | export default makeCacheManagerAuthState;
14 |
--------------------------------------------------------------------------------
/WASignalGroup/keyhelper.js:
--------------------------------------------------------------------------------
1 | const curve = require('libsignal/src/curve');
2 | const nodeCrypto = require('crypto');
3 |
4 | exports.generateSenderKey = function() {
5 | return nodeCrypto.randomBytes(32);
6 | }
7 |
8 | exports.generateSenderKeyId = function() {
9 | return nodeCrypto.randomInt(2147483647);
10 | }
11 |
12 | exports.generateSenderSigningKey = function(key) {
13 | if (!key) {
14 | key = curve.generateKeyPair();
15 | }
16 |
17 | return {
18 | public: key.pubKey,
19 | private: key.privKey,
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/lib/Utils/use-multi-file-auth-state.d.ts:
--------------------------------------------------------------------------------
1 | import { AuthenticationState } from '../Types';
2 | /**
3 | * stores the full authentication state in a single folder.
4 | * Far more efficient than singlefileauthstate
5 | *
6 | * Again, I wouldn't endorse this for any production level use other than perhaps a bot.
7 | * Would recommend writing an auth state for use with a proper SQL or No-SQL DB
8 | * */
9 | export declare const useMultiFileAuthState: (folder: string) => Promise<{
10 | state: AuthenticationState;
11 | saveCreds: () => Promise;
12 | }>;
13 |
--------------------------------------------------------------------------------
/lib/Socket/Client/mobile-socket-client.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Socket } from 'net';
3 | import { AbstractSocketClient } from './abstract-socket-client';
4 | export declare class MobileSocketClient extends AbstractSocketClient {
5 | protected socket: Socket | null;
6 | get isOpen(): boolean;
7 | get isClosed(): boolean;
8 | get isClosing(): boolean;
9 | get isConnecting(): boolean;
10 | connect(): Promise;
11 | close(): Promise;
12 | send(str: string | Uint8Array, cb?: (err?: Error) => void): boolean;
13 | }
14 |
--------------------------------------------------------------------------------
/lib/Store/make-ordered-dictionary.d.ts:
--------------------------------------------------------------------------------
1 | declare function makeOrderedDictionary(idGetter: (item: T) => string): {
2 | array: T[];
3 | get: (id: string) => T | undefined;
4 | upsert: (item: T, mode: 'append' | 'prepend') => void;
5 | update: (item: T) => boolean;
6 | remove: (item: T) => boolean;
7 | updateAssign: (id: string, update: Partial) => boolean;
8 | clear: () => void;
9 | filter: (contain: (item: T) => boolean) => void;
10 | toJSON: () => T[];
11 | fromJSON: (newItems: T[]) => void;
12 | };
13 | export default makeOrderedDictionary;
14 |
--------------------------------------------------------------------------------
/lib/Utils/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './generics';
2 | export * from './decode-wa-message';
3 | export * from './messages';
4 | export * from './messages-media';
5 | export * from './validate-connection';
6 | export * from './crypto';
7 | export * from './signal';
8 | export * from './noise-handler';
9 | export * from './history';
10 | export * from './chat-utils';
11 | export * from './lt-hash';
12 | export * from './auth-utils';
13 | export * from './baileys-event-stream';
14 | export * from './use-multi-file-auth-state';
15 | export * from './link-preview';
16 | export * from './event-buffer';
17 | export * from './process-message';
18 |
--------------------------------------------------------------------------------
/lib/Store/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | exports.makeCacheManagerAuthState = exports.makeInMemoryStore = void 0;
7 | const make_cache_manager_store_1 = __importDefault(require("./make-cache-manager-store"));
8 | exports.makeCacheManagerAuthState = make_cache_manager_store_1.default;
9 | const make_in_memory_store_1 = __importDefault(require("./make-in-memory-store"));
10 | exports.makeInMemoryStore = make_in_memory_store_1.default;
11 |
--------------------------------------------------------------------------------
/lib/Types/Message.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.WAMessageStatus = exports.WAMessageStubType = exports.WAProto = void 0;
4 | const WAProto_1 = require("../../WAProto");
5 | Object.defineProperty(exports, "WAProto", { enumerable: true, get: function () { return WAProto_1.proto; } });
6 | // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
7 | exports.WAMessageStubType = WAProto_1.proto.WebMessageInfo.StubType;
8 | // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
9 | exports.WAMessageStatus = WAProto_1.proto.WebMessageInfo.Status;
10 |
--------------------------------------------------------------------------------
/lib/Types/Contact.d.ts:
--------------------------------------------------------------------------------
1 | export interface Contact {
2 | id: string;
3 | lid?: string;
4 | /** name of the contact, you have saved on your WA */
5 | name?: string;
6 | /** name of the contact, the contact has set on their own on WA */
7 | notify?: string;
8 | /** I have no idea */
9 | verifiedName?: string;
10 | /**
11 | * Url of the profile picture of the contact
12 | *
13 | * 'changed' => if the profile picture has changed
14 | * null => if the profile picture has not been set (default profile picture)
15 | * any other string => url of the profile picture
16 | */
17 | imgUrl?: string | null | 'changed';
18 | status?: string;
19 | }
20 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2018",
4 | "module": "CommonJS",
5 | "moduleResolution": "NodeNext",
6 | "experimentalDecorators": true,
7 | "allowJs": false,
8 | "checkJs": false,
9 | "outDir": "lib",
10 | "strict": false,
11 | "strictNullChecks": true,
12 | "skipLibCheck": true,
13 | "noImplicitThis": true,
14 | "esModuleInterop": true,
15 | "resolveJsonModule": true,
16 | "forceConsistentCasingInFileNames": true,
17 | "declaration": true,
18 | "lib": ["es2020", "esnext.array", "DOM"]
19 | },
20 | "include": ["./lib/**/*.ts"],
21 | "exclude": ["node_modules", "lib/Tests/*", "lib/Binary/GenerateStatics.ts"]
22 | }
23 |
--------------------------------------------------------------------------------
/lib/Utils/baileys-event-stream.d.ts:
--------------------------------------------------------------------------------
1 | import type { BaileysEventEmitter } from '../Types';
2 | /**
3 | * Captures events from a baileys event emitter & stores them in a file
4 | * @param ev The event emitter to read events from
5 | * @param filename File to save to
6 | */
7 | export declare const captureEventStream: (ev: BaileysEventEmitter, filename: string) => void;
8 | /**
9 | * Read event file and emit events from there
10 | * @param filename filename containing event data
11 | * @param delayIntervalMs delay between each event emit
12 | */
13 | export declare const readAndEmitEventStream: (filename: string, delayIntervalMs?: number) => {
14 | ev: BaileysEventEmitter;
15 | task: Promise;
16 | };
17 |
--------------------------------------------------------------------------------
/lib/WABinary/types.d.ts:
--------------------------------------------------------------------------------
1 | import * as constants from './constants';
2 | /**
3 | * the binary node WA uses internally for communication
4 | *
5 | * this is manipulated soley as an object and it does not have any functions.
6 | * This is done for easy serialization, to prevent running into issues with prototypes &
7 | * to maintain functional code structure
8 | * */
9 | export type BinaryNode = {
10 | tag: string;
11 | attrs: {
12 | [key: string]: string;
13 | };
14 | content?: BinaryNode[] | string | Uint8Array;
15 | };
16 | export type BinaryNodeAttributes = BinaryNode['attrs'];
17 | export type BinaryNodeData = BinaryNode['content'];
18 | export type BinaryNodeCodingOptions = typeof constants;
19 |
--------------------------------------------------------------------------------
/lib/Socket/Client/abstract-socket-client.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | import { EventEmitter } from 'events';
4 | import { URL } from 'url';
5 | import { SocketConfig } from '../../Types';
6 | export declare abstract class AbstractSocketClient extends EventEmitter {
7 | url: URL;
8 | config: SocketConfig;
9 | abstract get isOpen(): boolean;
10 | abstract get isClosed(): boolean;
11 | abstract get isClosing(): boolean;
12 | abstract get isConnecting(): boolean;
13 | constructor(url: URL, config: SocketConfig);
14 | abstract connect(): Promise;
15 | abstract close(): Promise;
16 | abstract send(str: Uint8Array | string, cb?: (err?: Error) => void): boolean;
17 | }
18 |
--------------------------------------------------------------------------------
/lib/WABinary/constants.d.ts:
--------------------------------------------------------------------------------
1 | export declare const TAGS: {
2 | LIST_EMPTY: number;
3 | DICTIONARY_0: number;
4 | DICTIONARY_1: number;
5 | DICTIONARY_2: number;
6 | DICTIONARY_3: number;
7 | AD_JID: number;
8 | LIST_8: number;
9 | LIST_16: number;
10 | JID_PAIR: number;
11 | HEX_8: number;
12 | BINARY_8: number;
13 | BINARY_20: number;
14 | BINARY_32: number;
15 | NIBBLE_8: number;
16 | PACKED_MAX: number;
17 | SINGLE_BYTE_MAX: number;
18 | STREAM_END: number;
19 | };
20 | export declare const DOUBLE_BYTE_TOKENS: string[][];
21 | export declare const SINGLE_BYTE_TOKENS: (string | null)[];
22 | export declare const TOKEN_MAP: {
23 | [token: string]: {
24 | dict?: number;
25 | index: number;
26 | };
27 | };
28 |
--------------------------------------------------------------------------------
/lib/Utils/decode-wa-message.d.ts:
--------------------------------------------------------------------------------
1 | import { Logger } from 'pino';
2 | import { proto } from '../../WAProto';
3 | import { SignalRepository } from '../Types';
4 | import { BinaryNode } from '../WABinary';
5 | /**
6 | * Decode the received node as a message.
7 | * @note this will only parse the message, not decrypt it
8 | */
9 | export declare function decodeMessageNode(stanza: BinaryNode, meId: string, meLid: string): {
10 | fullMessage: proto.IWebMessageInfo;
11 | author: string;
12 | sender: string;
13 | };
14 | export declare const decryptMessageNode: (stanza: BinaryNode, meId: string, meLid: string, repository: SignalRepository, logger: Logger) => {
15 | fullMessage: proto.IWebMessageInfo;
16 | category: string;
17 | author: string;
18 | decrypt(): Promise;
19 | };
20 |
--------------------------------------------------------------------------------
/lib/Store/object-repository.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.ObjectRepository = void 0;
4 | class ObjectRepository {
5 | constructor(entities = {}) {
6 | this.entityMap = new Map(Object.entries(entities));
7 | }
8 | findById(id) {
9 | return this.entityMap.get(id);
10 | }
11 | findAll() {
12 | return Array.from(this.entityMap.values());
13 | }
14 | upsertById(id, entity) {
15 | return this.entityMap.set(id, { ...entity });
16 | }
17 | deleteById(id) {
18 | return this.entityMap.delete(id);
19 | }
20 | count() {
21 | return this.entityMap.size;
22 | }
23 | toJSON() {
24 | return this.findAll();
25 | }
26 | }
27 | exports.ObjectRepository = ObjectRepository;
28 |
--------------------------------------------------------------------------------
/lib/Utils/history.d.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig } from 'axios';
2 | import { proto } from '../../WAProto';
3 | import { Chat, Contact } from '../Types';
4 | export declare const downloadHistory: (msg: proto.Message.IHistorySyncNotification, options: AxiosRequestConfig) => Promise;
5 | export declare const processHistoryMessage: (item: proto.IHistorySync) => {
6 | chats: Chat[];
7 | contacts: Contact[];
8 | messages: proto.IWebMessageInfo[];
9 | };
10 | export declare const downloadAndProcessHistorySyncNotification: (msg: proto.Message.IHistorySyncNotification, options: AxiosRequestConfig) => Promise<{
11 | chats: Chat[];
12 | contacts: Contact[];
13 | messages: proto.IWebMessageInfo[];
14 | }>;
15 | export declare const getHistoryMsg: (message: proto.IMessage) => proto.Message.IHistorySyncNotification | null | undefined;
16 |
--------------------------------------------------------------------------------
/lib/Types/Label.d.ts:
--------------------------------------------------------------------------------
1 | export interface Label {
2 | /** Label uniq ID */
3 | id: string;
4 | /** Label name */
5 | name: string;
6 | /** Label color ID */
7 | color: number;
8 | /** Is label has been deleted */
9 | deleted: boolean;
10 | /** WhatsApp has 5 predefined labels (New customer, New order & etc) */
11 | predefinedId?: string;
12 | }
13 | /** WhatsApp has 20 predefined colors */
14 | export declare enum LabelColor {
15 | Color1 = 0,
16 | Color2 = 1,
17 | Color3 = 2,
18 | Color4 = 3,
19 | Color5 = 4,
20 | Color6 = 5,
21 | Color7 = 6,
22 | Color8 = 7,
23 | Color9 = 8,
24 | Color10 = 9,
25 | Color11 = 10,
26 | Color12 = 11,
27 | Color13 = 12,
28 | Color14 = 13,
29 | Color15 = 14,
30 | Color16 = 15,
31 | Color17 = 16,
32 | Color18 = 17,
33 | Color19 = 18,
34 | Color20 = 19
35 | }
36 |
--------------------------------------------------------------------------------
/lib/Utils/link-preview.d.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig } from 'axios';
2 | import { Logger } from 'pino';
3 | import { WAMediaUploadFunction, WAUrlInfo } from '../Types';
4 | export type URLGenerationOptions = {
5 | thumbnailWidth: number;
6 | fetchOpts: {
7 | /** Timeout in ms */
8 | timeout: number;
9 | proxyUrl?: string;
10 | headers?: AxiosRequestConfig<{}>['headers'];
11 | };
12 | uploadImage?: WAMediaUploadFunction;
13 | logger?: Logger;
14 | };
15 | /**
16 | * Given a piece of text, checks for any URL present, generates link preview for the same and returns it
17 | * Return undefined if the fetch failed or no URL was found
18 | * @param text first matched URL in text
19 | * @returns the URL info required to generate link preview
20 | */
21 | export declare const getUrlInfo: (text: string, opts?: URLGenerationOptions) => Promise;
22 |
--------------------------------------------------------------------------------
/lib/WAM/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | Object.defineProperty(exports, "__esModule", { value: true });
17 | __exportStar(require("./constants"), exports);
18 | __exportStar(require("./encode"), exports);
19 | __exportStar(require("./BinaryInfo"), exports);
20 |
--------------------------------------------------------------------------------
/lib/Utils/validate-connection.d.ts:
--------------------------------------------------------------------------------
1 | import { proto } from '../../WAProto';
2 | import type { AuthenticationCreds, SignalCreds, SocketConfig } from '../Types';
3 | import { BinaryNode } from '../WABinary';
4 | export declare const generateMobileNode: (config: SocketConfig) => proto.IClientPayload;
5 | export declare const generateLoginNode: (userJid: string, config: SocketConfig) => proto.IClientPayload;
6 | export declare const generateRegistrationNode: ({ registrationId, signedPreKey, signedIdentityKey }: SignalCreds, config: SocketConfig) => proto.ClientPayload;
7 | export declare const configureSuccessfulPairing: (stanza: BinaryNode, { advSecretKey, signedIdentityKey, signalIdentities }: Pick) => {
8 | creds: Partial;
9 | reply: BinaryNode;
10 | };
11 | export declare const encodeSignedDeviceIdentity: (account: proto.IADVSignedDeviceIdentity, includeSignatureKey: boolean) => Uint8Array;
12 |
--------------------------------------------------------------------------------
/lib/Socket/Client/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | Object.defineProperty(exports, "__esModule", { value: true });
17 | __exportStar(require("./abstract-socket-client"), exports);
18 | __exportStar(require("./mobile-socket-client"), exports);
19 | __exportStar(require("./web-socket-client"), exports);
20 |
--------------------------------------------------------------------------------
/lib/Types/State.d.ts:
--------------------------------------------------------------------------------
1 | import { Contact } from './Contact';
2 | export type WAConnectionState = 'open' | 'connecting' | 'close';
3 | export type ConnectionState = {
4 | /** connection is now open, connecting or closed */
5 | connection: WAConnectionState;
6 | /** the error that caused the connection to close */
7 | lastDisconnect?: {
8 | error: Error | undefined;
9 | date: Date;
10 | };
11 | /** is this a new login */
12 | isNewLogin?: boolean;
13 | /** the current QR code */
14 | qr?: string;
15 | /** has the device received all pending notifications while it was offline */
16 | receivedPendingNotifications?: boolean;
17 | /** legacy connection options */
18 | legacy?: {
19 | phoneConnected: boolean;
20 | user?: Contact;
21 | };
22 | /**
23 | * if the client is shown as an active, online client.
24 | * If this is false, the primary phone and other devices will receive notifs
25 | * */
26 | isOnline?: boolean;
27 | };
28 |
--------------------------------------------------------------------------------
/lib/Types/LabelAssociation.d.ts:
--------------------------------------------------------------------------------
1 | /** Association type */
2 | export declare enum LabelAssociationType {
3 | Chat = "label_jid",
4 | Message = "label_message"
5 | }
6 | export type LabelAssociationTypes = `${LabelAssociationType}`;
7 | /** Association for chat */
8 | export interface ChatLabelAssociation {
9 | type: LabelAssociationType.Chat;
10 | chatId: string;
11 | labelId: string;
12 | }
13 | /** Association for message */
14 | export interface MessageLabelAssociation {
15 | type: LabelAssociationType.Message;
16 | chatId: string;
17 | messageId: string;
18 | labelId: string;
19 | }
20 | export type LabelAssociation = ChatLabelAssociation | MessageLabelAssociation;
21 | /** Body for add/remove chat label association action */
22 | export interface ChatLabelAssociationActionBody {
23 | labelId: string;
24 | }
25 | /** body for add/remove message label association action */
26 | export interface MessageLabelAssociationActionBody {
27 | labelId: string;
28 | messageId: string;
29 | }
30 |
--------------------------------------------------------------------------------
/lib/Utils/noise-handler.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Logger } from 'pino';
3 | import { proto } from '../../WAProto';
4 | import { KeyPair } from '../Types';
5 | import { BinaryNode } from '../WABinary';
6 | export declare const makeNoiseHandler: ({ keyPair: { private: privateKey, public: publicKey }, NOISE_HEADER, mobile, logger, routingInfo }: {
7 | keyPair: KeyPair;
8 | NOISE_HEADER: Uint8Array;
9 | mobile: boolean;
10 | logger: Logger;
11 | routingInfo?: Buffer | undefined;
12 | }) => {
13 | encrypt: (plaintext: Uint8Array) => Buffer;
14 | decrypt: (ciphertext: Uint8Array) => Buffer;
15 | authenticate: (data: Uint8Array) => void;
16 | mixIntoKey: (data: Uint8Array) => void;
17 | finishInit: () => void;
18 | processHandshake: ({ serverHello }: proto.HandshakeMessage, noiseKey: KeyPair) => Buffer;
19 | encodeFrame: (data: Buffer | Uint8Array) => Buffer;
20 | decodeFrame: (newData: Buffer | Uint8Array, onFrame: (buff: Uint8Array | BinaryNode) => void) => void;
21 | };
22 |
--------------------------------------------------------------------------------
/lib/WABinary/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | Object.defineProperty(exports, "__esModule", { value: true });
17 | __exportStar(require("./encode"), exports);
18 | __exportStar(require("./decode"), exports);
19 | __exportStar(require("./generic-utils"), exports);
20 | __exportStar(require("./jid-utils"), exports);
21 | __exportStar(require("./types"), exports);
22 |
--------------------------------------------------------------------------------
/lib/WAM/constants.d.ts:
--------------------------------------------------------------------------------
1 | export declare const WEB_EVENTS: Event[];
2 | export declare const WEB_GLOBALS: Global[];
3 | export declare const FLAG_BYTE = 8, FLAG_GLOBAL = 0, FLAG_EVENT = 1, FLAG_FIELD = 2, FLAG_EXTENDED = 4;
4 | export type Event = {
5 | name: string;
6 | id: number;
7 | props: {
8 | [key: string]: [number, string | {
9 | [key: string]: number;
10 | }];
11 | };
12 | weight: number;
13 | wamChannel: string;
14 | privateStatsIdInt: number;
15 | };
16 | export type Global = {
17 | name: string;
18 | id: number;
19 | type: string | {
20 | [key: string]: number;
21 | };
22 | validator?: string;
23 | channels: string[];
24 | };
25 | type EventByName = Extract;
28 | export type EventInputType = {
29 | [key in Event['name']]: {
30 | props: {
31 | [k in keyof EventByName['props']]: any;
32 | };
33 | globals: {
34 | [x: string]: any;
35 | };
36 | };
37 | } & {};
38 | export {};
39 |
--------------------------------------------------------------------------------
/WASignalGroup/sender_message_key.js:
--------------------------------------------------------------------------------
1 | const { deriveSecrets } = require('libsignal/src/crypto');
2 | class SenderMessageKey {
3 | iteration = 0;
4 |
5 | iv = Buffer.alloc(0);
6 |
7 | cipherKey = Buffer.alloc(0);
8 |
9 | seed = Buffer.alloc(0);
10 |
11 | constructor(iteration, seed) {
12 | const derivative = deriveSecrets(seed, Buffer.alloc(32), Buffer.from('WhisperGroup'));
13 | const keys = new Uint8Array(32);
14 | keys.set(new Uint8Array(derivative[0].slice(16)));
15 | keys.set(new Uint8Array(derivative[1].slice(0, 16)), 16);
16 | this.iv = Buffer.from(derivative[0].slice(0, 16));
17 | this.cipherKey = Buffer.from(keys.buffer);
18 |
19 | this.iteration = iteration;
20 | this.seed = seed;
21 | }
22 |
23 | getIteration() {
24 | return this.iteration;
25 | }
26 |
27 | getIv() {
28 | return this.iv;
29 | }
30 |
31 | getCipherKey() {
32 | return this.cipherKey;
33 | }
34 |
35 | getSeed() {
36 | return this.seed;
37 | }
38 | }
39 | module.exports = SenderMessageKey;
--------------------------------------------------------------------------------
/lib/Utils/auth-utils.d.ts:
--------------------------------------------------------------------------------
1 | import type { Logger } from 'pino';
2 | import type { AuthenticationCreds, CacheStore, SignalKeyStore, SignalKeyStoreWithTransaction, TransactionCapabilityOptions } from '../Types';
3 | /**
4 | * Adds caching capability to a SignalKeyStore
5 | * @param store the store to add caching to
6 | * @param logger to log trace events
7 | * @param _cache cache store to use
8 | */
9 | export declare function makeCacheableSignalKeyStore(store: SignalKeyStore, logger: Logger, _cache?: CacheStore): SignalKeyStore;
10 | /**
11 | * Adds DB like transaction capability (https://en.wikipedia.org/wiki/Database_transaction) to the SignalKeyStore,
12 | * this allows batch read & write operations & improves the performance of the lib
13 | * @param state the key store to apply this capability to
14 | * @param logger logger to log events
15 | * @returns SignalKeyStore with transaction capability
16 | */
17 | export declare const addTransactionCapability: (state: SignalKeyStore, logger: Logger, { maxCommitRetries, delayBetweenTriesMs }: TransactionCapabilityOptions) => SignalKeyStoreWithTransaction;
18 | export declare const initAuthCreds: () => AuthenticationCreds;
19 |
--------------------------------------------------------------------------------
/lib/WABinary/generic-utils.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { proto } from '../../WAProto';
3 | import { BinaryNode } from './types';
4 | export declare const getBinaryNodeChildren: (node: BinaryNode | undefined, childTag: string) => BinaryNode[];
5 | export declare const getAllBinaryNodeChildren: ({ content }: BinaryNode) => BinaryNode[];
6 | export declare const getBinaryNodeChild: (node: BinaryNode | undefined, childTag: string) => BinaryNode | undefined;
7 | export declare const getBinaryNodeChildBuffer: (node: BinaryNode | undefined, childTag: string) => Uint8Array | Buffer | undefined;
8 | export declare const getBinaryNodeChildString: (node: BinaryNode | undefined, childTag: string) => string | undefined;
9 | export declare const getBinaryNodeChildUInt: (node: BinaryNode, childTag: string, length: number) => number | undefined;
10 | export declare const assertNodeErrorFree: (node: BinaryNode) => void;
11 | export declare const reduceBinaryNodeToDictionary: (node: BinaryNode, tag: string) => {
12 | [_: string]: string;
13 | };
14 | export declare const getBinaryNodeMessages: ({ content }: BinaryNode) => proto.WebMessageInfo[];
15 | export declare function binaryNodeToString(node: BinaryNode | BinaryNode['content'], i?: number): any;
16 |
--------------------------------------------------------------------------------
/lib/Utils/business.d.ts:
--------------------------------------------------------------------------------
1 | import { CatalogCollection, OrderDetails, Product, ProductCreate, ProductUpdate, WAMediaUpload, WAMediaUploadFunction } from '../Types';
2 | import { BinaryNode } from '../WABinary';
3 | export declare const parseCatalogNode: (node: BinaryNode) => {
4 | products: Product[];
5 | nextPageCursor: string | undefined;
6 | };
7 | export declare const parseCollectionsNode: (node: BinaryNode) => {
8 | collections: CatalogCollection[];
9 | };
10 | export declare const parseOrderDetailsNode: (node: BinaryNode) => OrderDetails;
11 | export declare const toProductNode: (productId: string | undefined, product: ProductCreate | ProductUpdate) => BinaryNode;
12 | export declare const parseProductNode: (productNode: BinaryNode) => Product;
13 | /**
14 | * Uploads images not already uploaded to WA's servers
15 | */
16 | export declare function uploadingNecessaryImagesOfProduct(product: T, waUploadToServer: WAMediaUploadFunction, timeoutMs?: number): Promise;
17 | /**
18 | * Uploads images not already uploaded to WA's servers
19 | */
20 | export declare const uploadingNecessaryImages: (images: WAMediaUpload[], waUploadToServer: WAMediaUploadFunction, timeoutMs?: number) => Promise<{
21 | url: string;
22 | }[]>;
23 |
--------------------------------------------------------------------------------
/WASignalGroup/sender_chain_key.js:
--------------------------------------------------------------------------------
1 | const SenderMessageKey = require('./sender_message_key');
2 | //const HKDF = require('./hkdf');
3 | const crypto = require('libsignal/src/crypto');
4 |
5 | class SenderChainKey {
6 | MESSAGE_KEY_SEED = Buffer.from([0x01]);
7 |
8 | CHAIN_KEY_SEED = Buffer.from([0x02]);
9 |
10 | iteration = 0;
11 |
12 | chainKey = Buffer.alloc(0);
13 |
14 | constructor(iteration, chainKey) {
15 | this.iteration = iteration;
16 | this.chainKey = chainKey;
17 | }
18 |
19 | getIteration() {
20 | return this.iteration;
21 | }
22 |
23 | getSenderMessageKey() {
24 | return new SenderMessageKey(
25 | this.iteration,
26 | this.getDerivative(this.MESSAGE_KEY_SEED, this.chainKey)
27 | );
28 | }
29 |
30 | getNext() {
31 | return new SenderChainKey(
32 | this.iteration + 1,
33 | this.getDerivative(this.CHAIN_KEY_SEED, this.chainKey)
34 | );
35 | }
36 |
37 | getSeed() {
38 | return typeof this.chainKey === 'string' ? Buffer.from(this.chainKey, 'base64') : this.chainKey;
39 | }
40 |
41 | getDerivative(seed, key) {
42 | key = typeof key === 'string' ? Buffer.from(key, 'base64') : key;
43 | const hash = crypto.calculateMAC(key, seed);
44 | //const hash = new Hash().hmac_hash(key, seed, 'sha256', '');
45 |
46 | return hash;
47 | }
48 | }
49 |
50 | module.exports = SenderChainKey;
--------------------------------------------------------------------------------
/lib/Types/Label.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.LabelColor = void 0;
4 | /** WhatsApp has 20 predefined colors */
5 | var LabelColor;
6 | (function (LabelColor) {
7 | LabelColor[LabelColor["Color1"] = 0] = "Color1";
8 | LabelColor[LabelColor["Color2"] = 1] = "Color2";
9 | LabelColor[LabelColor["Color3"] = 2] = "Color3";
10 | LabelColor[LabelColor["Color4"] = 3] = "Color4";
11 | LabelColor[LabelColor["Color5"] = 4] = "Color5";
12 | LabelColor[LabelColor["Color6"] = 5] = "Color6";
13 | LabelColor[LabelColor["Color7"] = 6] = "Color7";
14 | LabelColor[LabelColor["Color8"] = 7] = "Color8";
15 | LabelColor[LabelColor["Color9"] = 8] = "Color9";
16 | LabelColor[LabelColor["Color10"] = 9] = "Color10";
17 | LabelColor[LabelColor["Color11"] = 10] = "Color11";
18 | LabelColor[LabelColor["Color12"] = 11] = "Color12";
19 | LabelColor[LabelColor["Color13"] = 12] = "Color13";
20 | LabelColor[LabelColor["Color14"] = 13] = "Color14";
21 | LabelColor[LabelColor["Color15"] = 14] = "Color15";
22 | LabelColor[LabelColor["Color16"] = 15] = "Color16";
23 | LabelColor[LabelColor["Color17"] = 16] = "Color17";
24 | LabelColor[LabelColor["Color18"] = 17] = "Color18";
25 | LabelColor[LabelColor["Color19"] = 18] = "Color19";
26 | LabelColor[LabelColor["Color20"] = 19] = "Color20";
27 | })(LabelColor = exports.LabelColor || (exports.LabelColor = {}));
28 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | var __importDefault = (this && this.__importDefault) || function (mod) {
17 | return (mod && mod.__esModule) ? mod : { "default": mod };
18 | };
19 | Object.defineProperty(exports, "__esModule", { value: true });
20 | exports.makeWASocket = void 0;
21 | const Socket_1 = __importDefault(require("./Socket"));
22 | exports.makeWASocket = Socket_1.default;
23 | __exportStar(require("../WAProto"), exports);
24 | __exportStar(require("./Utils"), exports);
25 | __exportStar(require("./Types"), exports);
26 | __exportStar(require("./Store"), exports);
27 | __exportStar(require("./Defaults"), exports);
28 | __exportStar(require("./WABinary"), exports);
29 | __exportStar(require("./WAM"), exports);
30 | exports.default = Socket_1.default;
31 |
--------------------------------------------------------------------------------
/lib/Utils/make-mutex.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.makeKeyedMutex = exports.makeMutex = void 0;
4 | const makeMutex = () => {
5 | let task = Promise.resolve();
6 | let taskTimeout;
7 | return {
8 | mutex(code) {
9 | task = (async () => {
10 | // wait for the previous task to complete
11 | // if there is an error, we swallow so as to not block the queue
12 | try {
13 | await task;
14 | }
15 | catch (_a) { }
16 | try {
17 | // execute the current task
18 | const result = await code();
19 | return result;
20 | }
21 | finally {
22 | clearTimeout(taskTimeout);
23 | }
24 | })();
25 | // we replace the existing task, appending the new piece of execution to it
26 | // so the next task will have to wait for this one to finish
27 | return task;
28 | },
29 | };
30 | };
31 | exports.makeMutex = makeMutex;
32 | const makeKeyedMutex = () => {
33 | const map = {};
34 | return {
35 | mutex(key, task) {
36 | if (!map[key]) {
37 | map[key] = (0, exports.makeMutex)();
38 | }
39 | return map[key].mutex(task);
40 | }
41 | };
42 | };
43 | exports.makeKeyedMutex = makeKeyedMutex;
44 |
--------------------------------------------------------------------------------
/lib/Utils/event-buffer.d.ts:
--------------------------------------------------------------------------------
1 | import { Logger } from 'pino';
2 | import { BaileysEventEmitter, BaileysEventMap } from '../Types';
3 | /**
4 | * A map that contains a list of all events that have been triggered
5 | *
6 | * Note, this can contain different type of events
7 | * this can make processing events extremely efficient -- since everything
8 | * can be done in a single transaction
9 | */
10 | type BaileysEventData = Partial;
11 | type BaileysBufferableEventEmitter = BaileysEventEmitter & {
12 | /** Use to process events in a batch */
13 | process(handler: (events: BaileysEventData) => void | Promise): (() => void);
14 | /**
15 | * starts buffering events, call flush() to release them
16 | * */
17 | buffer(): void;
18 | /** buffers all events till the promise completes */
19 | createBufferedFunction(work: (...args: A) => Promise): ((...args: A) => Promise);
20 | /**
21 | * flushes all buffered events
22 | * @param force if true, will flush all data regardless of any pending buffers
23 | * @returns returns true if the flush actually happened, otherwise false
24 | */
25 | flush(force?: boolean): boolean;
26 | /** is there an ongoing buffer */
27 | isBuffering(): boolean;
28 | };
29 | /**
30 | * The event buffer logically consolidates different events into a single event
31 | * making the data processing more efficient.
32 | * @param ev the baileys event emitter
33 | */
34 | export declare const makeEventBuffer: (logger: Logger) => BaileysBufferableEventEmitter;
35 | export {};
36 |
--------------------------------------------------------------------------------
/WASignalGroup/sender_key_name.js:
--------------------------------------------------------------------------------
1 | function isNull(str) {
2 | return str === null || str.value === '';
3 | }
4 |
5 | /**
6 | * java String hashCode 的实现
7 | * @param strKey
8 | * @return intValue
9 | */
10 | function intValue(num) {
11 | const MAX_VALUE = 0x7fffffff;
12 | const MIN_VALUE = -0x80000000;
13 | if (num > MAX_VALUE || num < MIN_VALUE) {
14 | // eslint-disable-next-line
15 | return (num &= 0xffffffff);
16 | }
17 | return num;
18 | }
19 |
20 | function hashCode(strKey) {
21 | let hash = 0;
22 | if (!isNull(strKey)) {
23 | for (let i = 0; i < strKey.length; i++) {
24 | hash = hash * 31 + strKey.charCodeAt(i);
25 | hash = intValue(hash);
26 | }
27 | }
28 | return hash;
29 | }
30 |
31 | /**
32 | * 将js页面的number类型转换为java的int类型
33 | * @param num
34 | * @return intValue
35 | */
36 |
37 | class SenderKeyName {
38 | constructor(groupId, sender) {
39 | this.groupId = groupId;
40 | this.sender = sender;
41 | }
42 |
43 | getGroupId() {
44 | return this.groupId;
45 | }
46 |
47 | getSender() {
48 | return this.sender;
49 | }
50 |
51 | serialize() {
52 | return `${this.groupId}::${this.sender.id}::${this.sender.deviceId}`;
53 | }
54 |
55 | toString() {
56 | return this.serialize();
57 | }
58 |
59 | equals(other) {
60 | if (other === null) return false;
61 | if (!(other instanceof SenderKeyName)) return false;
62 | return this.groupId === other.groupId && this.sender.toString() === other.sender.toString();
63 | }
64 |
65 | hashCode() {
66 | return hashCode(this.groupId) ^ hashCode(this.sender.toString());
67 | }
68 | }
69 |
70 | module.exports = SenderKeyName;
--------------------------------------------------------------------------------
/lib/Types/Newsletter.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.QueryIds = exports.XWAPaths = exports.MexOperations = void 0;
4 | var MexOperations;
5 | (function (MexOperations) {
6 | MexOperations["PROMOTE"] = "NotificationNewsletterAdminPromote";
7 | MexOperations["DEMOTE"] = "NotificationNewsletterAdminDemote";
8 | MexOperations["UPDATE"] = "NotificationNewsletterUpdate";
9 | })(MexOperations = exports.MexOperations || (exports.MexOperations = {}));
10 | var XWAPaths;
11 | (function (XWAPaths) {
12 | XWAPaths["PROMOTE"] = "xwa2_notify_newsletter_admin_promote";
13 | XWAPaths["DEMOTE"] = "xwa2_notify_newsletter_admin_demote";
14 | XWAPaths["ADMIN_COUNT"] = "xwa2_newsletter_admin";
15 | XWAPaths["CREATE"] = "xwa2_newsletter_create";
16 | XWAPaths["NEWSLETTER"] = "xwa2_newsletter";
17 | XWAPaths["METADATA_UPDATE"] = "xwa2_notify_newsletter_on_metadata_update";
18 | })(XWAPaths = exports.XWAPaths || (exports.XWAPaths = {}));
19 | var QueryIds;
20 | (function (QueryIds) {
21 | QueryIds["JOB_MUTATION"] = "7150902998257522";
22 | QueryIds["METADATA"] = "6620195908089573";
23 | QueryIds["UNFOLLOW"] = "7238632346214362";
24 | QueryIds["FOLLOW"] = "7871414976211147";
25 | QueryIds["UNMUTE"] = "7337137176362961";
26 | QueryIds["MUTE"] = "25151904754424642";
27 | QueryIds["CREATE"] = "6996806640408138";
28 | QueryIds["ADMIN_COUNT"] = "7130823597031706";
29 | QueryIds["CHANGE_OWNER"] = "7341777602580933";
30 | QueryIds["DELETE"] = "8316537688363079";
31 | QueryIds["DEMOTE"] = "6551828931592903";
32 | })(QueryIds = exports.QueryIds || (exports.QueryIds = {}));
33 |
--------------------------------------------------------------------------------
/lib/Types/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './Auth';
2 | export * from './GroupMetadata';
3 | export * from './Chat';
4 | export * from './Contact';
5 | export * from './State';
6 | export * from './Message';
7 | export * from './Newsletter';
8 | export * from './Socket';
9 | export * from './Events';
10 | export * from './Product';
11 | export * from './Call';
12 | export * from './Signal';
13 | import { AuthenticationState } from './Auth';
14 | import { SocketConfig } from './Socket';
15 | export type UserFacingSocketConfig = Partial & {
16 | auth: AuthenticationState;
17 | };
18 | export declare enum DisconnectReason {
19 | connectionClosed = 428,
20 | connectionLost = 408,
21 | connectionReplaced = 440,
22 | timedOut = 408,
23 | loggedOut = 401,
24 | badSession = 500,
25 | restartRequired = 515,
26 | multideviceMismatch = 411,
27 | forbidden = 403,
28 | unavailableService = 503
29 | }
30 | export type WAInitResponse = {
31 | ref: string;
32 | ttl: number;
33 | status: 200;
34 | };
35 | export type WABusinessHoursConfig = {
36 | day_of_week: string;
37 | mode: string;
38 | open_time?: number;
39 | close_time?: number;
40 | };
41 | export type WABusinessProfile = {
42 | description: string;
43 | email: string | undefined;
44 | business_hours: {
45 | timezone?: string;
46 | config?: WABusinessHoursConfig[];
47 | business_config?: WABusinessHoursConfig[];
48 | };
49 | website: string[];
50 | category?: string;
51 | wid?: string;
52 | address?: string;
53 | };
54 | export type CurveKeyPair = {
55 | private: Uint8Array;
56 | public: Uint8Array;
57 | };
58 |
--------------------------------------------------------------------------------
/lib/Utils/signal.d.ts:
--------------------------------------------------------------------------------
1 | import { SignalRepository } from '../Types';
2 | import { AuthenticationCreds, AuthenticationState, KeyPair, SignalIdentity, SignalKeyStore, SignedKeyPair } from '../Types/Auth';
3 | import { BinaryNode, JidWithDevice } from '../WABinary';
4 | export declare const createSignalIdentity: (wid: string, accountSignatureKey: Uint8Array) => SignalIdentity;
5 | export declare const getPreKeys: ({ get }: SignalKeyStore, min: number, limit: number) => Promise<{
6 | [id: string]: KeyPair;
7 | }>;
8 | export declare const generateOrGetPreKeys: (creds: AuthenticationCreds, range: number) => {
9 | newPreKeys: {
10 | [id: number]: KeyPair;
11 | };
12 | lastPreKeyId: number;
13 | preKeysRange: readonly [number, number];
14 | };
15 | export declare const xmppSignedPreKey: (key: SignedKeyPair) => BinaryNode;
16 | export declare const xmppPreKey: (pair: KeyPair, id: number) => BinaryNode;
17 | export declare const parseAndInjectE2ESessions: (node: BinaryNode, repository: SignalRepository) => Promise;
18 | export declare const extractDeviceJids: (result: BinaryNode, myJid: string, excludeZeroDevices: boolean) => JidWithDevice[];
19 | /**
20 | * get the next N keys for upload or processing
21 | * @param count number of pre-keys to get or generate
22 | */
23 | export declare const getNextPreKeys: ({ creds, keys }: AuthenticationState, count: number) => Promise<{
24 | update: Partial;
25 | preKeys: {
26 | [id: string]: KeyPair;
27 | };
28 | }>;
29 | export declare const getNextPreKeysNode: (state: AuthenticationState, count: number) => Promise<{
30 | update: Partial;
31 | node: BinaryNode;
32 | }>;
33 |
--------------------------------------------------------------------------------
/lib/Utils/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | Object.defineProperty(exports, "__esModule", { value: true });
17 | __exportStar(require("./generics"), exports);
18 | __exportStar(require("./decode-wa-message"), exports);
19 | __exportStar(require("./messages"), exports);
20 | __exportStar(require("./messages-media"), exports);
21 | __exportStar(require("./validate-connection"), exports);
22 | __exportStar(require("./crypto"), exports);
23 | __exportStar(require("./signal"), exports);
24 | __exportStar(require("./noise-handler"), exports);
25 | __exportStar(require("./history"), exports);
26 | __exportStar(require("./chat-utils"), exports);
27 | __exportStar(require("./lt-hash"), exports);
28 | __exportStar(require("./auth-utils"), exports);
29 | __exportStar(require("./baileys-event-stream"), exports);
30 | __exportStar(require("./use-multi-file-auth-state"), exports);
31 | __exportStar(require("./link-preview"), exports);
32 | __exportStar(require("./event-buffer"), exports);
33 | __exportStar(require("./process-message"), exports);
34 |
--------------------------------------------------------------------------------
/lib/WABinary/jid-utils.d.ts:
--------------------------------------------------------------------------------
1 | export declare const S_WHATSAPP_NET = "@s.whatsapp.net";
2 | export declare const OFFICIAL_BIZ_JID = "16505361212@c.us";
3 | export declare const SERVER_JID = "server@c.us";
4 | export declare const PSA_WID = "0@c.us";
5 | export declare const STORIES_JID = "status@broadcast";
6 | export type JidServer = 'c.us' | 'g.us' | 'broadcast' | 's.whatsapp.net' | 'call' | 'lid' | 'newsletter';
7 | export type JidWithDevice = {
8 | user: string;
9 | device?: number;
10 | };
11 | export type FullJid = JidWithDevice & {
12 | server: JidServer | string;
13 | domainType?: number;
14 | };
15 | export declare const jidEncode: (user: string | number | null, server: JidServer, device?: number, agent?: number) => string;
16 | export declare const jidDecode: (jid: string | undefined) => FullJid | undefined;
17 | /** is the jid a user */
18 | export declare const areJidsSameUser: (jid1: string | undefined, jid2: string | undefined) => boolean;
19 | /** is the jid a user */
20 | export declare const isJidUser: (jid: string | undefined) => boolean | undefined;
21 | /** is the jid a group */
22 | export declare const isLidUser: (jid: string | undefined) => boolean | undefined;
23 | /** is the jid a broadcast */
24 | export declare const isJidBroadcast: (jid: string | undefined) => boolean | undefined;
25 | /** is the jid a group */
26 | export declare const isJidGroup: (jid: string | undefined) => boolean | undefined;
27 | /** is the jid the status broadcast */
28 | export declare const isJidStatusBroadcast: (jid: string) => boolean;
29 | /** is the jid the newsletter */
30 | export declare const isJidNewsLetter: (jid: string | undefined) => boolean | undefined;
31 | export declare const jidNormalizedUser: (jid: string | undefined) => string;
32 |
--------------------------------------------------------------------------------
/lib/Types/Signal.d.ts:
--------------------------------------------------------------------------------
1 | import { proto } from '../../WAProto';
2 | type DecryptGroupSignalOpts = {
3 | group: string;
4 | authorJid: string;
5 | msg: Uint8Array;
6 | };
7 | type ProcessSenderKeyDistributionMessageOpts = {
8 | item: proto.Message.ISenderKeyDistributionMessage;
9 | authorJid: string;
10 | };
11 | type DecryptSignalProtoOpts = {
12 | jid: string;
13 | type: 'pkmsg' | 'msg';
14 | ciphertext: Uint8Array;
15 | };
16 | type EncryptMessageOpts = {
17 | jid: string;
18 | data: Uint8Array;
19 | };
20 | type EncryptGroupMessageOpts = {
21 | group: string;
22 | data: Uint8Array;
23 | meId: string;
24 | };
25 | type PreKey = {
26 | keyId: number;
27 | publicKey: Uint8Array;
28 | };
29 | type SignedPreKey = PreKey & {
30 | signature: Uint8Array;
31 | };
32 | type E2ESession = {
33 | registrationId: number;
34 | identityKey: Uint8Array;
35 | signedPreKey: SignedPreKey;
36 | preKey: PreKey;
37 | };
38 | type E2ESessionOpts = {
39 | jid: string;
40 | session: E2ESession;
41 | };
42 | export type SignalRepository = {
43 | decryptGroupMessage(opts: DecryptGroupSignalOpts): Promise;
44 | processSenderKeyDistributionMessage(opts: ProcessSenderKeyDistributionMessageOpts): Promise;
45 | decryptMessage(opts: DecryptSignalProtoOpts): Promise;
46 | encryptMessage(opts: EncryptMessageOpts): Promise<{
47 | type: 'pkmsg' | 'msg';
48 | ciphertext: Uint8Array;
49 | }>;
50 | encryptGroupMessage(opts: EncryptGroupMessageOpts): Promise<{
51 | senderKeyDistributionMessage: Uint8Array;
52 | ciphertext: Uint8Array;
53 | }>;
54 | injectE2ESession(opts: E2ESessionOpts): Promise;
55 | jidToSignalProtocolAddress(jid: string): string;
56 | };
57 | export {};
58 |
--------------------------------------------------------------------------------
/WASignalGroup/sender_key_record.js:
--------------------------------------------------------------------------------
1 | const SenderKeyState = require('./sender_key_state');
2 |
3 | class SenderKeyRecord {
4 | MAX_STATES = 5;
5 |
6 | constructor(serialized) {
7 | this.senderKeyStates = [];
8 |
9 | if (serialized) {
10 | const list = serialized;
11 | for (let i = 0; i < list.length; i++) {
12 | const structure = list[i];
13 | this.senderKeyStates.push(
14 | new SenderKeyState(null, null, null, null, null, null, structure)
15 | );
16 | }
17 | }
18 | }
19 |
20 | isEmpty() {
21 | return this.senderKeyStates.length === 0;
22 | }
23 |
24 | getSenderKeyState(keyId) {
25 | if (!keyId && this.senderKeyStates.length) return this.senderKeyStates[this.senderKeyStates.length - 1];
26 | for (let i = 0; i < this.senderKeyStates.length; i++) {
27 | const state = this.senderKeyStates[i];
28 | if (state.getKeyId() === keyId) {
29 | return state;
30 | }
31 | }
32 | }
33 |
34 | addSenderKeyState(id, iteration, chainKey, signatureKey) {
35 | this.senderKeyStates.push(new SenderKeyState(id, iteration, chainKey, null, signatureKey));
36 | if (this.senderKeyStates.length > 5) {
37 | this.senderKeyStates.shift()
38 | }
39 | }
40 |
41 | setSenderKeyState(id, iteration, chainKey, keyPair) {
42 | this.senderKeyStates.length = 0;
43 | this.senderKeyStates.push(new SenderKeyState(id, iteration, chainKey, keyPair));
44 | }
45 |
46 | serialize() {
47 | const recordStructure = [];
48 | for (let i = 0; i < this.senderKeyStates.length; i++) {
49 | const senderKeyState = this.senderKeyStates[i];
50 | recordStructure.push(senderKeyState.getStructure());
51 | }
52 | return recordStructure;
53 | }
54 | }
55 |
56 | module.exports = SenderKeyRecord;
--------------------------------------------------------------------------------
/lib/Utils/lt-hash.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.LT_HASH_ANTI_TAMPERING = void 0;
4 | const crypto_1 = require("./crypto");
5 | /**
6 | * LT Hash is a summation based hash algorithm that maintains the integrity of a piece of data
7 | * over a series of mutations. You can add/remove mutations and it'll return a hash equal to
8 | * if the same series of mutations was made sequentially.
9 | */
10 | const o = 128;
11 | class d {
12 | constructor(e) {
13 | this.salt = e;
14 | }
15 | add(e, t) {
16 | var r = this;
17 | for (const item of t) {
18 | e = r._addSingle(e, item);
19 | }
20 | return e;
21 | }
22 | subtract(e, t) {
23 | var r = this;
24 | for (const item of t) {
25 | e = r._subtractSingle(e, item);
26 | }
27 | return e;
28 | }
29 | subtractThenAdd(e, t, r) {
30 | var n = this;
31 | return n.add(n.subtract(e, r), t);
32 | }
33 | _addSingle(e, t) {
34 | var r = this;
35 | const n = new Uint8Array((0, crypto_1.hkdf)(Buffer.from(t), o, { info: r.salt })).buffer;
36 | return r.performPointwiseWithOverflow(e, n, ((e, t) => e + t));
37 | }
38 | _subtractSingle(e, t) {
39 | var r = this;
40 | const n = new Uint8Array((0, crypto_1.hkdf)(Buffer.from(t), o, { info: r.salt })).buffer;
41 | return r.performPointwiseWithOverflow(e, n, ((e, t) => e - t));
42 | }
43 | performPointwiseWithOverflow(e, t, r) {
44 | const n = new DataView(e), i = new DataView(t), a = new ArrayBuffer(n.byteLength), s = new DataView(a);
45 | for (let e = 0; e < n.byteLength; e += 2) {
46 | s.setUint16(e, r(n.getUint16(e, !0), i.getUint16(e, !0)), !0);
47 | }
48 | return a;
49 | }
50 | }
51 | exports.LT_HASH_ANTI_TAMPERING = new d('WhatsApp Patch Integrity');
52 |
--------------------------------------------------------------------------------
/lib/Types/GroupMetadata.d.ts:
--------------------------------------------------------------------------------
1 | import { Contact } from './Contact';
2 | export type GroupParticipant = (Contact & {
3 | isAdmin?: boolean;
4 | isSuperAdmin?: boolean;
5 | admin?: 'admin' | 'superadmin' | null;
6 | });
7 | export type ParticipantAction = 'add' | 'remove' | 'promote' | 'demote';
8 | export interface GroupMetadata {
9 | id: string;
10 | owner: string | undefined;
11 | subject: string;
12 | /** group subject owner */
13 | subjectOwner?: string;
14 | /** group subject modification date */
15 | subjectTime?: number;
16 | creation?: number;
17 | desc?: string;
18 | descOwner?: string;
19 | descId?: string;
20 | /** if this group is part of a community, it returns the jid of the community to which it belongs */
21 | linkedParent?: string;
22 | /** is set when the group only allows admins to change group settings */
23 | restrict?: boolean;
24 | /** is set when the group only allows admins to write messages */
25 | announce?: boolean;
26 | /** is set when the group also allows members to add participants */
27 | memberAddMode?: boolean;
28 | /** Request approval to join the group */
29 | joinApprovalMode?: boolean;
30 | /** is this a community */
31 | isCommunity?: boolean;
32 | /** is this the announce of a community */
33 | isCommunityAnnounce?: boolean;
34 | /** number of group participants */
35 | size?: number;
36 | participants: GroupParticipant[];
37 | ephemeralDuration?: number;
38 | inviteCode?: string;
39 | /** the person who added you to group or changed some setting in group */
40 | author?: string;
41 | }
42 | export interface WAGroupCreateResponse {
43 | status: number;
44 | gid?: string;
45 | participants?: [{
46 | [key: string]: {};
47 | }];
48 | }
49 | export interface GroupModificationResponse {
50 | status: number;
51 | participants?: {
52 | [key: string]: {};
53 | };
54 | }
55 |
--------------------------------------------------------------------------------
/WASignalGroup/group_session_builder.js:
--------------------------------------------------------------------------------
1 | //const utils = require('../../common/utils');
2 | const SenderKeyDistributionMessage = require('./sender_key_distribution_message');
3 |
4 | const keyhelper = require("./keyhelper");
5 | class GroupSessionBuilder {
6 | constructor(senderKeyStore) {
7 | this.senderKeyStore = senderKeyStore;
8 | }
9 |
10 | async process(senderKeyName, senderKeyDistributionMessage) {
11 | //console.log('GroupSessionBuilder process', senderKeyName, senderKeyDistributionMessage);
12 | const senderKeyRecord = await this.senderKeyStore.loadSenderKey(senderKeyName);
13 | senderKeyRecord.addSenderKeyState(
14 | senderKeyDistributionMessage.getId(),
15 | senderKeyDistributionMessage.getIteration(),
16 | senderKeyDistributionMessage.getChainKey(),
17 | senderKeyDistributionMessage.getSignatureKey()
18 | );
19 | await this.senderKeyStore.storeSenderKey(senderKeyName, senderKeyRecord);
20 | }
21 |
22 | // [{"senderKeyId":1742199468,"senderChainKey":{"iteration":0,"seed":"yxMY9VFQcXEP34olRAcGCtsgx1XoKsHfDIh+1ea4HAQ="},"senderSigningKey":{"public":""}}]
23 | async create(senderKeyName) {
24 | const senderKeyRecord = await this.senderKeyStore.loadSenderKey(senderKeyName);
25 | //console.log('GroupSessionBuilder create session', senderKeyName, senderKeyRecord);
26 |
27 | if (senderKeyRecord.isEmpty()) {
28 | const keyId = keyhelper.generateSenderKeyId();
29 | const senderKey = keyhelper.generateSenderKey();
30 | const signingKey = keyhelper.generateSenderSigningKey();
31 |
32 | senderKeyRecord.setSenderKeyState(keyId, 0, senderKey, signingKey);
33 | await this.senderKeyStore.storeSenderKey(senderKeyName, senderKeyRecord);
34 | }
35 |
36 | const state = senderKeyRecord.getSenderKeyState();
37 |
38 | return new SenderKeyDistributionMessage(
39 | state.getKeyId(),
40 | state.getSenderChainKey().getIteration(),
41 | state.getSenderChainKey().getSeed(),
42 | state.getSigningKeyPublic()
43 | );
44 | }
45 | }
46 | module.exports = GroupSessionBuilder;
--------------------------------------------------------------------------------
/lib/Types/Product.d.ts:
--------------------------------------------------------------------------------
1 | import { WAMediaUpload } from './Message';
2 | export type CatalogResult = {
3 | data: {
4 | paging: {
5 | cursors: {
6 | before: string;
7 | after: string;
8 | };
9 | };
10 | data: any[];
11 | };
12 | };
13 | export type ProductCreateResult = {
14 | data: {
15 | product: {};
16 | };
17 | };
18 | export type CatalogStatus = {
19 | status: string;
20 | canAppeal: boolean;
21 | };
22 | export type CatalogCollection = {
23 | id: string;
24 | name: string;
25 | products: Product[];
26 | status: CatalogStatus;
27 | };
28 | export type ProductAvailability = 'in stock';
29 | export type ProductBase = {
30 | name: string;
31 | retailerId?: string;
32 | url?: string;
33 | description: string;
34 | price: number;
35 | currency: string;
36 | isHidden?: boolean;
37 | };
38 | export type ProductCreate = ProductBase & {
39 | /** ISO country code for product origin. Set to undefined for no country */
40 | originCountryCode: string | undefined;
41 | /** images of the product */
42 | images: WAMediaUpload[];
43 | };
44 | export type ProductUpdate = Omit;
45 | export type Product = ProductBase & {
46 | id: string;
47 | imageUrls: {
48 | [_: string]: string;
49 | };
50 | reviewStatus: {
51 | [_: string]: string;
52 | };
53 | availability: ProductAvailability;
54 | };
55 | export type OrderPrice = {
56 | currency: string;
57 | total: number;
58 | };
59 | export type OrderProduct = {
60 | id: string;
61 | imageUrl: string;
62 | name: string;
63 | quantity: number;
64 | currency: string;
65 | price: number;
66 | };
67 | export type OrderDetails = {
68 | price: OrderPrice;
69 | products: OrderProduct[];
70 | };
71 | export type CatalogCursor = string;
72 | export type GetCatalogOptions = {
73 | /** cursor to start from */
74 | cursor?: CatalogCursor;
75 | /** number of products to fetch */
76 | limit?: number;
77 | jid?: string;
78 | };
79 |
--------------------------------------------------------------------------------
/lib/Utils/process-message.d.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig } from 'axios';
2 | import type { Logger } from 'pino';
3 | import { proto } from '../../WAProto';
4 | import { AuthenticationCreds, BaileysEventEmitter, SignalKeyStoreWithTransaction, SocketConfig } from '../Types';
5 | type ProcessMessageContext = {
6 | shouldProcessHistoryMsg: boolean;
7 | creds: AuthenticationCreds;
8 | keyStore: SignalKeyStoreWithTransaction;
9 | ev: BaileysEventEmitter;
10 | getMessage: SocketConfig['getMessage'];
11 | logger?: Logger;
12 | options: AxiosRequestConfig<{}>;
13 | };
14 | /** Cleans a received message to further processing */
15 | export declare const cleanMessage: (message: proto.IWebMessageInfo, meId: string) => void;
16 | export declare const isRealMessage: (message: proto.IWebMessageInfo, meId: string) => boolean | undefined;
17 | export declare const shouldIncrementChatUnread: (message: proto.IWebMessageInfo) => boolean;
18 | /**
19 | * Get the ID of the chat from the given key.
20 | * Typically -- that'll be the remoteJid, but for broadcasts, it'll be the participant
21 | */
22 | export declare const getChatId: ({ remoteJid, participant, fromMe }: proto.IMessageKey) => string;
23 | type PollContext = {
24 | /** normalised jid of the person that created the poll */
25 | pollCreatorJid: string;
26 | /** ID of the poll creation message */
27 | pollMsgId: string;
28 | /** poll creation message enc key */
29 | pollEncKey: Uint8Array;
30 | /** jid of the person that voted */
31 | voterJid: string;
32 | };
33 | /**
34 | * Decrypt a poll vote
35 | * @param vote encrypted vote
36 | * @param ctx additional info about the poll required for decryption
37 | * @returns list of SHA256 options
38 | */
39 | export declare function decryptPollVote({ encPayload, encIv }: proto.Message.IPollEncValue, { pollCreatorJid, pollMsgId, pollEncKey, voterJid, }: PollContext): proto.Message.PollVoteMessage;
40 | declare const processMessage: (message: proto.IWebMessageInfo, { shouldProcessHistoryMsg, ev, creds, keyStore, logger, options, getMessage }: ProcessMessageContext) => Promise;
41 | export default processMessage;
42 |
--------------------------------------------------------------------------------
/lib/Socket/socket.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Boom } from '@hapi/boom';
3 | import { SocketConfig } from '../Types';
4 | import { BinaryNode } from '../WABinary';
5 | /**
6 | * Connects to WA servers and performs:
7 | * - simple queries (no retry mechanism, wait for connection establishment)
8 | * - listen to messages and emit events
9 | * - query phone connection
10 | */
11 | export declare const makeSocket: (config: SocketConfig) => {
12 | type: "md";
13 | ws: any;
14 | ev: import("../Types").BaileysEventEmitter & {
15 | process(handler: (events: Partial) => void | Promise): () => void;
16 | buffer(): void;
17 | createBufferedFunction(work: (...args: A) => Promise): (...args: A) => Promise;
18 | flush(force?: boolean | undefined): boolean;
19 | isBuffering(): boolean;
20 | };
21 | authState: {
22 | creds: import("../Types").AuthenticationCreds;
23 | keys: import("../Types").SignalKeyStoreWithTransaction;
24 | };
25 | signalRepository: import("../Types").SignalRepository;
26 | readonly user: import("../Types").Contact | undefined;
27 | generateMessageTag: () => string;
28 | query: (node: BinaryNode, timeoutMs?: number) => Promise;
29 | waitForMessage: (msgId: string, timeoutMs?: number | undefined) => Promise;
30 | waitForSocketOpen: () => Promise;
31 | sendRawMessage: (data: Uint8Array | Buffer) => Promise;
32 | sendNode: (frame: BinaryNode) => Promise;
33 | logout: (msg?: string) => Promise;
34 | end: (error: Error | undefined) => void;
35 | onUnexpectedError: (err: Error | Boom, msg: string) => void;
36 | uploadPreKeys: (count?: number) => Promise;
37 | uploadPreKeysToServerIfRequired: () => Promise;
38 | requestPairingCode: (phoneNumber: string) => Promise;
39 | /** Waits for the connection to WA to reach a state */
40 | waitForConnectionUpdate: (check: (u: Partial) => boolean | undefined, timeoutMs?: number | undefined) => Promise;
41 | sendWAMBuffer: (wamBuffer: Buffer) => Promise;
42 | };
43 | export type Socket = ReturnType;
44 |
--------------------------------------------------------------------------------
/WASignalGroup/queue_job.js:
--------------------------------------------------------------------------------
1 | // vim: ts=4:sw=4:expandtab
2 |
3 | /*
4 | * jobQueue manages multiple queues indexed by device to serialize
5 | * session io ops on the database.
6 | */
7 | 'use strict';
8 |
9 |
10 | const _queueAsyncBuckets = new Map();
11 | const _gcLimit = 10000;
12 |
13 | async function _asyncQueueExecutor(queue, cleanup) {
14 | let offt = 0;
15 | while (true) {
16 | let limit = Math.min(queue.length, _gcLimit); // Break up thundering hurds for GC duty.
17 | for (let i = offt; i < limit; i++) {
18 | const job = queue[i];
19 | try {
20 | job.resolve(await job.awaitable());
21 | } catch (e) {
22 | job.reject(e);
23 | }
24 | }
25 | if (limit < queue.length) {
26 | /* Perform lazy GC of queue for faster iteration. */
27 | if (limit >= _gcLimit) {
28 | queue.splice(0, limit);
29 | offt = 0;
30 | } else {
31 | offt = limit;
32 | }
33 | } else {
34 | break;
35 | }
36 | }
37 | cleanup();
38 | }
39 |
40 | module.exports = function (bucket, awaitable) {
41 | /* Run the async awaitable only when all other async calls registered
42 | * here have completed (or thrown). The bucket argument is a hashable
43 | * key representing the task queue to use. */
44 | if (!awaitable.name) {
45 | // Make debuging easier by adding a name to this function.
46 | Object.defineProperty(awaitable, 'name', { writable: true });
47 | if (typeof bucket === 'string') {
48 | awaitable.name = bucket;
49 | } else {
50 | console.warn("Unhandled bucket type (for naming):", typeof bucket, bucket);
51 | }
52 | }
53 | let inactive;
54 | if (!_queueAsyncBuckets.has(bucket)) {
55 | _queueAsyncBuckets.set(bucket, []);
56 | inactive = true;
57 | }
58 | const queue = _queueAsyncBuckets.get(bucket);
59 | const job = new Promise((resolve, reject) => queue.push({
60 | awaitable,
61 | resolve,
62 | reject
63 | }));
64 | if (inactive) {
65 | /* An executor is not currently active; Start one now. */
66 | _asyncQueueExecutor(queue, () => _queueAsyncBuckets.delete(bucket));
67 | }
68 | return job;
69 | };
--------------------------------------------------------------------------------
/lib/Utils/crypto.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { KeyPair } from '../Types';
3 | /** prefix version byte to the pub keys, required for some curve crypto functions */
4 | export declare const generateSignalPubKey: (pubKey: Uint8Array | Buffer) => Uint8Array | Buffer;
5 | export declare const Curve: {
6 | generateKeyPair: () => KeyPair;
7 | sharedKey: (privateKey: Uint8Array, publicKey: Uint8Array) => Buffer;
8 | sign: (privateKey: Uint8Array, buf: Uint8Array) => any;
9 | verify: (pubKey: Uint8Array, message: Uint8Array, signature: Uint8Array) => boolean;
10 | };
11 | export declare const signedKeyPair: (identityKeyPair: KeyPair, keyId: number) => {
12 | keyPair: KeyPair;
13 | signature: any;
14 | keyId: number;
15 | };
16 | /**
17 | * encrypt AES 256 GCM;
18 | * where the tag tag is suffixed to the ciphertext
19 | * */
20 | export declare function aesEncryptGCM(plaintext: Uint8Array, key: Uint8Array, iv: Uint8Array, additionalData: Uint8Array): Buffer;
21 | /**
22 | * decrypt AES 256 GCM;
23 | * where the auth tag is suffixed to the ciphertext
24 | * */
25 | export declare function aesDecryptGCM(ciphertext: Uint8Array, key: Uint8Array, iv: Uint8Array, additionalData: Uint8Array): Buffer;
26 | export declare function aesEncryptCTR(plaintext: Uint8Array, key: Uint8Array, iv: Uint8Array): Buffer;
27 | export declare function aesDecryptCTR(ciphertext: Uint8Array, key: Uint8Array, iv: Uint8Array): Buffer;
28 | /** decrypt AES 256 CBC; where the IV is prefixed to the buffer */
29 | export declare function aesDecrypt(buffer: Buffer, key: Buffer): Buffer;
30 | /** decrypt AES 256 CBC */
31 | export declare function aesDecryptWithIV(buffer: Buffer, key: Buffer, IV: Buffer): Buffer;
32 | export declare function aesEncrypt(buffer: Buffer | Uint8Array, key: Buffer): Buffer;
33 | export declare function aesEncrypWithIV(buffer: Buffer, key: Buffer, IV: Buffer): Buffer;
34 | export declare function hmacSign(buffer: Buffer | Uint8Array, key: Buffer | Uint8Array, variant?: 'sha256' | 'sha512'): Buffer;
35 | export declare function sha256(buffer: Buffer): Buffer;
36 | export declare function md5(buffer: Buffer): Buffer;
37 | export declare function hkdf(buffer: Uint8Array | Buffer, expandedLength: number, info: {
38 | salt?: Buffer;
39 | info?: string;
40 | }): Buffer;
41 | export declare function derivePairingCodeKey(pairingCode: string, salt: Buffer): Buffer;
42 |
--------------------------------------------------------------------------------
/WASignalGroup/sender_key_distribution_message.js:
--------------------------------------------------------------------------------
1 | const CiphertextMessage = require('./ciphertext_message');
2 | const protobufs = require('./protobufs');
3 |
4 | class SenderKeyDistributionMessage extends CiphertextMessage {
5 | constructor(
6 | id = null,
7 | iteration = null,
8 | chainKey = null,
9 | signatureKey = null,
10 | serialized = null
11 | ) {
12 | super();
13 | if (serialized) {
14 | try {
15 | const version = serialized[0];
16 | const message = serialized.slice(1);
17 |
18 | const distributionMessage = protobufs.SenderKeyDistributionMessage.decode(
19 | message
20 | ).toJSON();
21 | this.serialized = serialized;
22 | this.id = distributionMessage.id;
23 | this.iteration = distributionMessage.iteration;
24 | this.chainKey = distributionMessage.chainKey;
25 | this.signatureKey = distributionMessage.signingKey;
26 | } catch (e) {
27 | throw new Error(e);
28 | }
29 | } else {
30 | const version = this.intsToByteHighAndLow(this.CURRENT_VERSION, this.CURRENT_VERSION);
31 | this.id = id;
32 | this.iteration = iteration;
33 | this.chainKey = chainKey;
34 | this.signatureKey = signatureKey;
35 | const message = protobufs.SenderKeyDistributionMessage.encode(
36 | protobufs.SenderKeyDistributionMessage.create({
37 | id,
38 | iteration,
39 | chainKey,
40 | signingKey: this.signatureKey,
41 | })
42 | ).finish();
43 | this.serialized = Buffer.concat([Buffer.from([version]), message]);
44 | }
45 | }
46 |
47 | intsToByteHighAndLow(highValue, lowValue) {
48 | return (((highValue << 4) | lowValue) & 0xff) % 256;
49 | }
50 |
51 | serialize() {
52 | return this.serialized;
53 | }
54 |
55 | getType() {
56 | return this.SENDERKEY_DISTRIBUTION_TYPE;
57 | }
58 |
59 | getIteration() {
60 | return this.iteration;
61 | }
62 |
63 | getChainKey() {
64 | return typeof this.chainKey === 'string' ? Buffer.from(this.chainKey, 'base64') : this.chainKey;
65 | }
66 |
67 | getSignatureKey() {
68 | return typeof this.signatureKey === 'string'
69 | ? Buffer.from(this.signatureKey, 'base64')
70 | : this.signatureKey;
71 | }
72 |
73 | getId() {
74 | return this.id;
75 | }
76 | }
77 |
78 | module.exports = SenderKeyDistributionMessage;
--------------------------------------------------------------------------------
/lib/Types/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | Object.defineProperty(exports, "__esModule", { value: true });
17 | exports.DisconnectReason = void 0;
18 | __exportStar(require("./Auth"), exports);
19 | __exportStar(require("./GroupMetadata"), exports);
20 | __exportStar(require("./Chat"), exports);
21 | __exportStar(require("./Contact"), exports);
22 | __exportStar(require("./State"), exports);
23 | __exportStar(require("./Message"), exports);
24 | __exportStar(require("./Newsletter"), exports);
25 | __exportStar(require("./Socket"), exports);
26 | __exportStar(require("./Events"), exports);
27 | __exportStar(require("./Product"), exports);
28 | __exportStar(require("./Call"), exports);
29 | __exportStar(require("./Signal"), exports);
30 | var DisconnectReason;
31 | (function (DisconnectReason) {
32 | DisconnectReason[DisconnectReason["connectionClosed"] = 428] = "connectionClosed";
33 | DisconnectReason[DisconnectReason["connectionLost"] = 408] = "connectionLost";
34 | DisconnectReason[DisconnectReason["connectionReplaced"] = 440] = "connectionReplaced";
35 | DisconnectReason[DisconnectReason["timedOut"] = 408] = "timedOut";
36 | DisconnectReason[DisconnectReason["loggedOut"] = 401] = "loggedOut";
37 | DisconnectReason[DisconnectReason["badSession"] = 500] = "badSession";
38 | DisconnectReason[DisconnectReason["restartRequired"] = 515] = "restartRequired";
39 | DisconnectReason[DisconnectReason["multideviceMismatch"] = 411] = "multideviceMismatch";
40 | DisconnectReason[DisconnectReason["forbidden"] = 403] = "forbidden";
41 | DisconnectReason[DisconnectReason["unavailableService"] = 503] = "unavailableService";
42 | })(DisconnectReason = exports.DisconnectReason || (exports.DisconnectReason = {}));
43 |
--------------------------------------------------------------------------------
/lib/Store/make-ordered-dictionary.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | function makeOrderedDictionary(idGetter) {
4 | const array = [];
5 | const dict = {};
6 | const get = (id) => dict[id];
7 | const update = (item) => {
8 | const id = idGetter(item);
9 | const idx = array.findIndex(i => idGetter(i) === id);
10 | if (idx >= 0) {
11 | array[idx] = item;
12 | dict[id] = item;
13 | }
14 | return false;
15 | };
16 | const upsert = (item, mode) => {
17 | const id = idGetter(item);
18 | if (get(id)) {
19 | update(item);
20 | }
21 | else {
22 | if (mode === 'append') {
23 | array.push(item);
24 | }
25 | else {
26 | array.splice(0, 0, item);
27 | }
28 | dict[id] = item;
29 | }
30 | };
31 | const remove = (item) => {
32 | const id = idGetter(item);
33 | const idx = array.findIndex(i => idGetter(i) === id);
34 | if (idx >= 0) {
35 | array.splice(idx, 1);
36 | delete dict[id];
37 | return true;
38 | }
39 | return false;
40 | };
41 | return {
42 | array,
43 | get,
44 | upsert,
45 | update,
46 | remove,
47 | updateAssign: (id, update) => {
48 | const item = get(id);
49 | if (item) {
50 | Object.assign(item, update);
51 | delete dict[id];
52 | dict[idGetter(item)] = item;
53 | return true;
54 | }
55 | return false;
56 | },
57 | clear: () => {
58 | array.splice(0, array.length);
59 | Object.keys(dict).forEach(key => {
60 | delete dict[key];
61 | });
62 | },
63 | filter: (contain) => {
64 | let i = 0;
65 | while (i < array.length) {
66 | if (!contain(array[i])) {
67 | delete dict[idGetter(array[i])];
68 | array.splice(i, 1);
69 | }
70 | else {
71 | i += 1;
72 | }
73 | }
74 | },
75 | toJSON: () => array,
76 | fromJSON: (newItems) => {
77 | array.splice(0, array.length, ...newItems);
78 | }
79 | };
80 | }
81 | exports.default = makeOrderedDictionary;
82 |
--------------------------------------------------------------------------------
/lib/Socket/Client/mobile-socket-client.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.MobileSocketClient = void 0;
4 | const net_1 = require("net");
5 | const abstract_socket_client_1 = require("./abstract-socket-client");
6 | class MobileSocketClient extends abstract_socket_client_1.AbstractSocketClient {
7 | constructor() {
8 | super(...arguments);
9 | this.socket = null;
10 | }
11 | get isOpen() {
12 | var _a;
13 | return ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === 'open';
14 | }
15 | get isClosed() {
16 | var _a;
17 | return this.socket === null || ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === 'closed';
18 | }
19 | get isClosing() {
20 | var _a;
21 | return this.socket === null || ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === 'closed';
22 | }
23 | get isConnecting() {
24 | var _a;
25 | return ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === 'opening';
26 | }
27 | async connect() {
28 | var _a;
29 | if (this.socket) {
30 | return;
31 | }
32 | if (this.config.agent) {
33 | throw new Error('There are not support for proxy agent for mobile connection');
34 | }
35 | else {
36 | this.socket = (0, net_1.connect)({
37 | host: this.url.hostname,
38 | port: Number(this.url.port) || 443
39 | });
40 | }
41 | this.socket.setMaxListeners(0);
42 | const events = ['close', 'connect', 'data', 'drain', 'end', 'error', 'lookup', 'ready', 'timeout'];
43 | for (const event of events) {
44 | (_a = this.socket) === null || _a === void 0 ? void 0 : _a.on(event, (...args) => this.emit(event, ...args));
45 | }
46 | this.socket.on('data', (...args) => this.emit('message', ...args));
47 | this.socket.on('ready', (...args) => this.emit('open', ...args));
48 | }
49 | async close() {
50 | if (!this.socket) {
51 | return;
52 | }
53 | return new Promise(resolve => {
54 | this.socket.end(resolve);
55 | this.socket = null;
56 | });
57 | }
58 | send(str, cb) {
59 | if (this.socket === null) {
60 | return false;
61 | }
62 | return this.socket.write(str, undefined, cb);
63 | }
64 | }
65 | exports.MobileSocketClient = MobileSocketClient;
66 |
--------------------------------------------------------------------------------
/lib/Socket/Client/web-socket-client.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | exports.WebSocketClient = void 0;
7 | const ws_1 = __importDefault(require("ws"));
8 | const Defaults_1 = require("../../Defaults");
9 | const abstract_socket_client_1 = require("./abstract-socket-client");
10 | class WebSocketClient extends abstract_socket_client_1.AbstractSocketClient {
11 | constructor() {
12 | super(...arguments);
13 | this.socket = null;
14 | }
15 | get isOpen() {
16 | var _a;
17 | return ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === ws_1.default.OPEN;
18 | }
19 | get isClosed() {
20 | var _a;
21 | return this.socket === null || ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === ws_1.default.CLOSED;
22 | }
23 | get isClosing() {
24 | var _a;
25 | return this.socket === null || ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === ws_1.default.CLOSING;
26 | }
27 | get isConnecting() {
28 | var _a;
29 | return ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === ws_1.default.CONNECTING;
30 | }
31 | async connect() {
32 | var _a, _b;
33 | if (this.socket) {
34 | return;
35 | }
36 | this.socket = new ws_1.default(this.url, {
37 | origin: Defaults_1.DEFAULT_ORIGIN,
38 | headers: (_a = this.config.options) === null || _a === void 0 ? void 0 : _a.headers,
39 | handshakeTimeout: this.config.connectTimeoutMs,
40 | timeout: this.config.connectTimeoutMs,
41 | agent: this.config.agent,
42 | });
43 | this.socket.setMaxListeners(0);
44 | const events = ['close', 'error', 'upgrade', 'message', 'open', 'ping', 'pong', 'unexpected-response'];
45 | for (const event of events) {
46 | (_b = this.socket) === null || _b === void 0 ? void 0 : _b.on(event, (...args) => this.emit(event, ...args));
47 | }
48 | }
49 | async close() {
50 | if (!this.socket) {
51 | return;
52 | }
53 | this.socket.close();
54 | this.socket = null;
55 | }
56 | send(str, cb) {
57 | var _a;
58 | (_a = this.socket) === null || _a === void 0 ? void 0 : _a.send(str, cb);
59 | return Boolean(this.socket);
60 | }
61 | }
62 | exports.WebSocketClient = WebSocketClient;
63 |
--------------------------------------------------------------------------------
/lib/Utils/baileys-event-stream.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | exports.readAndEmitEventStream = exports.captureEventStream = void 0;
7 | const events_1 = __importDefault(require("events"));
8 | const fs_1 = require("fs");
9 | const promises_1 = require("fs/promises");
10 | const readline_1 = require("readline");
11 | const generics_1 = require("./generics");
12 | const make_mutex_1 = require("./make-mutex");
13 | /**
14 | * Captures events from a baileys event emitter & stores them in a file
15 | * @param ev The event emitter to read events from
16 | * @param filename File to save to
17 | */
18 | const captureEventStream = (ev, filename) => {
19 | const oldEmit = ev.emit;
20 | // write mutex so data is appended in order
21 | const writeMutex = (0, make_mutex_1.makeMutex)();
22 | // monkey patch eventemitter to capture all events
23 | ev.emit = function (...args) {
24 | const content = JSON.stringify({ timestamp: Date.now(), event: args[0], data: args[1] }) + '\n';
25 | const result = oldEmit.apply(ev, args);
26 | writeMutex.mutex(async () => {
27 | await (0, promises_1.writeFile)(filename, content, { flag: 'a' });
28 | });
29 | return result;
30 | };
31 | };
32 | exports.captureEventStream = captureEventStream;
33 | /**
34 | * Read event file and emit events from there
35 | * @param filename filename containing event data
36 | * @param delayIntervalMs delay between each event emit
37 | */
38 | const readAndEmitEventStream = (filename, delayIntervalMs = 0) => {
39 | const ev = new events_1.default();
40 | const fireEvents = async () => {
41 | // from: https://stackoverflow.com/questions/6156501/read-a-file-one-line-at-a-time-in-node-js
42 | const fileStream = (0, fs_1.createReadStream)(filename);
43 | const rl = (0, readline_1.createInterface)({
44 | input: fileStream,
45 | crlfDelay: Infinity
46 | });
47 | // Note: we use the crlfDelay option to recognize all instances of CR LF
48 | // ('\r\n') in input.txt as a single line break.
49 | for await (const line of rl) {
50 | if (line) {
51 | const { event, data } = JSON.parse(line);
52 | ev.emit(event, data);
53 | delayIntervalMs && await (0, generics_1.delay)(delayIntervalMs);
54 | }
55 | }
56 | fileStream.close();
57 | };
58 | return {
59 | ev,
60 | task: fireEvents()
61 | };
62 | };
63 | exports.readAndEmitEventStream = readAndEmitEventStream;
64 |
--------------------------------------------------------------------------------
/WASignalGroup/sender_key_message.js:
--------------------------------------------------------------------------------
1 | const CiphertextMessage = require('./ciphertext_message');
2 | const curve = require('libsignal/src/curve');
3 | const protobufs = require('./protobufs');
4 |
5 | class SenderKeyMessage extends CiphertextMessage {
6 | SIGNATURE_LENGTH = 64;
7 |
8 | constructor(
9 | keyId = null,
10 | iteration = null,
11 | ciphertext = null,
12 | signatureKey = null,
13 | serialized = null
14 | ) {
15 | super();
16 | if (serialized) {
17 | const version = serialized[0];
18 | const message = serialized.slice(1, serialized.length - this.SIGNATURE_LENGTH);
19 | const signature = serialized.slice(-1 * this.SIGNATURE_LENGTH);
20 | const senderKeyMessage = protobufs.SenderKeyMessage.decode(message).toJSON();
21 | senderKeyMessage.ciphertext = Buffer.from(senderKeyMessage.ciphertext, 'base64');
22 |
23 | this.serialized = serialized;
24 | this.messageVersion = (version & 0xff) >> 4;
25 |
26 | this.keyId = senderKeyMessage.id;
27 | this.iteration = senderKeyMessage.iteration;
28 | this.ciphertext = senderKeyMessage.ciphertext;
29 | this.signature = signature;
30 | } else {
31 | const version = (((this.CURRENT_VERSION << 4) | this.CURRENT_VERSION) & 0xff) % 256;
32 | ciphertext = Buffer.from(ciphertext); // .toString('base64');
33 | const message = protobufs.SenderKeyMessage.encode(
34 | protobufs.SenderKeyMessage.create({
35 | id: keyId,
36 | iteration,
37 | ciphertext,
38 | })
39 | ).finish();
40 |
41 | const signature = this.getSignature(
42 | signatureKey,
43 | Buffer.concat([Buffer.from([version]), message])
44 | );
45 | this.serialized = Buffer.concat([Buffer.from([version]), message, Buffer.from(signature)]);
46 | this.messageVersion = this.CURRENT_VERSION;
47 | this.keyId = keyId;
48 | this.iteration = iteration;
49 | this.ciphertext = ciphertext;
50 | this.signature = signature;
51 | }
52 | }
53 |
54 | getKeyId() {
55 | return this.keyId;
56 | }
57 |
58 | getIteration() {
59 | return this.iteration;
60 | }
61 |
62 | getCipherText() {
63 | return this.ciphertext;
64 | }
65 |
66 | verifySignature(signatureKey) {
67 | const part1 = this.serialized.slice(0, this.serialized.length - this.SIGNATURE_LENGTH);
68 | const part2 = this.serialized.slice(-1 * this.SIGNATURE_LENGTH);
69 | const res = curve.verifySignature(signatureKey, part1, part2);
70 | if (!res) throw new Error('Invalid signature!');
71 | }
72 |
73 | getSignature(signatureKey, serialized) {
74 | const signature = Buffer.from(
75 | curve.calculateSignature(
76 | signatureKey,
77 | serialized
78 | )
79 | );
80 | return signature;
81 | }
82 |
83 | serialize() {
84 | return this.serialized;
85 | }
86 |
87 | getType() {
88 | return 4;
89 | }
90 | }
91 |
92 | module.exports = SenderKeyMessage;
--------------------------------------------------------------------------------
/lib/WABinary/jid-utils.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.jidNormalizedUser = exports.isJidNewsLetter = exports.isJidStatusBroadcast = exports.isJidGroup = exports.isJidBroadcast = exports.isLidUser = exports.isJidUser = exports.areJidsSameUser = exports.jidDecode = exports.jidEncode = exports.STORIES_JID = exports.PSA_WID = exports.SERVER_JID = exports.OFFICIAL_BIZ_JID = exports.S_WHATSAPP_NET = void 0;
4 | exports.S_WHATSAPP_NET = '@s.whatsapp.net';
5 | exports.OFFICIAL_BIZ_JID = '16505361212@c.us';
6 | exports.SERVER_JID = 'server@c.us';
7 | exports.PSA_WID = '0@c.us';
8 | exports.STORIES_JID = 'status@broadcast';
9 | const jidEncode = (user, server, device, agent) => {
10 | return `${user || ''}${!!agent ? `_${agent}` : ''}${!!device ? `:${device}` : ''}@${server}`;
11 | };
12 | exports.jidEncode = jidEncode;
13 | const jidDecode = (jid) => {
14 | const sepIdx = typeof jid === 'string' ? jid.indexOf('@') : -1;
15 | if (sepIdx < 0) {
16 | return undefined;
17 | }
18 | const server = jid.slice(sepIdx + 1);
19 | const userCombined = jid.slice(0, sepIdx);
20 | const [userAgent, device] = userCombined.split(':');
21 | const user = userAgent.split('_')[0];
22 | return {
23 | server,
24 | user,
25 | domainType: server === 'lid' ? 1 : 0,
26 | device: device ? +device : undefined
27 | };
28 | };
29 | exports.jidDecode = jidDecode;
30 | /** is the jid a user */
31 | const areJidsSameUser = (jid1, jid2) => {
32 | var _a, _b;
33 | return (((_a = (0, exports.jidDecode)(jid1)) === null || _a === void 0 ? void 0 : _a.user) === ((_b = (0, exports.jidDecode)(jid2)) === null || _b === void 0 ? void 0 : _b.user));
34 | };
35 | exports.areJidsSameUser = areJidsSameUser;
36 | /** is the jid a user */
37 | const isJidUser = (jid) => (jid === null || jid === void 0 ? void 0 : jid.endsWith('@s.whatsapp.net'));
38 | exports.isJidUser = isJidUser;
39 | /** is the jid a group */
40 | const isLidUser = (jid) => (jid === null || jid === void 0 ? void 0 : jid.endsWith('@lid'));
41 | exports.isLidUser = isLidUser;
42 | /** is the jid a broadcast */
43 | const isJidBroadcast = (jid) => (jid === null || jid === void 0 ? void 0 : jid.endsWith('@broadcast'));
44 | exports.isJidBroadcast = isJidBroadcast;
45 | /** is the jid a group */
46 | const isJidGroup = (jid) => (jid === null || jid === void 0 ? void 0 : jid.endsWith('@g.us'));
47 | exports.isJidGroup = isJidGroup;
48 | /** is the jid the status broadcast */
49 | const isJidStatusBroadcast = (jid) => jid === 'status@broadcast';
50 | exports.isJidStatusBroadcast = isJidStatusBroadcast;
51 | /** is the jid the newsletter */
52 | const isJidNewsLetter = (jid) => (jid === null || jid === void 0 ? void 0 : jid.endsWith('newsletter'));
53 | exports.isJidNewsLetter = isJidNewsLetter;
54 | const jidNormalizedUser = (jid) => {
55 | const result = (0, exports.jidDecode)(jid);
56 | if (!result) {
57 | return '';
58 | }
59 | const { user, server } = result;
60 | return (0, exports.jidEncode)(user, server === 'c.us' ? 's.whatsapp.net' : server);
61 | };
62 | exports.jidNormalizedUser = jidNormalizedUser;
63 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "baileys",
3 | "version": "6.7.4",
4 | "description": "WhatsApp API",
5 | "keywords": [
6 | "whatsapp",
7 | "js-whatsapp",
8 | "whatsapp-api",
9 | "whatsapp-web",
10 | "whatsapp-chat",
11 | "whatsapp-group",
12 | "automation",
13 | "multi-device"
14 | ],
15 | "homepage": "https://github.com/WhiskeySockets/Baileys",
16 | "repository": {
17 | "url": "git@github.com:WhiskeySockets/Baileys.git"
18 | },
19 | "license": "MIT",
20 | "author": "Adhiraj Singh",
21 | "main": "lib/index.js",
22 | "types": "lib/index.d.ts",
23 | "files": [
24 | "lib/*",
25 | "WAProto/*",
26 | "WASignalGroup/*.js"
27 | ],
28 | "scripts": {
29 | "build:all": "tsc && typedoc",
30 | "build:docs": "typedoc",
31 | "build:tsc": "tsc",
32 | "changelog:last": "conventional-changelog -p angular -r 2",
33 | "changelog:preview": "conventional-changelog -p angular -u",
34 | "changelog:update": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
35 | "example": "node --inspect -r ts-node/register Example/example.ts",
36 | "example:mobile": "node --inspect -r ts-node/register Example/example.ts --mobile",
37 | "gen:protobuf": "sh WAProto/GenerateStatics.sh",
38 | "lint": "eslint src --ext .js,.ts,.jsx,.tsx",
39 | "lint:fix": "eslint src --fix --ext .js,.ts,.jsx,.tsx",
40 | "prepack": "tsc",
41 | "prepare": "tsc",
42 | "release": "release-it",
43 | "test": "jest"
44 | },
45 | "dependencies": {
46 | "@adiwajshing/keyed-db": "^0.2.4",
47 | "@hapi/boom": "^9.1.3",
48 | "audio-decode": "^2.1.3",
49 | "axios": "^1.3.3",
50 | "cache-manager": "4.0.1",
51 | "futoin-hkdf": "^1.5.1",
52 | "libphonenumber-js": "^1.10.20",
53 | "libsignal": "github:adiwajshing/libsignal-node",
54 | "music-metadata": "^7.12.3",
55 | "node-cache": "^5.1.2",
56 | "pino": "^7.0.0",
57 | "protobufjs": "^7.2.4",
58 | "uuid": "^9.0.0",
59 | "ws": "^8.13.0"
60 | },
61 | "devDependencies": {
62 | "@adiwajshing/eslint-config": "github:adiwajshing/eslint-config",
63 | "@types/got": "^9.6.11",
64 | "@types/jest": "^27.5.1",
65 | "@types/node": "^16.0.0",
66 | "@types/sharp": "^0.29.4",
67 | "@types/ws": "^8.0.0",
68 | "conventional-changelog-cli": "^2.2.2",
69 | "eslint": "^8.0.0",
70 | "jest": "^27.0.6",
71 | "jimp": "^0.16.1",
72 | "link-preview-js": "^3.0.0",
73 | "open": "^8.4.2",
74 | "qrcode-terminal": "^0.12.0",
75 | "release-it": "^15.10.3",
76 | "sharp": "^0.30.5",
77 | "ts-jest": "^27.0.3",
78 | "ts-node": "^10.8.1",
79 | "typedoc": "^0.24.7",
80 | "typescript": "^4.6.4",
81 | "json": "^11.0.0"
82 | },
83 | "peerDependencies": {
84 | "jimp": "^0.16.1",
85 | "link-preview-js": "^3.0.0",
86 | "qrcode-terminal": "^0.12.0",
87 | "sharp": "^0.32.2"
88 | },
89 | "peerDependenciesMeta": {
90 | "jimp": {
91 | "optional": true
92 | },
93 | "link-preview-js": {
94 | "optional": true
95 | },
96 | "qrcode-terminal": {
97 | "optional": true
98 | },
99 | "sharp": {
100 | "optional": true
101 | }
102 | },
103 | "packageManager": "yarn@1.22.19"
104 | }
105 |
--------------------------------------------------------------------------------
/lib/Store/make-cache-manager-store.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | const cache_manager_1 = require("cache-manager");
7 | const WAProto_1 = require("../../WAProto");
8 | const Utils_1 = require("../Utils");
9 | const logger_1 = __importDefault(require("../Utils/logger"));
10 | const makeCacheManagerAuthState = async (store, sessionKey) => {
11 | const defaultKey = (file) => `${sessionKey}:${file}`;
12 | const databaseConn = await (0, cache_manager_1.caching)(store);
13 | const writeData = async (file, data) => {
14 | let ttl = undefined;
15 | if (file === 'creds') {
16 | ttl = 63115200; // 2 years
17 | }
18 | await databaseConn.set(defaultKey(file), JSON.stringify(data, Utils_1.BufferJSON.replacer), ttl);
19 | };
20 | const readData = async (file) => {
21 | try {
22 | const data = await databaseConn.get(defaultKey(file));
23 | if (data) {
24 | return JSON.parse(data, Utils_1.BufferJSON.reviver);
25 | }
26 | return null;
27 | }
28 | catch (error) {
29 | logger_1.default.error(error);
30 | return null;
31 | }
32 | };
33 | const removeData = async (file) => {
34 | try {
35 | return await databaseConn.del(defaultKey(file));
36 | }
37 | catch (_a) {
38 | logger_1.default.error(`Error removing ${file} from session ${sessionKey}`);
39 | }
40 | };
41 | const clearState = async () => {
42 | try {
43 | const result = await databaseConn.store.keys(`${sessionKey}*`);
44 | await Promise.all(result.map(async (key) => await databaseConn.del(key)));
45 | }
46 | catch (err) {
47 | }
48 | };
49 | const creds = (await readData('creds')) || (0, Utils_1.initAuthCreds)();
50 | return {
51 | clearState,
52 | saveCreds: () => writeData('creds', creds),
53 | state: {
54 | creds,
55 | keys: {
56 | get: async (type, ids) => {
57 | const data = {};
58 | await Promise.all(ids.map(async (id) => {
59 | let value = await readData(`${type}-${id}`);
60 | if (type === 'app-state-sync-key' && value) {
61 | value = WAProto_1.proto.Message.AppStateSyncKeyData.fromObject(value);
62 | }
63 | data[id] = value;
64 | }));
65 | return data;
66 | },
67 | set: async (data) => {
68 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
69 | const tasks = [];
70 | for (const category in data) {
71 | for (const id in data[category]) {
72 | const value = data[category][id];
73 | const key = `${category}-${id}`;
74 | tasks.push(value ? writeData(key, value) : removeData(key));
75 | }
76 | }
77 | await Promise.all(tasks);
78 | },
79 | }
80 | }
81 | };
82 | };
83 | exports.default = makeCacheManagerAuthState;
84 |
--------------------------------------------------------------------------------
/lib/Types/Newsletter.d.ts:
--------------------------------------------------------------------------------
1 | import { proto } from '../../WAProto';
2 | export type NewsletterReactionMode = 'ALL' | 'BASIC' | 'NONE';
3 | export type NewsletterState = 'ACTIVE' | 'GEOSUSPENDED' | 'SUSPENDED';
4 | export type NewsletterVerification = 'VERIFIED' | 'UNVERIFIED';
5 | export type NewsletterMute = 'ON' | 'OFF' | 'UNDEFINED';
6 | export type NewsletterViewRole = 'ADMIN' | 'GUEST' | 'OWNER' | 'SUBSCRIBER';
7 | export type NewsletterViewerMetadata = {
8 | mute: NewsletterMute;
9 | view_role: NewsletterViewRole;
10 | };
11 | export type NewsletterMetadata = {
12 | /**jid of newsletter */
13 | id: string;
14 | /**state of newsletter */
15 | state: NewsletterState;
16 | /**creation timestamp of newsletter */
17 | creation_time: number;
18 | /**name of newsletter */
19 | name: string;
20 | /**timestamp of last name modification of newsletter */
21 | nameTime: number;
22 | /**description of newsletter */
23 | description: string;
24 | /**timestamp of last description modification of newsletter */
25 | descriptionTime: number;
26 | /**invite code of newsletter */
27 | invite: string;
28 | /**i dont know */
29 | handle: null;
30 | /**direct path of picture */
31 | picture: string | null;
32 | /**direct path of picture preview (lower quality) */
33 | preview: string | null;
34 | /**reaction mode of newsletter */
35 | reaction_codes?: NewsletterReactionMode;
36 | /**subscribers count of newsletter */
37 | subscribers: number;
38 | /**verification state of newsletter */
39 | verification: NewsletterVerification;
40 | /**viewer metadata */
41 | viewer_metadata: NewsletterViewerMetadata;
42 | };
43 | export type SubscriberAction = 'promote' | 'demote';
44 | export type ReactionModeUpdate = {
45 | reaction_codes: {
46 | blocked_codes: null;
47 | enabled_ts_sec: null;
48 | value: NewsletterReactionMode;
49 | };
50 | };
51 | /**only exists reaction mode update */
52 | export type NewsletterSettingsUpdate = ReactionModeUpdate;
53 | export type NewsletterReaction = {
54 | count: number;
55 | code: string;
56 | };
57 | export type NewsletterFetchedUpdate = {
58 | /**id of message in newsletter, starts from 100 */
59 | server_id: string;
60 | /**count of views in this message */
61 | views?: number;
62 | /**reactions in this message */
63 | reactions: NewsletterReaction[];
64 | /**the message, if you requested only updates, you will not receive message */
65 | message?: proto.IWebMessageInfo;
66 | };
67 | export declare enum MexOperations {
68 | PROMOTE = "NotificationNewsletterAdminPromote",
69 | DEMOTE = "NotificationNewsletterAdminDemote",
70 | UPDATE = "NotificationNewsletterUpdate"
71 | }
72 | export declare enum XWAPaths {
73 | PROMOTE = "xwa2_notify_newsletter_admin_promote",
74 | DEMOTE = "xwa2_notify_newsletter_admin_demote",
75 | ADMIN_COUNT = "xwa2_newsletter_admin",
76 | CREATE = "xwa2_newsletter_create",
77 | NEWSLETTER = "xwa2_newsletter",
78 | METADATA_UPDATE = "xwa2_notify_newsletter_on_metadata_update"
79 | }
80 | export declare enum QueryIds {
81 | JOB_MUTATION = "7150902998257522",
82 | METADATA = "6620195908089573",
83 | UNFOLLOW = "7238632346214362",
84 | FOLLOW = "7871414976211147",
85 | UNMUTE = "7337137176362961",
86 | MUTE = "25151904754424642",
87 | CREATE = "6996806640408138",
88 | ADMIN_COUNT = "7130823597031706",
89 | CHANGE_OWNER = "7341777602580933",
90 | DELETE = "8316537688363079",
91 | DEMOTE = "6551828931592903"
92 | }
93 |
--------------------------------------------------------------------------------
/lib/Utils/use-multi-file-auth-state.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.useMultiFileAuthState = void 0;
4 | const promises_1 = require("fs/promises");
5 | const path_1 = require("path");
6 | const WAProto_1 = require("../../WAProto");
7 | const auth_utils_1 = require("./auth-utils");
8 | const generics_1 = require("./generics");
9 | /**
10 | * stores the full authentication state in a single folder.
11 | * Far more efficient than singlefileauthstate
12 | *
13 | * Again, I wouldn't endorse this for any production level use other than perhaps a bot.
14 | * Would recommend writing an auth state for use with a proper SQL or No-SQL DB
15 | * */
16 | const useMultiFileAuthState = async (folder) => {
17 | const writeData = (data, file) => {
18 | return (0, promises_1.writeFile)((0, path_1.join)(folder, fixFileName(file)), JSON.stringify(data, generics_1.BufferJSON.replacer));
19 | };
20 | const readData = async (file) => {
21 | try {
22 | const data = await (0, promises_1.readFile)((0, path_1.join)(folder, fixFileName(file)), { encoding: 'utf-8' });
23 | return JSON.parse(data, generics_1.BufferJSON.reviver);
24 | }
25 | catch (error) {
26 | return null;
27 | }
28 | };
29 | const removeData = async (file) => {
30 | try {
31 | await (0, promises_1.unlink)((0, path_1.join)(folder, fixFileName(file)));
32 | }
33 | catch (_a) {
34 | }
35 | };
36 | const folderInfo = await (0, promises_1.stat)(folder).catch(() => { });
37 | if (folderInfo) {
38 | if (!folderInfo.isDirectory()) {
39 | throw new Error(`found something that is not a directory at ${folder}, either delete it or specify a different location`);
40 | }
41 | }
42 | else {
43 | await (0, promises_1.mkdir)(folder, { recursive: true });
44 | }
45 | const fixFileName = (file) => { var _a; return (_a = file === null || file === void 0 ? void 0 : file.replace(/\//g, '__')) === null || _a === void 0 ? void 0 : _a.replace(/:/g, '-'); };
46 | const creds = await readData('creds.json') || (0, auth_utils_1.initAuthCreds)();
47 | return {
48 | state: {
49 | creds,
50 | keys: {
51 | get: async (type, ids) => {
52 | const data = {};
53 | await Promise.all(ids.map(async (id) => {
54 | let value = await readData(`${type}-${id}.json`);
55 | if (type === 'app-state-sync-key' && value) {
56 | value = WAProto_1.proto.Message.AppStateSyncKeyData.fromObject(value);
57 | }
58 | data[id] = value;
59 | }));
60 | return data;
61 | },
62 | set: async (data) => {
63 | const tasks = [];
64 | for (const category in data) {
65 | for (const id in data[category]) {
66 | const value = data[category][id];
67 | const file = `${category}-${id}.json`;
68 | tasks.push(value ? writeData(value, file) : removeData(file));
69 | }
70 | }
71 | await Promise.all(tasks);
72 | }
73 | }
74 | },
75 | saveCreds: () => {
76 | return writeData(creds, 'creds.json');
77 | }
78 | };
79 | };
80 | exports.useMultiFileAuthState = useMultiFileAuthState;
81 |
--------------------------------------------------------------------------------
/lib/Types/Auth.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import type { proto } from '../../WAProto';
3 | import { RegistrationOptions } from '../Socket/registration';
4 | import type { Contact } from './Contact';
5 | import type { MinimalMessage } from './Message';
6 | export type KeyPair = {
7 | public: Uint8Array;
8 | private: Uint8Array;
9 | };
10 | export type SignedKeyPair = {
11 | keyPair: KeyPair;
12 | signature: Uint8Array;
13 | keyId: number;
14 | timestampS?: number;
15 | };
16 | export type ProtocolAddress = {
17 | name: string;
18 | deviceId: number;
19 | };
20 | export type SignalIdentity = {
21 | identifier: ProtocolAddress;
22 | identifierKey: Uint8Array;
23 | };
24 | export type LTHashState = {
25 | version: number;
26 | hash: Buffer;
27 | indexValueMap: {
28 | [indexMacBase64: string]: {
29 | valueMac: Uint8Array | Buffer;
30 | };
31 | };
32 | };
33 | export type SignalCreds = {
34 | readonly signedIdentityKey: KeyPair;
35 | readonly signedPreKey: SignedKeyPair;
36 | readonly registrationId: number;
37 | };
38 | export type AccountSettings = {
39 | /** unarchive chats when a new message is received */
40 | unarchiveChats: boolean;
41 | /** the default mode to start new conversations with */
42 | defaultDisappearingMode?: Pick;
43 | };
44 | export type AuthenticationCreds = SignalCreds & {
45 | readonly noiseKey: KeyPair;
46 | readonly pairingEphemeralKeyPair: KeyPair;
47 | advSecretKey: string;
48 | me?: Contact;
49 | account?: proto.IADVSignedDeviceIdentity;
50 | signalIdentities?: SignalIdentity[];
51 | myAppStateKeyId?: string;
52 | firstUnuploadedPreKeyId: number;
53 | nextPreKeyId: number;
54 | lastAccountSyncTimestamp?: number;
55 | platform?: string;
56 | processedHistoryMessages: MinimalMessage[];
57 | /** number of times history & app state has been synced */
58 | accountSyncCounter: number;
59 | accountSettings: AccountSettings;
60 | deviceId: string;
61 | phoneId: string;
62 | identityId: Buffer;
63 | registered: boolean;
64 | backupToken: Buffer;
65 | registration: RegistrationOptions;
66 | pairingCode: string | undefined;
67 | lastPropHash: string | undefined;
68 | routingInfo: Buffer | undefined;
69 | };
70 | export type SignalDataTypeMap = {
71 | 'pre-key': KeyPair;
72 | 'session': Uint8Array;
73 | 'sender-key': Uint8Array;
74 | 'sender-key-memory': {
75 | [jid: string]: boolean;
76 | };
77 | 'app-state-sync-key': proto.Message.IAppStateSyncKeyData;
78 | 'app-state-sync-version': LTHashState;
79 | };
80 | export type SignalDataSet = {
81 | [T in keyof SignalDataTypeMap]?: {
82 | [id: string]: SignalDataTypeMap[T] | null;
83 | };
84 | };
85 | type Awaitable = T | Promise;
86 | export type SignalKeyStore = {
87 | get(type: T, ids: string[]): Awaitable<{
88 | [id: string]: SignalDataTypeMap[T];
89 | }>;
90 | set(data: SignalDataSet): Awaitable;
91 | /** clear all the data in the store */
92 | clear?(): Awaitable;
93 | };
94 | export type SignalKeyStoreWithTransaction = SignalKeyStore & {
95 | isInTransaction: () => boolean;
96 | transaction(exec: () => Promise): Promise;
97 | };
98 | export type TransactionCapabilityOptions = {
99 | maxCommitRetries: number;
100 | delayBetweenTriesMs: number;
101 | };
102 | export type SignalAuthState = {
103 | creds: SignalCreds;
104 | keys: SignalKeyStore | SignalKeyStoreWithTransaction;
105 | };
106 | export type AuthenticationState = {
107 | creds: AuthenticationCreds;
108 | keys: SignalKeyStore;
109 | };
110 | export {};
111 |
--------------------------------------------------------------------------------
/lib/Utils/chat-utils.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { AxiosRequestConfig } from 'axios';
3 | import type { Logger } from 'pino';
4 | import { proto } from '../../WAProto';
5 | import { BaileysEventEmitter, ChatModification, ChatMutation, Contact, InitialAppStateSyncOptions, LTHashState, WAPatchCreate, WAPatchName } from '../Types';
6 | import { BinaryNode } from '../WABinary';
7 | type FetchAppStateSyncKey = (keyId: string) => Promise;
8 | export type ChatMutationMap = {
9 | [index: string]: ChatMutation;
10 | };
11 | export declare const newLTHashState: () => LTHashState;
12 | export declare const encodeSyncdPatch: ({ type, index, syncAction, apiVersion, operation }: WAPatchCreate, myAppStateKeyId: string, state: LTHashState, getAppStateSyncKey: FetchAppStateSyncKey) => Promise<{
13 | patch: proto.ISyncdPatch;
14 | state: LTHashState;
15 | }>;
16 | export declare const decodeSyncdMutations: (msgMutations: (proto.ISyncdMutation | proto.ISyncdRecord)[], initialState: LTHashState, getAppStateSyncKey: FetchAppStateSyncKey, onMutation: (mutation: ChatMutation) => void, validateMacs: boolean) => Promise<{
17 | hash: Buffer;
18 | indexValueMap: {
19 | [indexMacBase64: string]: {
20 | valueMac: Uint8Array | Buffer;
21 | };
22 | };
23 | }>;
24 | export declare const decodeSyncdPatch: (msg: proto.ISyncdPatch, name: WAPatchName, initialState: LTHashState, getAppStateSyncKey: FetchAppStateSyncKey, onMutation: (mutation: ChatMutation) => void, validateMacs: boolean) => Promise<{
25 | hash: Buffer;
26 | indexValueMap: {
27 | [indexMacBase64: string]: {
28 | valueMac: Uint8Array | Buffer;
29 | };
30 | };
31 | }>;
32 | export declare const extractSyncdPatches: (result: BinaryNode, options: AxiosRequestConfig) => Promise<{
33 | critical_block: {
34 | patches: proto.ISyncdPatch[];
35 | hasMorePatches: boolean;
36 | snapshot?: proto.ISyncdSnapshot | undefined;
37 | };
38 | critical_unblock_low: {
39 | patches: proto.ISyncdPatch[];
40 | hasMorePatches: boolean;
41 | snapshot?: proto.ISyncdSnapshot | undefined;
42 | };
43 | regular_high: {
44 | patches: proto.ISyncdPatch[];
45 | hasMorePatches: boolean;
46 | snapshot?: proto.ISyncdSnapshot | undefined;
47 | };
48 | regular_low: {
49 | patches: proto.ISyncdPatch[];
50 | hasMorePatches: boolean;
51 | snapshot?: proto.ISyncdSnapshot | undefined;
52 | };
53 | regular: {
54 | patches: proto.ISyncdPatch[];
55 | hasMorePatches: boolean;
56 | snapshot?: proto.ISyncdSnapshot | undefined;
57 | };
58 | }>;
59 | export declare const downloadExternalBlob: (blob: proto.IExternalBlobReference, options: AxiosRequestConfig) => Promise;
60 | export declare const downloadExternalPatch: (blob: proto.IExternalBlobReference, options: AxiosRequestConfig) => Promise;
61 | export declare const decodeSyncdSnapshot: (name: WAPatchName, snapshot: proto.ISyncdSnapshot, getAppStateSyncKey: FetchAppStateSyncKey, minimumVersionNumber: number | undefined, validateMacs?: boolean) => Promise<{
62 | state: LTHashState;
63 | mutationMap: ChatMutationMap;
64 | }>;
65 | export declare const decodePatches: (name: WAPatchName, syncds: proto.ISyncdPatch[], initial: LTHashState, getAppStateSyncKey: FetchAppStateSyncKey, options: AxiosRequestConfig, minimumVersionNumber?: number, logger?: Logger, validateMacs?: boolean) => Promise<{
66 | state: LTHashState;
67 | mutationMap: ChatMutationMap;
68 | }>;
69 | export declare const chatModificationToAppPatch: (mod: ChatModification, jid: string) => WAPatchCreate;
70 | export declare const processSyncAction: (syncAction: ChatMutation, ev: BaileysEventEmitter, me: Contact, initialSyncOpts?: InitialAppStateSyncOptions, logger?: Logger) => void;
71 | export {};
72 |
--------------------------------------------------------------------------------
/lib/Types/Chat.d.ts:
--------------------------------------------------------------------------------
1 | import type { proto } from '../../WAProto';
2 | import type { AccountSettings } from './Auth';
3 | import type { BufferedEventData } from './Events';
4 | import type { ChatLabelAssociationActionBody } from './LabelAssociation';
5 | import type { MessageLabelAssociationActionBody } from './LabelAssociation';
6 | import type { MinimalMessage } from './Message';
7 | /** privacy settings in WhatsApp Web */
8 | export type WAPrivacyValue = 'all' | 'contacts' | 'contact_blacklist' | 'none';
9 | export type WAPrivacyOnlineValue = 'all' | 'match_last_seen';
10 | export type WAReadReceiptsValue = 'all' | 'none';
11 | /** set of statuses visible to other people; see updatePresence() in WhatsAppWeb.Send */
12 | export type WAPresence = 'unavailable' | 'available' | 'composing' | 'recording' | 'paused';
13 | export declare const ALL_WA_PATCH_NAMES: readonly ["critical_block", "critical_unblock_low", "regular_high", "regular_low", "regular"];
14 | export type WAPatchName = typeof ALL_WA_PATCH_NAMES[number];
15 | export interface PresenceData {
16 | lastKnownPresence: WAPresence;
17 | lastSeen?: number;
18 | }
19 | export type ChatMutation = {
20 | syncAction: proto.ISyncActionData;
21 | index: string[];
22 | };
23 | export type WAPatchCreate = {
24 | syncAction: proto.ISyncActionValue;
25 | index: string[];
26 | type: WAPatchName;
27 | apiVersion: number;
28 | operation: proto.SyncdMutation.SyncdOperation;
29 | };
30 | export type Chat = proto.IConversation & {
31 | /** unix timestamp of when the last message was received in the chat */
32 | lastMessageRecvTimestamp?: number;
33 | };
34 | export type ChatUpdate = Partial boolean | undefined;
45 | }>;
46 | /**
47 | * the last messages in a chat, sorted reverse-chronologically. That is, the latest message should be first in the chat
48 | * for MD modifications, the last message in the array (i.e. the earlist message) must be the last message recv in the chat
49 | * */
50 | export type LastMessageList = MinimalMessage[] | proto.SyncActionValue.ISyncActionMessageRange;
51 | export type ChatModification = {
52 | archive: boolean;
53 | lastMessages: LastMessageList;
54 | } | {
55 | pushNameSetting: string;
56 | } | {
57 | pin: boolean;
58 | } | {
59 | /** mute for duration, or provide timestamp of mute to remove*/
60 | mute: number | null;
61 | } | {
62 | clear: 'all' | {
63 | messages: {
64 | id: string;
65 | fromMe?: boolean;
66 | timestamp: number;
67 | }[];
68 | };
69 | } | {
70 | star: {
71 | messages: {
72 | id: string;
73 | fromMe?: boolean;
74 | }[];
75 | star: boolean;
76 | };
77 | } | {
78 | markRead: boolean;
79 | lastMessages: LastMessageList;
80 | } | {
81 | delete: true;
82 | lastMessages: LastMessageList;
83 | } | {
84 | addChatLabel: ChatLabelAssociationActionBody;
85 | } | {
86 | removeChatLabel: ChatLabelAssociationActionBody;
87 | } | {
88 | addMessageLabel: MessageLabelAssociationActionBody;
89 | } | {
90 | removeMessageLabel: MessageLabelAssociationActionBody;
91 | };
92 | export type InitialReceivedChatsState = {
93 | [jid: string]: {
94 | /** the last message received from the other party */
95 | lastMsgRecvTimestamp?: number;
96 | /** the absolute last message in the chat */
97 | lastMsgTimestamp: number;
98 | };
99 | };
100 | export type InitialAppStateSyncOptions = {
101 | accountSettings: AccountSettings;
102 | };
103 |
--------------------------------------------------------------------------------
/lib/Utils/link-preview.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.getUrlInfo = void 0;
4 | const messages_1 = require("./messages");
5 | const messages_media_1 = require("./messages-media");
6 | const THUMBNAIL_WIDTH_PX = 192;
7 | /** Fetches an image and generates a thumbnail for it */
8 | const getCompressedJpegThumbnail = async (url, { thumbnailWidth, fetchOpts }) => {
9 | const stream = await (0, messages_media_1.getHttpStream)(url, fetchOpts);
10 | const result = await (0, messages_media_1.extractImageThumb)(stream, thumbnailWidth);
11 | return result;
12 | };
13 | /**
14 | * Given a piece of text, checks for any URL present, generates link preview for the same and returns it
15 | * Return undefined if the fetch failed or no URL was found
16 | * @param text first matched URL in text
17 | * @returns the URL info required to generate link preview
18 | */
19 | const getUrlInfo = async (text, opts = {
20 | thumbnailWidth: THUMBNAIL_WIDTH_PX,
21 | fetchOpts: { timeout: 3000 }
22 | }) => {
23 | var _a;
24 | try {
25 | // retries
26 | const retries = 0;
27 | const maxRetry = 5;
28 | const { getLinkPreview } = await import('link-preview-js');
29 | let previewLink = text;
30 | if (!text.startsWith('https://') && !text.startsWith('http://')) {
31 | previewLink = 'https://' + previewLink;
32 | }
33 | const info = await getLinkPreview(previewLink, {
34 | ...opts.fetchOpts,
35 | followRedirects: 'follow',
36 | handleRedirects: (baseURL, forwardedURL) => {
37 | const urlObj = new URL(baseURL);
38 | const forwardedURLObj = new URL(forwardedURL);
39 | if (retries >= maxRetry) {
40 | return false;
41 | }
42 | if (forwardedURLObj.hostname === urlObj.hostname
43 | || forwardedURLObj.hostname === 'www.' + urlObj.hostname
44 | || 'www.' + forwardedURLObj.hostname === urlObj.hostname) {
45 | retries + 1;
46 | return true;
47 | }
48 | else {
49 | return false;
50 | }
51 | },
52 | headers: opts.fetchOpts
53 | });
54 | if (info && 'title' in info && info.title) {
55 | const [image] = info.images;
56 | const urlInfo = {
57 | 'canonical-url': info.url,
58 | 'matched-text': text,
59 | title: info.title,
60 | description: info.description,
61 | originalThumbnailUrl: image
62 | };
63 | if (opts.uploadImage) {
64 | const { imageMessage } = await (0, messages_1.prepareWAMessageMedia)({ image: { url: image } }, {
65 | upload: opts.uploadImage,
66 | mediaTypeOverride: 'thumbnail-link',
67 | options: opts.fetchOpts
68 | });
69 | urlInfo.jpegThumbnail = (imageMessage === null || imageMessage === void 0 ? void 0 : imageMessage.jpegThumbnail)
70 | ? Buffer.from(imageMessage.jpegThumbnail)
71 | : undefined;
72 | urlInfo.highQualityThumbnail = imageMessage || undefined;
73 | }
74 | else {
75 | try {
76 | urlInfo.jpegThumbnail = image
77 | ? (await getCompressedJpegThumbnail(image, opts)).buffer
78 | : undefined;
79 | }
80 | catch (error) {
81 | (_a = opts.logger) === null || _a === void 0 ? void 0 : _a.debug({ err: error.stack, url: previewLink }, 'error in generating thumbnail');
82 | }
83 | }
84 | return urlInfo;
85 | }
86 | }
87 | catch (error) {
88 | if (!error.message.includes('receive a valid')) {
89 | throw error;
90 | }
91 | }
92 | };
93 | exports.getUrlInfo = getUrlInfo;
94 |
--------------------------------------------------------------------------------
/WASignalGroup/group_cipher.js:
--------------------------------------------------------------------------------
1 | const queue_job = require('./queue_job');
2 | const SenderKeyMessage = require('./sender_key_message');
3 | const crypto = require('libsignal/src/crypto');
4 |
5 | class GroupCipher {
6 | constructor(senderKeyStore, senderKeyName) {
7 | this.senderKeyStore = senderKeyStore;
8 | this.senderKeyName = senderKeyName;
9 | }
10 |
11 | queueJob(awaitable) {
12 | return queue_job(this.senderKeyName.toString(), awaitable)
13 | }
14 |
15 | async encrypt(paddedPlaintext) {
16 | return await this.queueJob(async () => {
17 | const record = await this.senderKeyStore.loadSenderKey(this.senderKeyName);
18 | if (!record) {
19 | throw new Error("No SenderKeyRecord found for encryption")
20 | }
21 | const senderKeyState = record.getSenderKeyState();
22 | if (!senderKeyState) {
23 | throw new Error("No session to encrypt message");
24 | }
25 | const iteration = senderKeyState.getSenderChainKey().getIteration()
26 | const senderKey = this.getSenderKey(senderKeyState, iteration === 0 ? 0 : iteration + 1)
27 |
28 | const ciphertext = await this.getCipherText(
29 | senderKey.getIv(),
30 | senderKey.getCipherKey(),
31 | paddedPlaintext
32 | );
33 |
34 | const senderKeyMessage = new SenderKeyMessage(
35 | senderKeyState.getKeyId(),
36 | senderKey.getIteration(),
37 | ciphertext,
38 | senderKeyState.getSigningKeyPrivate()
39 | );
40 | await this.senderKeyStore.storeSenderKey(this.senderKeyName, record);
41 | return senderKeyMessage.serialize()
42 | })
43 | }
44 |
45 | async decrypt(senderKeyMessageBytes) {
46 | return await this.queueJob(async () => {
47 | const record = await this.senderKeyStore.loadSenderKey(this.senderKeyName);
48 | if (!record) {
49 | throw new Error("No SenderKeyRecord found for decryption")
50 | }
51 | const senderKeyMessage = new SenderKeyMessage(null, null, null, null, senderKeyMessageBytes);
52 | const senderKeyState = record.getSenderKeyState(senderKeyMessage.getKeyId());
53 | if (!senderKeyState) {
54 | throw new Error("No session found to decrypt message")
55 | }
56 |
57 | senderKeyMessage.verifySignature(senderKeyState.getSigningKeyPublic());
58 | const senderKey = this.getSenderKey(senderKeyState, senderKeyMessage.getIteration());
59 | // senderKeyState.senderKeyStateStructure.senderSigningKey.private =
60 |
61 | const plaintext = await this.getPlainText(
62 | senderKey.getIv(),
63 | senderKey.getCipherKey(),
64 | senderKeyMessage.getCipherText()
65 | );
66 |
67 | await this.senderKeyStore.storeSenderKey(this.senderKeyName, record);
68 |
69 | return plaintext;
70 | })
71 | }
72 |
73 | getSenderKey(senderKeyState, iteration) {
74 | let senderChainKey = senderKeyState.getSenderChainKey();
75 | if (senderChainKey.getIteration() > iteration) {
76 | if (senderKeyState.hasSenderMessageKey(iteration)) {
77 | return senderKeyState.removeSenderMessageKey(iteration);
78 | }
79 | throw new Error(
80 | `Received message with old counter: ${senderChainKey.getIteration()}, ${iteration}`
81 | );
82 | }
83 |
84 | if (iteration - senderChainKey.getIteration() > 2000) {
85 | throw new Error('Over 2000 messages into the future!');
86 | }
87 |
88 | while (senderChainKey.getIteration() < iteration) {
89 | senderKeyState.addSenderMessageKey(senderChainKey.getSenderMessageKey());
90 | senderChainKey = senderChainKey.getNext();
91 | }
92 |
93 | senderKeyState.setSenderChainKey(senderChainKey.getNext());
94 | return senderChainKey.getSenderMessageKey();
95 | }
96 |
97 | getPlainText(iv, key, ciphertext) {
98 | try {
99 | const plaintext = crypto.decrypt(key, ciphertext, iv);
100 | return plaintext;
101 | } catch (e) {
102 | //console.log(e.stack);
103 | throw new Error('InvalidMessageException');
104 | }
105 | }
106 |
107 | getCipherText(iv, key, plaintext) {
108 | try {
109 | iv = typeof iv === 'string' ? Buffer.from(iv, 'base64') : iv;
110 | key = typeof key === 'string' ? Buffer.from(key, 'base64') : key;
111 | const crypted = crypto.encrypt(key, Buffer.from(plaintext), iv);
112 | return crypted;
113 | } catch (e) {
114 | //console.log(e.stack);
115 | throw new Error('InvalidMessageException');
116 | }
117 | }
118 | }
119 |
120 | module.exports = GroupCipher;
--------------------------------------------------------------------------------
/lib/Utils/history.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.getHistoryMsg = exports.downloadAndProcessHistorySyncNotification = exports.processHistoryMessage = exports.downloadHistory = void 0;
4 | const util_1 = require("util");
5 | const zlib_1 = require("zlib");
6 | const WAProto_1 = require("../../WAProto");
7 | const Types_1 = require("../Types");
8 | const WABinary_1 = require("../WABinary");
9 | const generics_1 = require("./generics");
10 | const messages_1 = require("./messages");
11 | const messages_media_1 = require("./messages-media");
12 | const inflatePromise = (0, util_1.promisify)(zlib_1.inflate);
13 | const downloadHistory = async (msg, options) => {
14 | const stream = await (0, messages_media_1.downloadContentFromMessage)(msg, 'md-msg-hist', { options });
15 | const bufferArray = [];
16 | for await (const chunk of stream) {
17 | bufferArray.push(chunk);
18 | }
19 | let buffer = Buffer.concat(bufferArray);
20 | // decompress buffer
21 | buffer = await inflatePromise(buffer);
22 | const syncData = WAProto_1.proto.HistorySync.decode(buffer);
23 | return syncData;
24 | };
25 | exports.downloadHistory = downloadHistory;
26 | const processHistoryMessage = (item) => {
27 | var _a, _b, _c;
28 | const messages = [];
29 | const contacts = [];
30 | const chats = [];
31 | switch (item.syncType) {
32 | case WAProto_1.proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP:
33 | case WAProto_1.proto.HistorySync.HistorySyncType.RECENT:
34 | case WAProto_1.proto.HistorySync.HistorySyncType.FULL:
35 | for (const chat of item.conversations) {
36 | contacts.push({ id: chat.id, name: chat.name || undefined });
37 | const msgs = chat.messages || [];
38 | delete chat.messages;
39 | delete chat.archived;
40 | delete chat.muteEndTime;
41 | delete chat.pinned;
42 | for (const item of msgs) {
43 | const message = item.message;
44 | messages.push(message);
45 | if (!((_a = chat.messages) === null || _a === void 0 ? void 0 : _a.length)) {
46 | // keep only the most recent message in the chat array
47 | chat.messages = [{ message }];
48 | }
49 | if (!message.key.fromMe && !chat.lastMessageRecvTimestamp) {
50 | chat.lastMessageRecvTimestamp = (0, generics_1.toNumber)(message.messageTimestamp);
51 | }
52 | if ((message.messageStubType === Types_1.WAMessageStubType.BIZ_PRIVACY_MODE_TO_BSP
53 | || message.messageStubType === Types_1.WAMessageStubType.BIZ_PRIVACY_MODE_TO_FB)
54 | && ((_b = message.messageStubParameters) === null || _b === void 0 ? void 0 : _b[0])) {
55 | contacts.push({
56 | id: message.key.participant || message.key.remoteJid,
57 | verifiedName: (_c = message.messageStubParameters) === null || _c === void 0 ? void 0 : _c[0],
58 | });
59 | }
60 | }
61 | if ((0, WABinary_1.isJidUser)(chat.id) && chat.readOnly && chat.archived) {
62 | delete chat.readOnly;
63 | }
64 | chats.push({ ...chat });
65 | }
66 | break;
67 | case WAProto_1.proto.HistorySync.HistorySyncType.PUSH_NAME:
68 | for (const c of item.pushnames) {
69 | contacts.push({ id: c.id, notify: c.pushname });
70 | }
71 | break;
72 | }
73 | return {
74 | chats,
75 | contacts,
76 | messages,
77 | };
78 | };
79 | exports.processHistoryMessage = processHistoryMessage;
80 | const downloadAndProcessHistorySyncNotification = async (msg, options) => {
81 | const historyMsg = await (0, exports.downloadHistory)(msg, options);
82 | return (0, exports.processHistoryMessage)(historyMsg);
83 | };
84 | exports.downloadAndProcessHistorySyncNotification = downloadAndProcessHistorySyncNotification;
85 | const getHistoryMsg = (message) => {
86 | var _a;
87 | const normalizedContent = !!message ? (0, messages_1.normalizeMessageContent)(message) : undefined;
88 | const anyHistoryMsg = (_a = normalizedContent === null || normalizedContent === void 0 ? void 0 : normalizedContent.protocolMessage) === null || _a === void 0 ? void 0 : _a.historySyncNotification;
89 | return anyHistoryMsg;
90 | };
91 | exports.getHistoryMsg = getHistoryMsg;
92 |
--------------------------------------------------------------------------------
/lib/Defaults/phonenumber-mcc.json:
--------------------------------------------------------------------------------
1 | {
2 | "93": 412,
3 | "355": 276,
4 | "213": 603,
5 | "1-684": 544,
6 | "376": 213,
7 | "244": 631,
8 | "1-264": 365,
9 | "1-268": 344,
10 | "54": 722,
11 | "374": 283,
12 | "297": 363,
13 | "61": 505,
14 | "43": 232,
15 | "994": 400,
16 | "1-242": 364,
17 | "973": 426,
18 | "880": 470,
19 | "1-246": 342,
20 | "375": 257,
21 | "32": 206,
22 | "501": 702,
23 | "229": 616,
24 | "1-441": 350,
25 | "975": 402,
26 | "591": 736,
27 | "387": 218,
28 | "267": 652,
29 | "55": 724,
30 | "1-284": 348,
31 | "673": 528,
32 | "359": 284,
33 | "226": 613,
34 | "257": 642,
35 | "855": 456,
36 | "237": 624,
37 | "238": 625,
38 | "1-345": 346,
39 | "236": 623,
40 | "235": 622,
41 | "56": 730,
42 | "86": 454,
43 | "57": 732,
44 | "269": 654,
45 | "682": 548,
46 | "506": 712,
47 | "385": 219,
48 | "53": 368,
49 | "357": 280,
50 | "420": 230,
51 | "243": 630,
52 | "45": 238,
53 | "253": 638,
54 | "1-767": 366,
55 | "1-809": 370,
56 | "1-849": 370,
57 | "1-829": 370,
58 | "593": 740,
59 | "20": 602,
60 | "503": 706,
61 | "240": 627,
62 | "291": 657,
63 | "372": 248,
64 | "251": 636,
65 | "500": 750,
66 | "298": 288,
67 | "679": 542,
68 | "358": 244,
69 | "33": 208,
70 | "689": 547,
71 | "241": 628,
72 | "220": 607,
73 | "995": 282,
74 | "49": 262,
75 | "233": 620,
76 | "350": 266,
77 | "30": 202,
78 | "299": 290,
79 | "1-473": 352,
80 | "1-671": 535,
81 | "502": 704,
82 | "224": 537,
83 | "592": 738,
84 | "509": 372,
85 | "504": 708,
86 | "852": 454,
87 | "36": 216,
88 | "354": 274,
89 | "91": 404,
90 | "62": 510,
91 | "98": 432,
92 | "964": 418,
93 | "353": 234,
94 | "972": 425,
95 | "39": 222,
96 | "225": 612,
97 | "1-876": 338,
98 | "81": 440,
99 | "962": 416,
100 | "254": 639,
101 | "686": 545,
102 | "383": 221,
103 | "965": 419,
104 | "371": 247,
105 | "961": 415,
106 | "266": 651,
107 | "231": 618,
108 | "218": 606,
109 | "423": 295,
110 | "370": 246,
111 | "352": 270,
112 | "389": 294,
113 | "261": 646,
114 | "265": 650,
115 | "60": 502,
116 | "960": 472,
117 | "223": 610,
118 | "356": 278,
119 | "692": 551,
120 | "222": 609,
121 | "230": 617,
122 | "52": 334,
123 | "691": 550,
124 | "373": 259,
125 | "377": 212,
126 | "976": 428,
127 | "382": 297,
128 | "1-664": 354,
129 | "212": 604,
130 | "258": 643,
131 | "95": 414,
132 | "264": 649,
133 | "674": 536,
134 | "977": 429,
135 | "31": 204,
136 | "687": 546,
137 | "64": 530,
138 | "505": 710,
139 | "227": 614,
140 | "234": 621,
141 | "683": 555,
142 | "1-670": 534,
143 | "47": 242,
144 | "968": 226,
145 | "92": 410,
146 | "680": 552,
147 | "970": 423,
148 | "507": 714,
149 | "675": 537,
150 | "595": 744,
151 | "51": 716,
152 | "63": 515,
153 | "48": 260,
154 | "351": 268,
155 | "1-787, 1-939": 330,
156 | "974": 427,
157 | "242": 630,
158 | "40": 226,
159 | "7": 250,
160 | "250": 635,
161 | "290": 658,
162 | "1-869": 356,
163 | "1-758": 358,
164 | "508": 308,
165 | "1-784": 360,
166 | "685": 544,
167 | "378": 292,
168 | "239": 626,
169 | "966": 420,
170 | "221": 608,
171 | "381": 220,
172 | "248": 633,
173 | "232": 619,
174 | "65": 525,
175 | "386": 293,
176 | "677": 540,
177 | "27": 655,
178 | "211": 659,
179 | "34": 214,
180 | "94": 413,
181 | "249": 634,
182 | "597": 746,
183 | "268": 653,
184 | "46": 240,
185 | "41": 228,
186 | "963": 417,
187 | "886": 466,
188 | "992": 436,
189 | "255": 640,
190 | "66": 520,
191 | "228": 615,
192 | "690": 554,
193 | "676": 539,
194 | "1-868": 374,
195 | "216": 605,
196 | "90": 286,
197 | "993": 438,
198 | "1-649": 376,
199 | "688": 553,
200 | "1-340": 332,
201 | "256": 641,
202 | "380": 255,
203 | "971": 424,
204 | "44": 234,
205 | "1": 310,
206 | "598": 748,
207 | "998": 434,
208 | "678": 541,
209 | "379": 225,
210 | "58": 734,
211 | "681": 543,
212 | "967": 421,
213 | "260": 645,
214 | "263": 648,
215 | "670": 514,
216 | "245": 632,
217 | "856": 457,
218 | "599": 362,
219 | "850": 467,
220 | "262": 647,
221 | "82": 450,
222 | "84": 452
223 | }
224 |
--------------------------------------------------------------------------------
/lib/WABinary/generic-utils.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.binaryNodeToString = exports.getBinaryNodeMessages = exports.reduceBinaryNodeToDictionary = exports.assertNodeErrorFree = exports.getBinaryNodeChildUInt = exports.getBinaryNodeChildString = exports.getBinaryNodeChildBuffer = exports.getBinaryNodeChild = exports.getAllBinaryNodeChildren = exports.getBinaryNodeChildren = void 0;
4 | const boom_1 = require("@hapi/boom");
5 | const WAProto_1 = require("../../WAProto");
6 | // some extra useful utilities
7 | const getBinaryNodeChildren = (node, childTag) => {
8 | if (Array.isArray(node === null || node === void 0 ? void 0 : node.content)) {
9 | return node.content.filter(item => item.tag === childTag);
10 | }
11 | return [];
12 | };
13 | exports.getBinaryNodeChildren = getBinaryNodeChildren;
14 | const getAllBinaryNodeChildren = ({ content }) => {
15 | if (Array.isArray(content)) {
16 | return content;
17 | }
18 | return [];
19 | };
20 | exports.getAllBinaryNodeChildren = getAllBinaryNodeChildren;
21 | const getBinaryNodeChild = (node, childTag) => {
22 | if (Array.isArray(node === null || node === void 0 ? void 0 : node.content)) {
23 | return node === null || node === void 0 ? void 0 : node.content.find(item => item.tag === childTag);
24 | }
25 | };
26 | exports.getBinaryNodeChild = getBinaryNodeChild;
27 | const getBinaryNodeChildBuffer = (node, childTag) => {
28 | var _a;
29 | const child = (_a = (0, exports.getBinaryNodeChild)(node, childTag)) === null || _a === void 0 ? void 0 : _a.content;
30 | if (Buffer.isBuffer(child) || child instanceof Uint8Array) {
31 | return child;
32 | }
33 | };
34 | exports.getBinaryNodeChildBuffer = getBinaryNodeChildBuffer;
35 | const getBinaryNodeChildString = (node, childTag) => {
36 | var _a;
37 | const child = (_a = (0, exports.getBinaryNodeChild)(node, childTag)) === null || _a === void 0 ? void 0 : _a.content;
38 | if (Buffer.isBuffer(child) || child instanceof Uint8Array) {
39 | return Buffer.from(child).toString('utf-8');
40 | }
41 | else if (typeof child === 'string') {
42 | return child;
43 | }
44 | };
45 | exports.getBinaryNodeChildString = getBinaryNodeChildString;
46 | const getBinaryNodeChildUInt = (node, childTag, length) => {
47 | const buff = (0, exports.getBinaryNodeChildBuffer)(node, childTag);
48 | if (buff) {
49 | return bufferToUInt(buff, length);
50 | }
51 | };
52 | exports.getBinaryNodeChildUInt = getBinaryNodeChildUInt;
53 | const assertNodeErrorFree = (node) => {
54 | const errNode = (0, exports.getBinaryNodeChild)(node, 'error');
55 | if (errNode) {
56 | throw new boom_1.Boom(errNode.attrs.text || 'Unknown error', { data: +errNode.attrs.code });
57 | }
58 | };
59 | exports.assertNodeErrorFree = assertNodeErrorFree;
60 | const reduceBinaryNodeToDictionary = (node, tag) => {
61 | const nodes = (0, exports.getBinaryNodeChildren)(node, tag);
62 | const dict = nodes.reduce((dict, { attrs }) => {
63 | dict[attrs.name || attrs.config_code] = attrs.value || attrs.config_value;
64 | return dict;
65 | }, {});
66 | return dict;
67 | };
68 | exports.reduceBinaryNodeToDictionary = reduceBinaryNodeToDictionary;
69 | const getBinaryNodeMessages = ({ content }) => {
70 | const msgs = [];
71 | if (Array.isArray(content)) {
72 | for (const item of content) {
73 | if (item.tag === 'message') {
74 | msgs.push(WAProto_1.proto.WebMessageInfo.decode(item.content));
75 | }
76 | }
77 | }
78 | return msgs;
79 | };
80 | exports.getBinaryNodeMessages = getBinaryNodeMessages;
81 | function bufferToUInt(e, t) {
82 | let a = 0;
83 | for (let i = 0; i < t; i++) {
84 | a = 256 * a + e[i];
85 | }
86 | return a;
87 | }
88 | const tabs = (n) => '\t'.repeat(n);
89 | function binaryNodeToString(node, i = 0) {
90 | if (!node) {
91 | return node;
92 | }
93 | if (typeof node === 'string') {
94 | return tabs(i) + node;
95 | }
96 | if (node instanceof Uint8Array) {
97 | return tabs(i) + Buffer.from(node).toString('hex');
98 | }
99 | if (Array.isArray(node)) {
100 | return node.map((x) => tabs(i + 1) + binaryNodeToString(x, i + 1)).join('\n');
101 | }
102 | const children = binaryNodeToString(node.content, i + 1);
103 | const tag = `<${node.tag} ${Object.entries(node.attrs || {})
104 | .filter(([, v]) => v !== undefined)
105 | .map(([k, v]) => `${k}='${v}'`)
106 | .join(' ')}`;
107 | const content = children ? `>\n${children}\n${tabs(i)}${node.tag}>` : '/>';
108 | return tag + content;
109 | }
110 | exports.binaryNodeToString = binaryNodeToString;
111 |
--------------------------------------------------------------------------------
/lib/Utils/generics.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { AxiosRequestConfig } from 'axios';
3 | import { Logger } from 'pino';
4 | import { proto } from '../../WAProto';
5 | import { BaileysEventEmitter, BaileysEventMap, WACallUpdateType, WAVersion } from '../Types';
6 | import { BinaryNode } from '../WABinary';
7 | export declare const Browsers: {
8 | ubuntu: (browser: any) => [string, string, string];
9 | macOS: (browser: any) => [string, string, string];
10 | baileys: (browser: any) => [string, string, string];
11 | windows: (browser: any) => [string, string, string];
12 | /** The appropriate browser based on your OS & release */
13 | appropriate: (browser: any) => [string, string, string];
14 | };
15 | export declare const BufferJSON: {
16 | replacer: (k: any, value: any) => any;
17 | reviver: (_: any, value: any) => any;
18 | };
19 | export declare const getKeyAuthor: (key: proto.IMessageKey | undefined | null, meId?: string) => string;
20 | export declare const writeRandomPadMax16: (msg: Uint8Array) => Buffer;
21 | export declare const unpadRandomMax16: (e: Uint8Array | Buffer) => Uint8Array;
22 | export declare const encodeWAMessage: (message: proto.IMessage) => Buffer;
23 | export declare const generateRegistrationId: () => number;
24 | export declare const encodeBigEndian: (e: number, t?: number) => Uint8Array;
25 | export declare const toNumber: (t: Long | number | null | undefined) => number;
26 | /** unix timestamp of a date in seconds */
27 | export declare const unixTimestampSeconds: (date?: Date) => number;
28 | export type DebouncedTimeout = ReturnType;
29 | export declare const debouncedTimeout: (intervalMs?: number, task?: () => void) => {
30 | start: (newIntervalMs?: number, newTask?: () => void) => void;
31 | cancel: () => void;
32 | setTask: (newTask: () => void) => () => void;
33 | setInterval: (newInterval: number) => number;
34 | };
35 | export declare const delay: (ms: number) => Promise;
36 | export declare const delayCancellable: (ms: number) => {
37 | delay: Promise;
38 | cancel: () => void;
39 | };
40 | export declare function promiseTimeout(ms: number | undefined, promise: (resolve: (v: T) => void, reject: (error: any) => void) => void): Promise;
41 | export declare const generateMessageIDV2: (userId?: string) => string;
42 | export declare const generateMessageID: () => string;
43 | export declare function bindWaitForEvent(ev: BaileysEventEmitter, event: T): (check: (u: BaileysEventMap[T]) => boolean | undefined, timeoutMs?: number) => Promise;
44 | export declare const bindWaitForConnectionUpdate: (ev: BaileysEventEmitter) => (check: (u: Partial) => boolean | undefined, timeoutMs?: number) => Promise;
45 | export declare const printQRIfNecessaryListener: (ev: BaileysEventEmitter, logger: Logger) => void;
46 | /**
47 | * utility that fetches latest baileys version from the master branch.
48 | * Use to ensure your WA connection is always on the latest version
49 | */
50 | export declare const fetchLatestBaileysVersion: (options?: AxiosRequestConfig) => Promise<{
51 | version: WAVersion;
52 | isLatest: boolean;
53 | error?: undefined;
54 | } | {
55 | version: WAVersion;
56 | isLatest: boolean;
57 | error: any;
58 | }>;
59 | /**
60 | * A utility that fetches the latest web version of whatsapp.
61 | * Use to ensure your WA connection is always on the latest version
62 | */
63 | export declare const fetchLatestWaWebVersion: (options: AxiosRequestConfig) => Promise<{
64 | version: WAVersion;
65 | isLatest: boolean;
66 | error?: undefined;
67 | } | {
68 | version: WAVersion;
69 | isLatest: boolean;
70 | error: any;
71 | }>;
72 | /** unique message tag prefix for MD clients */
73 | export declare const generateMdTagPrefix: () => string;
74 | /**
75 | * Given a type of receipt, returns what the new status of the message should be
76 | * @param type type from receipt
77 | */
78 | export declare const getStatusFromReceiptType: (type: string | undefined) => proto.WebMessageInfo.Status;
79 | /**
80 | * Stream errors generally provide a reason, map that to a baileys DisconnectReason
81 | * @param reason the string reason given, eg. "conflict"
82 | */
83 | export declare const getErrorCodeFromStreamError: (node: BinaryNode) => {
84 | reason: string;
85 | statusCode: number;
86 | };
87 | export declare const getCallStatusFromNode: ({ tag, attrs }: BinaryNode) => WACallUpdateType;
88 | export declare const getCodeFromWSError: (error: Error) => number;
89 | /**
90 | * Is the given platform WA business
91 | * @param platform AuthenticationCreds.platform
92 | */
93 | export declare const isWABusinessPlatform: (platform: string) => boolean;
94 | export declare function trimUndefined(obj: any): any;
95 | export declare function bytesToCrockford(buffer: Buffer): string;
96 |
--------------------------------------------------------------------------------
/lib/Socket/chats.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Boom } from '@hapi/boom';
3 | import { proto } from '../../WAProto';
4 | import { ChatModification, MessageUpsertType, SocketConfig, WABusinessProfile, WAMediaUpload, WAPatchCreate, WAPresence, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '../Types';
5 | import { BinaryNode } from '../WABinary';
6 | export declare const makeChatsSocket: (config: SocketConfig) => {
7 | processingMutex: {
8 | mutex(code: () => T | Promise): Promise;
9 | };
10 | fetchPrivacySettings: (force?: boolean) => Promise<{
11 | [_: string]: string;
12 | }>;
13 | upsertMessage: (msg: proto.IWebMessageInfo, type: MessageUpsertType) => Promise;
14 | appPatch: (patchCreate: WAPatchCreate) => Promise;
15 | sendPresenceUpdate: (type: WAPresence, toJid?: string) => Promise;
16 | presenceSubscribe: (toJid: string, tcToken?: Buffer) => Promise;
17 | profilePictureUrl: (jid: string, type?: 'preview' | 'image', timeoutMs?: number) => Promise;
18 | onWhatsApp: (...jids: string[]) => Promise<{
19 | exists: boolean;
20 | jid: string;
21 | }[]>;
22 | fetchBlocklist: () => Promise;
23 | fetchStatus: (jid: string) => Promise<{
24 | status: string | undefined;
25 | setAt: Date;
26 | } | undefined>;
27 | updateProfilePicture: (jid: string, content: WAMediaUpload) => Promise;
28 | removeProfilePicture: (jid: string) => Promise;
29 | updateProfileStatus: (status: string) => Promise;
30 | updateProfileName: (name: string) => Promise;
31 | updateBlockStatus: (jid: string, action: 'block' | 'unblock') => Promise;
32 | updateLastSeenPrivacy: (value: WAPrivacyValue) => Promise;
33 | updateOnlinePrivacy: (value: WAPrivacyOnlineValue) => Promise;
34 | updateProfilePicturePrivacy: (value: WAPrivacyValue) => Promise;
35 | updateStatusPrivacy: (value: WAPrivacyValue) => Promise;
36 | updateReadReceiptsPrivacy: (value: WAReadReceiptsValue) => Promise;
37 | updateGroupsAddPrivacy: (value: WAPrivacyValue) => Promise;
38 | updateDefaultDisappearingMode: (duration: number) => Promise;
39 | getBusinessProfile: (jid: string) => Promise;
40 | resyncAppState: (collections: readonly ("critical_block" | "critical_unblock_low" | "regular_high" | "regular_low" | "regular")[], isInitialSync: boolean) => Promise;
41 | chatModify: (mod: ChatModification, jid: string) => Promise;
42 | cleanDirtyBits: (type: 'account_sync' | 'groups', fromTimestamp?: number | string) => Promise;
43 | addChatLabel: (jid: string, labelId: string) => Promise;
44 | removeChatLabel: (jid: string, labelId: string) => Promise;
45 | addMessageLabel: (jid: string, messageId: string, labelId: string) => Promise;
46 | removeMessageLabel: (jid: string, messageId: string, labelId: string) => Promise;
47 | star: (jid: string, messages: {
48 | id: string;
49 | fromMe?: boolean;
50 | }[], star: boolean) => Promise;
51 | type: "md";
52 | ws: any;
53 | ev: import("../Types").BaileysEventEmitter & {
54 | process(handler: (events: Partial) => void | Promise): () => void;
55 | buffer(): void;
56 | createBufferedFunction(work: (...args: A) => Promise): (...args: A) => Promise;
57 | flush(force?: boolean | undefined): boolean;
58 | isBuffering(): boolean;
59 | };
60 | authState: {
61 | creds: import("../Types").AuthenticationCreds;
62 | keys: import("../Types").SignalKeyStoreWithTransaction;
63 | };
64 | signalRepository: import("../Types").SignalRepository;
65 | user: import("../Types").Contact | undefined;
66 | generateMessageTag: () => string;
67 | query: (node: BinaryNode, timeoutMs?: number | undefined) => Promise;
68 | waitForMessage: (msgId: string, timeoutMs?: number | undefined) => Promise;
69 | waitForSocketOpen: () => Promise;
70 | sendRawMessage: (data: Uint8Array | Buffer) => Promise;
71 | sendNode: (frame: BinaryNode) => Promise;
72 | logout: (msg?: string | undefined) => Promise;
73 | end: (error: Error | undefined) => void;
74 | onUnexpectedError: (err: Error | Boom, msg: string) => void;
75 | uploadPreKeys: (count?: number) => Promise;
76 | uploadPreKeysToServerIfRequired: () => Promise;
77 | requestPairingCode: (phoneNumber: string) => Promise;
78 | waitForConnectionUpdate: (check: (u: Partial) => boolean | undefined, timeoutMs?: number | undefined) => Promise;
79 | sendWAMBuffer: (wamBuffer: Buffer) => Promise;
80 | };
81 |
--------------------------------------------------------------------------------
/lib/Utils/messages.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | import { Logger } from 'pino';
4 | import { type Transform } from 'stream';
5 | import { proto } from '../../WAProto';
6 | import { AnyMediaMessageContent, AnyMessageContent, MediaGenerationOptions, MessageContentGenerationOptions, MessageGenerationOptions, MessageGenerationOptionsFromContent, MessageUserReceipt, WAMessage, WAMessageContent, WAProto } from '../Types';
7 | import { MediaDownloadOptions } from './messages-media';
8 | /**
9 | * Uses a regex to test whether the string contains a URL, and returns the URL if it does.
10 | * @param text eg. hello https://google.com
11 | * @returns the URL, eg. https://google.com
12 | */
13 | export declare const extractUrlFromText: (text: string) => string | undefined;
14 | export declare const generateLinkPreviewIfRequired: (text: string, getUrlInfo: MessageGenerationOptions['getUrlInfo'], logger: MessageGenerationOptions['logger']) => Promise;
15 | export declare const prepareWAMessageMedia: (message: AnyMediaMessageContent, options: MediaGenerationOptions) => Promise;
16 | export declare const prepareDisappearingMessageSettingContent: (ephemeralExpiration?: number) => proto.Message;
17 | /**
18 | * Generate forwarded message content like WA does
19 | * @param message the message to forward
20 | * @param options.forceForward will show the message as forwarded even if it is from you
21 | */
22 | export declare const generateForwardMessageContent: (message: WAMessage, forceForward?: boolean) => proto.IMessage;
23 | export declare const generateWAMessageContent: (message: AnyMessageContent, options: MessageContentGenerationOptions) => Promise;
24 | export declare const generateWAMessageFromContent: (jid: string, message: WAMessageContent, options: MessageGenerationOptionsFromContent) => proto.WebMessageInfo;
25 | export declare const generateWAMessage: (jid: string, content: AnyMessageContent, options: MessageGenerationOptions) => Promise;
26 | /** Get the key to access the true type of content */
27 | export declare const getContentType: (content: WAProto.IMessage | undefined) => keyof proto.IMessage | undefined;
28 | /**
29 | * Normalizes ephemeral, view once messages to regular message content
30 | * Eg. image messages in ephemeral messages, in view once messages etc.
31 | * @param content
32 | * @returns
33 | */
34 | export declare const normalizeMessageContent: (content: WAMessageContent | null | undefined) => WAMessageContent | undefined;
35 | /**
36 | * Extract the true message content from a message
37 | * Eg. extracts the inner message from a disappearing message/view once message
38 | */
39 | export declare const extractMessageContent: (content: WAMessageContent | undefined | null) => WAMessageContent | undefined;
40 | /**
41 | * Returns the device predicted by message ID
42 | */
43 | export declare const getDevice: (id: string) => "android" | "unknown" | "web" | "ios" | "desktop";
44 | /** Upserts a receipt in the message */
45 | export declare const updateMessageWithReceipt: (msg: Pick, receipt: MessageUserReceipt) => void;
46 | /** Update the message with a new reaction */
47 | export declare const updateMessageWithReaction: (msg: Pick, reaction: proto.IReaction) => void;
48 | /** Update the message with a new poll update */
49 | export declare const updateMessageWithPollUpdate: (msg: Pick, update: proto.IPollUpdate) => void;
50 | type VoteAggregation = {
51 | name: string;
52 | voters: string[];
53 | };
54 | /**
55 | * Aggregates all poll updates in a poll.
56 | * @param msg the poll creation message
57 | * @param meId your jid
58 | * @returns A list of options & their voters
59 | */
60 | export declare function getAggregateVotesInPollMessage({ message, pollUpdates }: Pick, meId?: string): VoteAggregation[];
61 | /** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
62 | export declare const aggregateMessageKeysNotFromMe: (keys: proto.IMessageKey[]) => {
63 | jid: string;
64 | participant: string | undefined;
65 | messageIds: string[];
66 | }[];
67 | type DownloadMediaMessageContext = {
68 | reuploadRequest: (msg: WAMessage) => Promise;
69 | logger: Logger;
70 | };
71 | /**
72 | * Downloads the given message. Throws an error if it's not a media message
73 | */
74 | export declare const downloadMediaMessage: (message: WAMessage, type: Type, options: MediaDownloadOptions, ctx?: DownloadMediaMessageContext) => Promise;
75 | /** Checks whether the given message is a media message; if it is returns the inner content */
76 | export declare const assertMediaContent: (content: proto.IMessage | null | undefined) => proto.Message.IVideoMessage | proto.Message.IImageMessage | proto.Message.IAudioMessage | proto.Message.IDocumentMessage | proto.Message.IStickerMessage;
77 | export {};
78 |
--------------------------------------------------------------------------------
/lib/Types/Socket.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | import { AxiosRequestConfig } from 'axios';
4 | import type { Agent } from 'https';
5 | import type { Logger } from 'pino';
6 | import type { URL } from 'url';
7 | import { proto } from '../../WAProto';
8 | import { AuthenticationState, SignalAuthState, TransactionCapabilityOptions } from './Auth';
9 | import { MediaConnInfo } from './Message';
10 | import { SignalRepository } from './Signal';
11 | export type WAVersion = [number, number, number];
12 | export type WABrowserDescription = [string, string, string];
13 | export type CacheStore = {
14 | /** get a cached key and change the stats */
15 | get(key: string): T | undefined;
16 | /** set a key in the cache */
17 | set(key: string, value: T): void;
18 | /** delete a key from the cache */
19 | del(key: string): void;
20 | /** flush all data */
21 | flushAll(): void;
22 | };
23 | export type SocketConfig = {
24 | /** the WS url to connect to WA */
25 | waWebSocketUrl: string | URL;
26 | /** Fails the connection if the socket times out in this interval */
27 | connectTimeoutMs: number;
28 | /** Default timeout for queries, undefined for no timeout */
29 | defaultQueryTimeoutMs: number | undefined;
30 | /** ping-pong interval for WS connection */
31 | keepAliveIntervalMs: number;
32 | /** should baileys use the mobile api instead of the multi device api */
33 | mobile?: boolean;
34 | /** proxy agent */
35 | agent?: Agent;
36 | /** pino logger */
37 | logger: Logger;
38 | /** version to connect with */
39 | version: WAVersion;
40 | /** override browser config */
41 | browser: WABrowserDescription;
42 | /** agent used for fetch requests -- uploading/downloading media */
43 | fetchAgent?: Agent;
44 | /** should the QR be printed in the terminal */
45 | printQRInTerminal: boolean;
46 | /** should events be emitted for actions done by this socket connection */
47 | emitOwnEvents: boolean;
48 | /** custom upload hosts to upload media to */
49 | customUploadHosts: MediaConnInfo['hosts'];
50 | /** time to wait between sending new retry requests */
51 | retryRequestDelayMs: number;
52 | /** max retry count */
53 | maxMsgRetryCount: number;
54 | /** time to wait for the generation of the next QR in ms */
55 | qrTimeout?: number;
56 | /** provide an auth state object to maintain the auth state */
57 | auth: AuthenticationState;
58 | /** manage history processing with this control; by default will sync up everything */
59 | shouldSyncHistoryMessage: (msg: proto.Message.IHistorySyncNotification) => boolean;
60 | /** transaction capability options for SignalKeyStore */
61 | transactionOpts: TransactionCapabilityOptions;
62 | /** marks the client as online whenever the socket successfully connects */
63 | markOnlineOnConnect: boolean;
64 | /** provide a cache to store media, so does not have to be re-uploaded */
65 | mediaCache?: CacheStore;
66 | /**
67 | * map to store the retry counts for failed messages;
68 | * used to determine whether to retry a message or not */
69 | msgRetryCounterCache?: CacheStore;
70 | /** provide a cache to store a user's device list */
71 | userDevicesCache?: CacheStore;
72 | /** cache to store call offers */
73 | callOfferCache?: CacheStore;
74 | /** width for link preview images */
75 | linkPreviewImageThumbnailWidth: number;
76 | /** Should Baileys ask the phone for full history, will be received async */
77 | syncFullHistory: boolean;
78 | /** Should baileys fire init queries automatically, default true */
79 | fireInitQueries: boolean;
80 | /**
81 | * generate a high quality link preview,
82 | * entails uploading the jpegThumbnail to WA
83 | * */
84 | generateHighQualityLinkPreview: boolean;
85 | /**
86 | * Returns if a jid should be ignored,
87 | * no event for that jid will be triggered.
88 | * Messages from that jid will also not be decrypted
89 | * */
90 | shouldIgnoreJid: (jid: string) => boolean | undefined;
91 | /**
92 | * Optionally patch the message before sending out
93 | * */
94 | patchMessageBeforeSending: (msg: proto.IMessage, recipientJids: string[]) => Promise | proto.IMessage;
95 | /** verify app state MACs */
96 | appStateMacVerification: {
97 | patch: boolean;
98 | snapshot: boolean;
99 | };
100 | /** options for axios */
101 | options: AxiosRequestConfig<{}>;
102 | /**
103 | * fetch a message from your store
104 | * implement this so that messages failed to send
105 | * (solves the "this message can take a while" issue) can be retried
106 | * */
107 | getMessage: (key: proto.IMessageKey) => Promise;
108 | makeSignalRepository: (auth: SignalAuthState) => SignalRepository;
109 | /** Socket passthrough */
110 | socket?: any;
111 | };
112 |
--------------------------------------------------------------------------------
/lib/Store/make-in-memory-store.d.ts:
--------------------------------------------------------------------------------
1 | import type KeyedDB from '@adiwajshing/keyed-db';
2 | import type { Comparable } from '@adiwajshing/keyed-db/lib/Types';
3 | import type { Logger } from 'pino';
4 | import { proto } from '../../WAProto';
5 | import type makeMDSocket from '../Socket';
6 | import type { BaileysEventEmitter, Chat, ConnectionState, Contact, GroupMetadata, PresenceData, WAMessage, WAMessageCursor, WAMessageKey } from '../Types';
7 | import { Label } from '../Types/Label';
8 | import { LabelAssociation } from '../Types/LabelAssociation';
9 | import { ObjectRepository } from './object-repository';
10 | type WASocket = ReturnType;
11 | export declare const waChatKey: (pin: boolean) => {
12 | key: (c: Chat) => string;
13 | compare: (k1: string, k2: string) => number;
14 | };
15 | export declare const waMessageID: (m: WAMessage) => string;
16 | export declare const waLabelAssociationKey: Comparable;
17 | export type BaileysInMemoryStoreConfig = {
18 | chatKey?: Comparable;
19 | labelAssociationKey?: Comparable;
20 | logger?: Logger;
21 | socket?: WASocket;
22 | };
23 | declare const _default: (config: BaileysInMemoryStoreConfig) => {
24 | chats: KeyedDB;
25 | contacts: {
26 | [_: string]: Contact;
27 | };
28 | messages: {
29 | [_: string]: {
30 | array: proto.IWebMessageInfo[];
31 | get: (id: string) => proto.IWebMessageInfo | undefined;
32 | upsert: (item: proto.IWebMessageInfo, mode: "append" | "prepend") => void;
33 | update: (item: proto.IWebMessageInfo) => boolean;
34 | remove: (item: proto.IWebMessageInfo) => boolean;
35 | updateAssign: (id: string, update: Partial) => boolean;
36 | clear: () => void;
37 | filter: (contain: (item: proto.IWebMessageInfo) => boolean) => void;
38 | toJSON: () => proto.IWebMessageInfo[];
39 | fromJSON: (newItems: proto.IWebMessageInfo[]) => void;
40 | };
41 | };
42 | groupMetadata: {
43 | [_: string]: GroupMetadata;
44 | };
45 | state: ConnectionState;
46 | presences: {
47 | [id: string]: {
48 | [participant: string]: PresenceData;
49 | };
50 | };
51 | labels: ObjectRepository