@ryuu-reinzz/baileys 3.0.0-beta.2 → 3.0.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,48 @@
1
+ import { proto } from '../../WAProto/index.js';
2
+ import { isLidUser, isPnUser } from '../WABinary/index.js';
3
+ /**
4
+ * Process contactAction and return events to emit.
5
+ * Pure function - no side effects.
6
+ */
7
+ export const processContactAction = (action, id, logger) => {
8
+ const results = [];
9
+ if (!id) {
10
+ logger?.warn({ hasFullName: !!action.fullName, hasLidJid: !!action.lidJid, hasPnJid: !!action.pnJid }, 'contactAction sync: missing id in index');
11
+ return results;
12
+ }
13
+ const lidJid = action.lidJid;
14
+ const idIsPn = isPnUser(id);
15
+ // PN is in index[1], not in contactAction.pnJid which is usually null
16
+ const phoneNumber = idIsPn ? id : action.pnJid || undefined;
17
+ // Always emit contacts.upsert
18
+ results.push({
19
+ event: 'contacts.upsert',
20
+ data: [
21
+ {
22
+ id,
23
+ name: action.fullName || action.firstName || action.username || undefined,
24
+ lid: lidJid || undefined,
25
+ phoneNumber
26
+ }
27
+ ]
28
+ });
29
+ // Emit lid-mapping.update if we have valid LID-PN pair
30
+ if (lidJid && isLidUser(lidJid) && idIsPn) {
31
+ results.push({
32
+ event: 'lid-mapping.update',
33
+ data: { lid: lidJid, pn: id }
34
+ });
35
+ }
36
+ return results;
37
+ };
38
+ export const emitSyncActionResults = (ev, results) => {
39
+ for (const result of results) {
40
+ if (result.event === 'contacts.upsert') {
41
+ ev.emit('contacts.upsert', result.data);
42
+ }
43
+ else {
44
+ ev.emit('lid-mapping.update', result.data);
45
+ }
46
+ }
47
+ };
48
+ //# sourceMappingURL=sync-action-utils.js.map
@@ -0,0 +1,18 @@
1
+ export async function buildTcTokenFromJid({ authState, jid, baseContent = [] }) {
2
+ try {
3
+ const tcTokenData = await authState.keys.get('tctoken', [jid]);
4
+ const tcTokenBuffer = tcTokenData?.[jid]?.token;
5
+ if (!tcTokenBuffer)
6
+ return baseContent.length > 0 ? baseContent : undefined;
7
+ baseContent.push({
8
+ tag: 'tctoken',
9
+ attrs: {},
10
+ content: tcTokenBuffer
11
+ });
12
+ return baseContent;
13
+ }
14
+ catch (error) {
15
+ return baseContent.length > 0 ? baseContent : undefined;
16
+ }
17
+ }
18
+ //# sourceMappingURL=tc-token-utils.js.map
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Custom SQLite Auth Store untuk Baileys
3
+ * by Ryuu
4
+ */
5
+
6
+ import Database from "better-sqlite3";
7
+ import { proto } from '../../WAProto/index.js';
8
+ import { initAuthCreds } from './auth-utils.js';
9
+ import { BufferJSON } from './generics.js';
10
+ import fs from 'fs';
11
+ /**
12
+ * Membuat atau mengambil auth state dari SQLite
13
+ * @param {string} folder - Lokasi file SQLite (contoh: "./auth.db")
14
+ */
15
+ export const useSQLiteAuthState = async (folder) => {
16
+ if (!folder) {
17
+ throw new Error('Path required')
18
+ };
19
+ if (!fs.existsSync(folder)) {
20
+ fs.mkdirSync(folder, { recursive: true })
21
+ };
22
+ if (folder.endsWith("/")) {
23
+ folder += "auth.db"
24
+ } else {
25
+ folder += "/auth.db"
26
+ }
27
+ const db = new Database(folder);
28
+ db.pragma("journal_mode = WAL");
29
+
30
+ db.prepare(`
31
+ CREATE TABLE IF NOT EXISTS baileys_state (
32
+ key TEXT PRIMARY KEY,
33
+ value BLOB
34
+ )
35
+ `).run();
36
+
37
+ const load = (key) => {
38
+ const row = db.prepare("SELECT value FROM baileys_state WHERE key = ?").get(key);
39
+ if (!row) return null;
40
+ try {
41
+ return JSON.parse(row.value.toString(), BufferJSON.reviver);
42
+ } catch {
43
+ return null;
44
+ }
45
+ };
46
+
47
+ const save = (key, data) => {
48
+ const json = JSON.stringify(data, BufferJSON.replacer);
49
+ const buf = Buffer.from(json, "utf8");
50
+ db.prepare("REPLACE INTO baileys_state (key, value) VALUES (?, ?)").run(key, buf);
51
+ };
52
+
53
+ const creds = load("creds") || initAuthCreds();
54
+
55
+ const keys = {};
56
+ const categories = [
57
+ "pre-key",
58
+ "session",
59
+ "sender-key",
60
+ "app-state-sync-key",
61
+ "app-state-sync-version"
62
+ ];
63
+
64
+ for (const category of categories) {
65
+ keys[category] = {};
66
+ const rows = db
67
+ .prepare("SELECT key, value FROM baileys_state WHERE key LIKE ?")
68
+ .all(`${category}:%`);
69
+ for (const row of rows) {
70
+ try {
71
+ keys[category][row.key.slice(category.length + 1)] = JSON.parse(row.value.toString());
72
+ } catch {}
73
+ }
74
+ }
75
+
76
+ async function saveCreds() {
77
+ save("creds", creds);
78
+ }
79
+
80
+ const set = (category, id, value) => {
81
+ const key = `${category}:${id}`;
82
+ save(key, value);
83
+ };
84
+
85
+ const get = (category, id) => {
86
+ const key = `${category}:${id}`;
87
+ return load(key);
88
+ };
89
+
90
+ const del = (category, id) => {
91
+ const key = `${category}:${id}`;
92
+ db.prepare("DELETE FROM baileys_state WHERE key = ?").run(key);
93
+ };
94
+
95
+ return {
96
+ state: {
97
+ creds,
98
+ keys: {
99
+ get: async (type, ids) => {
100
+ const data = {};
101
+ for (const id of ids) {
102
+ const value = load(`${type}:${id}`);
103
+ if (value) data[id] = value;
104
+ }
105
+ return data;
106
+ },
107
+ set: async (data) => {
108
+ for (const category in data) {
109
+ for (const id in data[category]) {
110
+ const value = data[category][id];
111
+ save(`${category}:${id}`, value);
112
+ }
113
+ }
114
+ }
115
+ }
116
+ },
117
+ saveCreds: async () => save("creds", creds)
118
+ };
119
+ setInterval(async () => {
120
+ await save("creds", creds);
121
+ }, 30_000);
122
+ }
@@ -136,6 +136,26 @@ export const decodeDecompressedBinaryNode = (buffer, opts, indexRef = { index: 0
136
136
  }
137
137
  return jidEncode(user, server, device);
138
138
  };
139
+ const readFbJid = () => {
140
+ const user = readString(readByte());
141
+ const device = readInt(2);
142
+ const server = readString(readByte());
143
+ return `${user}:${device}@${server}`;
144
+ };
145
+ const readInteropJid = () => {
146
+ const user = readString(readByte());
147
+ const device = readInt(2);
148
+ const integrator = readInt(2);
149
+ let server = 'interop';
150
+ const beforeServer = indexRef.index;
151
+ try {
152
+ server = readString(readByte());
153
+ }
154
+ catch (err) {
155
+ indexRef.index = beforeServer;
156
+ }
157
+ return `${integrator}-${user}:${device}@${server}`;
158
+ };
139
159
  const readString = (tag) => {
140
160
  if (tag >= 1 && tag < SINGLE_BYTE_TOKENS.length) {
141
161
  return SINGLE_BYTE_TOKENS[tag] || '';
@@ -156,6 +176,10 @@ export const decodeDecompressedBinaryNode = (buffer, opts, indexRef = { index: 0
156
176
  return readStringFromChars(readInt(4));
157
177
  case TAGS.JID_PAIR:
158
178
  return readJidPair();
179
+ case TAGS.FB_JID:
180
+ return readFbJid();
181
+ case TAGS.INTEROP_JID:
182
+ return readInteropJid();
159
183
  case TAGS.AD_JID:
160
184
  return readAdJid();
161
185
  case TAGS.HEX_8:
@@ -144,6 +144,10 @@ const encodeBinaryNodeInner = ({ tag, attrs, content }, opts, buffer) => {
144
144
  pushByte(TAGS.LIST_EMPTY);
145
145
  return;
146
146
  }
147
+ if (str === '') {
148
+ writeStringRaw(str);
149
+ return;
150
+ }
147
151
  const tokenIndex = TOKEN_MAP[str];
148
152
  if (tokenIndex) {
149
153
  if (typeof tokenIndex.dict === 'number') {
@@ -157,7 +161,7 @@ const encodeBinaryNodeInner = ({ tag, attrs, content }, opts, buffer) => {
157
161
  else if (isHex(str)) {
158
162
  writePackedBytes(str, 'hex');
159
163
  }
160
- else if (str) {
164
+ else {
161
165
  const decodedJid = jidDecode(str);
162
166
  if (decodedJid) {
163
167
  writeJid(decodedJid);
@@ -2,11 +2,27 @@ import { Boom } from '@hapi/boom';
2
2
  import { proto } from '../../WAProto/index.js';
3
3
  import {} from './types.js';
4
4
  // some extra useful utilities
5
+ const indexCache = new WeakMap();
5
6
  export const getBinaryNodeChildren = (node, childTag) => {
6
- if (Array.isArray(node?.content)) {
7
- return node.content.filter(item => item.tag === childTag);
7
+ if (!node || !Array.isArray(node.content))
8
+ return [];
9
+ let index = indexCache.get(node);
10
+ // Build the index once per node
11
+ if (!index) {
12
+ index = new Map();
13
+ for (const child of node.content) {
14
+ let arr = index.get(child.tag);
15
+ if (!arr)
16
+ index.set(child.tag, (arr = []));
17
+ arr.push(child);
18
+ }
19
+ indexCache.set(node, index);
8
20
  }
9
- return [];
21
+ // Return first matching child
22
+ return index.get(childTag) || [];
23
+ };
24
+ export const getBinaryNodeChild = (node, childTag) => {
25
+ return getBinaryNodeChildren(node, childTag)[0];
10
26
  };
11
27
  export const getAllBinaryNodeChildren = ({ content }) => {
12
28
  if (Array.isArray(content)) {
@@ -14,11 +30,6 @@ export const getAllBinaryNodeChildren = ({ content }) => {
14
30
  }
15
31
  return [];
16
32
  };
17
- export const getBinaryNodeChild = (node, childTag) => {
18
- if (Array.isArray(node?.content)) {
19
- return node?.content.find(item => item.tag === childTag);
20
- }
21
- };
22
33
  export const getBinaryNodeChildBuffer = (node, childTag) => {
23
34
  const child = getBinaryNodeChild(node, childTag)?.content;
24
35
  if (Buffer.isBuffer(child) || child instanceof Uint8Array) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ryuu-reinzz/baileys",
3
3
  "type": "module",
4
- "version": "3.0.0-beta.2",
4
+ "version": "3.0.0-beta.21",
5
5
  "description": "A WebSockets library for interacting with WhatsApp Web",
6
6
  "keywords": [
7
7
  "whatsapp",
@@ -20,17 +20,22 @@
20
20
  "WAProto/**/*",
21
21
  "engine-requirements.js"
22
22
  ],
23
+ "scripts": {
24
+ "start": "node engine-requirements.js"
25
+ },
23
26
  "dependencies": {
24
27
  "@cacheable/node-cache": "^1.4.0",
25
- "@ryuu-reinzz/haruka-lib": "^3.2.0",
28
+ "@ryuu-reinzz/haruka-lib": "^3.2.3",
26
29
  "@hapi/boom": "^9.1.3",
27
30
  "async-mutex": "^0.5.0",
31
+ "better-sqlite3": "^12.5.0",
28
32
  "libsignal": "git+https://github.com/whiskeysockets/libsignal-node",
29
33
  "lru-cache": "^11.1.0",
30
34
  "music-metadata": "^11.7.0",
31
35
  "p-queue": "^9.0.0",
32
36
  "pino": "^9.6",
33
37
  "protobufjs": "^7.2.4",
38
+ "whatsapp-rust-bridge": "0.5.2",
34
39
  "ws": "^8.13.0"
35
40
  },
36
41
  "devDependencies": {