@vanzxy/baileys 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +111 -0
- package/README.md +830 -0
- package/WAProto/index.d.ts +9 -0
- package/WAProto/index.js +142036 -0
- package/engine-requirements.js +13 -0
- package/lib/Defaults/index.d.ts +152 -0
- package/lib/Defaults/index.js +179 -0
- package/lib/Framework/Bot.js +209 -0
- package/lib/Framework/Context.js +90 -0
- package/lib/Framework/MediaManager.js +152 -0
- package/lib/Framework/SessionManager.js +34 -0
- package/lib/Framework/StatsManager.js +120 -0
- package/lib/Framework/Store/SQLiteStore.js +74 -0
- package/lib/Framework/index.js +11 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
- package/lib/Signal/Group/ciphertext-message.js +12 -0
- package/lib/Signal/Group/group-session-builder.d.ts +7 -0
- package/lib/Signal/Group/group-session-builder.js +30 -0
- package/lib/Signal/Group/group_cipher.d.ts +10 -0
- package/lib/Signal/Group/group_cipher.js +82 -0
- package/lib/Signal/Group/index.d.ts +11 -0
- package/lib/Signal/Group/index.js +12 -0
- package/lib/Signal/Group/keyhelper.d.ts +6 -0
- package/lib/Signal/Group/keyhelper.js +18 -0
- package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
- package/lib/Signal/Group/sender-chain-key.js +26 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +63 -0
- package/lib/Signal/Group/sender-key-message.d.ts +18 -0
- package/lib/Signal/Group/sender-key-message.js +66 -0
- package/lib/Signal/Group/sender-key-name.d.ts +11 -0
- package/lib/Signal/Group/sender-key-name.js +48 -0
- package/lib/Signal/Group/sender-key-record.d.ts +12 -0
- package/lib/Signal/Group/sender-key-record.js +41 -0
- package/lib/Signal/Group/sender-key-state.d.ts +16 -0
- package/lib/Signal/Group/sender-key-state.js +84 -0
- package/lib/Signal/Group/sender-message-key.d.ts +11 -0
- package/lib/Signal/Group/sender-message-key.js +26 -0
- package/lib/Signal/libsignal.d.ts +54 -0
- package/lib/Signal/libsignal.js +431 -0
- package/lib/Signal/lid-mapping.d.ts +20 -0
- package/lib/Signal/lid-mapping.js +277 -0
- package/lib/Socket/Client/index.d.ts +2 -0
- package/lib/Socket/Client/index.js +3 -0
- package/lib/Socket/Client/types.d.ts +5 -0
- package/lib/Socket/Client/types.js +11 -0
- package/lib/Socket/Client/websocket.d.ts +12 -0
- package/lib/Socket/Client/websocket.js +54 -0
- package/lib/Socket/business.d.ts +395 -0
- package/lib/Socket/business.js +380 -0
- package/lib/Socket/chats.d.ts +136 -0
- package/lib/Socket/chats.js +1328 -0
- package/lib/Socket/communities.d.ts +561 -0
- package/lib/Socket/communities.js +434 -0
- package/lib/Socket/dugong.d.ts +117 -0
- package/lib/Socket/dugong.js +799 -0
- package/lib/Socket/groups.d.ts +285 -0
- package/lib/Socket/groups.js +355 -0
- package/lib/Socket/index.d.ts +531 -0
- package/lib/Socket/index.js +34 -0
- package/lib/Socket/messages-recv.d.ts +333 -0
- package/lib/Socket/messages-recv.js +1782 -0
- package/lib/Socket/messages-send.d.ts +329 -0
- package/lib/Socket/messages-send.js +1383 -0
- package/lib/Socket/mex.d.ts +1 -0
- package/lib/Socket/mex.js +42 -0
- package/lib/Socket/newsletter.d.ts +281 -0
- package/lib/Socket/newsletter.js +321 -0
- package/lib/Socket/socket.d.ts +60 -0
- package/lib/Socket/socket.js +1001 -0
- package/lib/Socket/username.js +153 -0
- package/lib/Store/index.d.ts +3 -0
- package/lib/Store/index.js +4 -0
- package/lib/Store/make-in-memory-store.d.ts +62 -0
- package/lib/Store/make-in-memory-store.js +429 -0
- package/lib/Store/make-ordered-dictionary.d.ts +12 -0
- package/lib/Store/make-ordered-dictionary.js +79 -0
- package/lib/Store/object-repository.d.ts +10 -0
- package/lib/Store/object-repository.js +24 -0
- package/lib/Types/Auth.d.ts +117 -0
- package/lib/Types/Auth.js +2 -0
- package/lib/Types/Bussines.d.ts +25 -0
- package/lib/Types/Bussines.js +2 -0
- package/lib/Types/Call.d.ts +15 -0
- package/lib/Types/Call.js +2 -0
- package/lib/Types/Chat.d.ts +124 -0
- package/lib/Types/Chat.js +8 -0
- package/lib/Types/Contact.d.ts +26 -0
- package/lib/Types/Contact.js +2 -0
- package/lib/Types/Events.d.ts +256 -0
- package/lib/Types/Events.js +2 -0
- package/lib/Types/GroupMetadata.d.ts +71 -0
- package/lib/Types/GroupMetadata.js +2 -0
- package/lib/Types/Label.d.ts +2 -0
- package/lib/Types/Label.js +25 -0
- package/lib/Types/LabelAssociation.d.ts +2 -0
- package/lib/Types/LabelAssociation.js +7 -0
- package/lib/Types/Message.d.ts +11 -0
- package/lib/Types/Message.js +18 -0
- package/lib/Types/Mex.d.ts +2 -0
- package/lib/Types/Mex.js +39 -0
- package/lib/Types/Product.d.ts +79 -0
- package/lib/Types/Product.js +2 -0
- package/lib/Types/RichType.d.ts +2 -0
- package/lib/Types/RichType.js +23 -0
- package/lib/Types/Signal.d.ts +87 -0
- package/lib/Types/Signal.js +2 -0
- package/lib/Types/Socket.d.ts +136 -0
- package/lib/Types/Socket.js +2 -0
- package/lib/Types/State.d.ts +5 -0
- package/lib/Types/State.js +56 -0
- package/lib/Types/USync.d.ts +26 -0
- package/lib/Types/USync.js +2 -0
- package/lib/Types/index.d.ts +66 -0
- package/lib/Types/index.js +26 -0
- package/lib/Utils/A2UI.js +277 -0
- package/lib/Utils/MessageBuilder.js +4405 -0
- package/lib/Utils/MessageBuilder_d.ts +411 -0
- package/lib/Utils/PersistentStore.js +592 -0
- package/lib/Utils/PersistentStore_d.ts +60 -0
- package/lib/Utils/anti-delete.d.ts +74 -0
- package/lib/Utils/anti-delete.js +222 -0
- package/lib/Utils/auth-utils.d.ts +57 -0
- package/lib/Utils/auth-utils.js +307 -0
- package/lib/Utils/auto-reply.d.ts +47 -0
- package/lib/Utils/auto-reply.js +158 -0
- package/lib/Utils/baileys-event-stream.d.ts +8 -0
- package/lib/Utils/baileys-event-stream.js +62 -0
- package/lib/Utils/browser-utils.d.ts +8 -0
- package/lib/Utils/browser-utils.js +28 -0
- package/lib/Utils/business.d.ts +49 -0
- package/lib/Utils/business.js +240 -0
- package/lib/Utils/button-helper-utils.js +314 -0
- package/lib/Utils/button-sender.js +824 -0
- package/lib/Utils/chat-control.d.ts +159 -0
- package/lib/Utils/chat-control.js +232 -0
- package/lib/Utils/chat-history-helpers.d.ts +21 -0
- package/lib/Utils/chat-history-helpers.js +71 -0
- package/lib/Utils/chat-utils.d.ts +407 -0
- package/lib/Utils/chat-utils.js +886 -0
- package/lib/Utils/companion-reg-client-utils.d.ts +4 -0
- package/lib/Utils/companion-reg-client-utils.js +40 -0
- package/lib/Utils/crypto.d.ts +41 -0
- package/lib/Utils/crypto.js +148 -0
- package/lib/Utils/decode-wa-message.d.ts +83 -0
- package/lib/Utils/decode-wa-message.js +317 -0
- package/lib/Utils/event-buffer.d.ts +12 -0
- package/lib/Utils/event-buffer.js +636 -0
- package/lib/Utils/generics.d.ts +69 -0
- package/lib/Utils/generics.js +439 -0
- package/lib/Utils/history.d.ts +90 -0
- package/lib/Utils/history.js +147 -0
- package/lib/Utils/identity-change-handler.d.ts +13 -0
- package/lib/Utils/identity-change-handler.js +50 -0
- package/lib/Utils/index.d.ts +39 -0
- package/lib/Utils/index.js +46 -0
- package/lib/Utils/link-preview.d.ts +12 -0
- package/lib/Utils/link-preview.js +85 -0
- package/lib/Utils/logger.d.ts +2 -0
- package/lib/Utils/logger.js +3 -0
- package/lib/Utils/lt-hash.d.ts +12 -0
- package/lib/Utils/lt-hash.js +27 -0
- package/lib/Utils/make-mutex.d.ts +6 -0
- package/lib/Utils/make-mutex.js +33 -0
- package/lib/Utils/media-messages.d.ts +18 -0
- package/lib/Utils/media-messages.js +71 -0
- package/lib/Utils/media-set.d.ts +13 -0
- package/lib/Utils/media-set.js +172 -0
- package/lib/Utils/message-kind.js +139 -0
- package/lib/Utils/message-retry-manager.d.ts +79 -0
- package/lib/Utils/message-retry-manager.js +265 -0
- package/lib/Utils/message-search.d.ts +44 -0
- package/lib/Utils/message-search.js +189 -0
- package/lib/Utils/messages-media.d.ts +135 -0
- package/lib/Utils/messages-media.js +869 -0
- package/lib/Utils/messages.d.ts +44 -0
- package/lib/Utils/messages.js +2155 -0
- package/lib/Utils/noise-handler.d.ts +20 -0
- package/lib/Utils/noise-handler.js +201 -0
- package/lib/Utils/offline-node-processor.d.ts +9 -0
- package/lib/Utils/offline-node-processor.js +40 -0
- package/lib/Utils/past-participants.d.ts +14 -0
- package/lib/Utils/past-participants.js +40 -0
- package/lib/Utils/pre-key-manager.d.ts +25 -0
- package/lib/Utils/pre-key-manager.js +106 -0
- package/lib/Utils/process-message.d.ts +82 -0
- package/lib/Utils/process-message.js +809 -0
- package/lib/Utils/reporting-utils.d.ts +12 -0
- package/lib/Utils/reporting-utils.js +258 -0
- package/lib/Utils/rich-message-utils.d.ts +48 -0
- package/lib/Utils/rich-message-utils.js +445 -0
- package/lib/Utils/scheduling.d.ts +42 -0
- package/lib/Utils/scheduling.js +140 -0
- package/lib/Utils/signal.d.ts +82 -0
- package/lib/Utils/signal.js +201 -0
- package/lib/Utils/stanza-ack.d.ts +16 -0
- package/lib/Utils/stanza-ack.js +38 -0
- package/lib/Utils/status.d.ts +50 -0
- package/lib/Utils/status.js +108 -0
- package/lib/Utils/stickerpack.d.ts +51 -0
- package/lib/Utils/stickerpack.js +275 -0
- package/lib/Utils/sync-action-utils.d.ts +2 -0
- package/lib/Utils/sync-action-utils.js +49 -0
- package/lib/Utils/tc-token-utils.d.ts +29 -0
- package/lib/Utils/tc-token-utils.js +163 -0
- package/lib/Utils/templates.d.ts +76 -0
- package/lib/Utils/templates.js +151 -0
- package/lib/Utils/use-cache-manager-auth-state.d.ts +13 -0
- package/lib/Utils/use-cache-manager-auth-state.js +82 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts +10 -0
- package/lib/Utils/use-multi-file-auth-state.js +167 -0
- package/lib/Utils/use-single-file-auth-state.d.ts +10 -0
- package/lib/Utils/use-single-file-auth-state.js +114 -0
- package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
- package/lib/Utils/use-sqlite-auth-state.js +170 -0
- package/lib/Utils/validate-connection.d.ts +42 -0
- package/lib/Utils/validate-connection.js +199 -0
- package/lib/Utils/vcard.d.ts +58 -0
- package/lib/Utils/vcard.js +105 -0
- package/lib/VoIP/audio-feeder.d.ts +15 -0
- package/lib/VoIP/audio-feeder.js +132 -0
- package/lib/VoIP/index.js +277 -0
- package/lib/VoIP/relay-transport.d.ts +43 -0
- package/lib/VoIP/relay-transport.js +559 -0
- package/lib/VoIP/signaling.js +624 -0
- package/lib/VoIP/types.d.ts +69 -0
- package/lib/VoIP/types.js +17 -0
- package/lib/VoIP/wasm-engine.d.ts +103 -0
- package/lib/VoIP/wasm-engine.js +1214 -0
- package/lib/VoIP/worker-bootstrap.js +1042 -0
- package/lib/WABinary/constants.d.ts +61 -0
- package/lib/WABinary/constants.js +1467 -0
- package/lib/WABinary/decode.d.ts +9 -0
- package/lib/WABinary/decode.js +262 -0
- package/lib/WABinary/encode.d.ts +2 -0
- package/lib/WABinary/encode.js +220 -0
- package/lib/WABinary/generic-utils.d.ts +74 -0
- package/lib/WABinary/generic-utils.js +277 -0
- package/lib/WABinary/index.d.ts +5 -0
- package/lib/WABinary/index.js +6 -0
- package/lib/WABinary/jid-utils.d.ts +28 -0
- package/lib/WABinary/jid-utils.js +96 -0
- package/lib/WABinary/types.d.ts +19 -0
- package/lib/WABinary/types.js +2 -0
- package/lib/WAM/BinaryInfo.d.ts +7 -0
- package/lib/WAM/BinaryInfo.js +10 -0
- package/lib/WAM/constants.d.ts +34926 -0
- package/lib/WAM/constants.js +22853 -0
- package/lib/WAM/encode.d.ts +1 -0
- package/lib/WAM/encode.js +150 -0
- package/lib/WAM/index.d.ts +3 -0
- package/lib/WAM/index.js +4 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +36 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +52 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +29 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +63 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +38 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +9 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +38 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +51 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +14 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +29 -0
- package/lib/WAUSync/Protocols/index.d.ts +7 -0
- package/lib/WAUSync/Protocols/index.js +8 -0
- package/lib/WAUSync/USyncQuery.d.ts +20 -0
- package/lib/WAUSync/USyncQuery.js +122 -0
- package/lib/WAUSync/USyncUser.d.ts +16 -0
- package/lib/WAUSync/USyncUser.js +31 -0
- package/lib/WAUSync/index.d.ts +3 -0
- package/lib/WAUSync/index.js +4 -0
- package/lib/assets/wasm/loader.js +5 -0
- package/lib/assets/wasm/whatsapp.wasm +0 -0
- package/lib/assets/wasm/worker-modules.js +273 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +20 -0
- package/package.json +175 -0
- package/postinstall-banner.js +56 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { mkdir, readFile, stat, unlink, writeFile } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { proto } from '../../WAProto/index.js';
|
|
4
|
+
import { initAuthCreds } from './auth-utils.js';
|
|
5
|
+
import { BufferJSON } from './generics.js';
|
|
6
|
+
async function loadBetterSqlite3() {
|
|
7
|
+
try {
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
|
+
const mod = (await import('better-sqlite3'));
|
|
10
|
+
return mod.default ?? mod;
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
const helpful = new Error('`better-sqlite3` is required for `useSqliteAuthState`. Install it as a peer dependency: `npm install better-sqlite3` (or `yarn add better-sqlite3`).');
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
helpful.cause = err;
|
|
16
|
+
throw helpful;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const CREDS_ROW_KEY = '__creds__';
|
|
20
|
+
const CREATE_SCHEMA_SQL = `
|
|
21
|
+
CREATE TABLE IF NOT EXISTS creds (
|
|
22
|
+
key TEXT PRIMARY KEY,
|
|
23
|
+
value TEXT NOT NULL
|
|
24
|
+
);
|
|
25
|
+
CREATE TABLE IF NOT EXISTS signal_keys (
|
|
26
|
+
type TEXT NOT NULL,
|
|
27
|
+
id TEXT NOT NULL,
|
|
28
|
+
value TEXT NOT NULL,
|
|
29
|
+
PRIMARY KEY (type, id)
|
|
30
|
+
);
|
|
31
|
+
CREATE INDEX IF NOT EXISTS signal_keys_type_idx ON signal_keys(type);
|
|
32
|
+
`;
|
|
33
|
+
// Vanz@Add 29-08-26 --- Migration tracking, ported in spirit from zapo-js's
|
|
34
|
+
// wa_migrations pattern (packages/store-sqlite/src/migrations.ts). Each entry
|
|
35
|
+
// is `{ id, sql }`; applied migrations are recorded by id in `wa_migrations`
|
|
36
|
+
// so `db.exec(...)` schema changes are only ever run once per database file,
|
|
37
|
+
// letting future releases evolve the schema without a manual ALTER step from
|
|
38
|
+
// the user. Kept as an ordered array (not a folder of files) since the schema
|
|
39
|
+
// here is a single flat file, unlike zapo's per-domain migration modules.
|
|
40
|
+
const MIGRATIONS = [
|
|
41
|
+
{ id: '0001_init', sql: CREATE_SCHEMA_SQL }
|
|
42
|
+
];
|
|
43
|
+
function ensureMigrationsTable(db) {
|
|
44
|
+
db.exec('CREATE TABLE IF NOT EXISTS wa_migrations (id TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)');
|
|
45
|
+
}
|
|
46
|
+
function runMigrations(db) {
|
|
47
|
+
ensureMigrationsTable(db);
|
|
48
|
+
const applied = new Set(db.prepare('SELECT id FROM wa_migrations').all().map((r) => r.id));
|
|
49
|
+
const insertMigration = db.prepare('INSERT INTO wa_migrations (id, applied_at) VALUES (?, ?)');
|
|
50
|
+
for (const migration of MIGRATIONS) {
|
|
51
|
+
if (applied.has(migration.id))
|
|
52
|
+
continue;
|
|
53
|
+
const tx = db.transaction(() => {
|
|
54
|
+
db.exec(migration.sql);
|
|
55
|
+
insertMigration.run(migration.id, Date.now());
|
|
56
|
+
});
|
|
57
|
+
tx();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export async function useSqliteAuthState(opts) {
|
|
61
|
+
let db;
|
|
62
|
+
if (opts.database) {
|
|
63
|
+
db = opts.database;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const Database = await loadBetterSqlite3();
|
|
67
|
+
db = new Database(opts.dbPath);
|
|
68
|
+
}
|
|
69
|
+
// WAL mode allows concurrent reads alongside a single writer; matches
|
|
70
|
+
// what SQLite recommends for read-heavy workloads with sporadic writes.
|
|
71
|
+
db.pragma('journal_mode = WAL');
|
|
72
|
+
db.pragma('synchronous = NORMAL');
|
|
73
|
+
runMigrations(db);
|
|
74
|
+
// Vanz@Fix (bug 8): periodic WAL checkpoint + cleanup old signal keys to prevent DB bloat.
|
|
75
|
+
// Runs every 30 minutes. WAL checkpoint reclaims WAL file space; key cleanup removes stale session entries.
|
|
76
|
+
const _walCleanupInterval = setInterval(() => {
|
|
77
|
+
try {
|
|
78
|
+
db.pragma('wal_checkpoint(PASSIVE)');
|
|
79
|
+
// Remove signal keys older than 30 days (pre-keys, session keys that have expired)
|
|
80
|
+
// Only removes types that are safe to prune (not creds or app-state-sync-key)
|
|
81
|
+
const pruneTypes = ['pre-key', 'session'];
|
|
82
|
+
for (const type of pruneTypes) {
|
|
83
|
+
try {
|
|
84
|
+
// Keep last 500 per type to avoid breaking active sessions
|
|
85
|
+
db.prepare(`
|
|
86
|
+
DELETE FROM signal_keys WHERE type = ? AND id NOT IN (
|
|
87
|
+
SELECT id FROM signal_keys WHERE type = ? ORDER BY rowid DESC LIMIT 500
|
|
88
|
+
)
|
|
89
|
+
`).run(type, type);
|
|
90
|
+
} catch { /* ignore per-type errors */ }
|
|
91
|
+
}
|
|
92
|
+
} catch { /* ignore checkpoint errors — non-fatal */ }
|
|
93
|
+
}, 30 * 60 * 1000);
|
|
94
|
+
// Allow Node process to exit even if interval is still running
|
|
95
|
+
if (_walCleanupInterval.unref) _walCleanupInterval.unref();
|
|
96
|
+
const stmts = {
|
|
97
|
+
credsSelect: db.prepare('SELECT value FROM creds WHERE key = ?'),
|
|
98
|
+
credsUpsert: db.prepare('INSERT INTO creds (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value'),
|
|
99
|
+
keySelect: db.prepare('SELECT value FROM signal_keys WHERE type = ? AND id = ?'),
|
|
100
|
+
keyUpsert: db.prepare('INSERT INTO signal_keys (type, id, value) VALUES (?, ?, ?) ON CONFLICT(type, id) DO UPDATE SET value = excluded.value'),
|
|
101
|
+
keyDelete: db.prepare('DELETE FROM signal_keys WHERE type = ? AND id = ?'),
|
|
102
|
+
keyListIds: db.prepare('SELECT id FROM signal_keys WHERE type = ?'),
|
|
103
|
+
keyList: db.prepare('SELECT id, value FROM signal_keys WHERE type = ?'),
|
|
104
|
+
clearKeys: db.prepare('DELETE FROM signal_keys')
|
|
105
|
+
};
|
|
106
|
+
const loadCreds = () => {
|
|
107
|
+
const row = stmts.credsSelect.get(CREDS_ROW_KEY);
|
|
108
|
+
if (!row)
|
|
109
|
+
return initAuthCreds();
|
|
110
|
+
return JSON.parse(row.value, BufferJSON.reviver);
|
|
111
|
+
};
|
|
112
|
+
const persistCreds = (creds) => {
|
|
113
|
+
stmts.credsUpsert.run(CREDS_ROW_KEY, JSON.stringify(creds, BufferJSON.replacer));
|
|
114
|
+
};
|
|
115
|
+
const creds = loadCreds();
|
|
116
|
+
return {
|
|
117
|
+
state: {
|
|
118
|
+
creds,
|
|
119
|
+
keys: {
|
|
120
|
+
get: async (type, ids) => {
|
|
121
|
+
const data = {};
|
|
122
|
+
for (const id of ids) {
|
|
123
|
+
const row = stmts.keySelect.get(type, id);
|
|
124
|
+
if (row) {
|
|
125
|
+
let value = JSON.parse(row.value, BufferJSON.reviver);
|
|
126
|
+
if (type === 'app-state-sync-key' && value) {
|
|
127
|
+
value = proto.Message.AppStateSyncKeyData.fromObject(value);
|
|
128
|
+
}
|
|
129
|
+
data[id] = value;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return data;
|
|
133
|
+
},
|
|
134
|
+
set: async (data) => {
|
|
135
|
+
const writeTx = db.transaction(() => {
|
|
136
|
+
for (const category in data) {
|
|
137
|
+
for (const id in data[category]) {
|
|
138
|
+
const value = data[category][id];
|
|
139
|
+
if (value) {
|
|
140
|
+
const stringified = JSON.stringify(value, BufferJSON.replacer);
|
|
141
|
+
stmts.keyUpsert.run(category, id, stringified);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
stmts.keyDelete.run(category, id);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
writeTx();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
saveCreds: async () => {
|
|
154
|
+
persistCreds(creds);
|
|
155
|
+
},
|
|
156
|
+
// Vanz@Fix: release the WAL cleanup interval and (if we opened it ourselves)
|
|
157
|
+
// the underlying db handle. Without this, every useSqliteAuthState() call
|
|
158
|
+
// (e.g. re-pairing / rotating sessions) leaked a timer + open sqlite fd forever.
|
|
159
|
+
close: async () => {
|
|
160
|
+
clearInterval(_walCleanupInterval);
|
|
161
|
+
if (!opts.database) {
|
|
162
|
+
try {
|
|
163
|
+
db.close();
|
|
164
|
+
}
|
|
165
|
+
catch { /* already closed */ }
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=use-sqlite-auth-state.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export function generateLoginNode(userJid: any, config: any): any;
|
|
2
|
+
export function generateRegistrationNode({ registrationId, signedPreKey, signedIdentityKey }: {
|
|
3
|
+
registrationId: any;
|
|
4
|
+
signedPreKey: any;
|
|
5
|
+
signedIdentityKey: any;
|
|
6
|
+
}, config: any): any;
|
|
7
|
+
export function configureSuccessfulPairing(stanza: any, { advSecretKey, signedIdentityKey, signalIdentities }: {
|
|
8
|
+
advSecretKey: any;
|
|
9
|
+
signedIdentityKey: any;
|
|
10
|
+
signalIdentities: any;
|
|
11
|
+
}): {
|
|
12
|
+
creds: {
|
|
13
|
+
account: any;
|
|
14
|
+
me: {
|
|
15
|
+
id: any;
|
|
16
|
+
name: any;
|
|
17
|
+
lid: any;
|
|
18
|
+
};
|
|
19
|
+
signalIdentities: any[];
|
|
20
|
+
platform: any;
|
|
21
|
+
};
|
|
22
|
+
reply: {
|
|
23
|
+
tag: string;
|
|
24
|
+
attrs: {
|
|
25
|
+
to: string;
|
|
26
|
+
type: string;
|
|
27
|
+
id: any;
|
|
28
|
+
};
|
|
29
|
+
content: {
|
|
30
|
+
tag: string;
|
|
31
|
+
attrs: {};
|
|
32
|
+
content: {
|
|
33
|
+
tag: string;
|
|
34
|
+
attrs: {
|
|
35
|
+
'key-index': any;
|
|
36
|
+
};
|
|
37
|
+
content: any;
|
|
38
|
+
}[];
|
|
39
|
+
}[];
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export function encodeSignedDeviceIdentity(account: any, includeSignatureKey: any): any;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
import { proto } from '../../WAProto/index.js';
|
|
4
|
+
import { KEY_BUNDLE_TYPE, WA_ADV_ACCOUNT_SIG_PREFIX, WA_ADV_DEVICE_SIG_PREFIX, WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX, COMPANION_DEVICE_VERSION } from '../Defaults/index.js';
|
|
5
|
+
import { getBinaryNodeChild, jidDecode, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
6
|
+
import { Curve, hmacSign } from './crypto.js';
|
|
7
|
+
import { encodeBigEndian } from './generics.js';
|
|
8
|
+
import { createSignalIdentity } from './signal.js';
|
|
9
|
+
const getUserAgent = (config) => {
|
|
10
|
+
return {
|
|
11
|
+
appVersion: {
|
|
12
|
+
primary: config.version[0],
|
|
13
|
+
secondary: config.version[1],
|
|
14
|
+
tertiary: config.version[2]
|
|
15
|
+
},
|
|
16
|
+
platform: proto.ClientPayload.UserAgent.Platform.WEB,
|
|
17
|
+
releaseChannel: proto.ClientPayload.UserAgent.ReleaseChannel.RELEASE,
|
|
18
|
+
osVersion: '0.1',
|
|
19
|
+
device: 'Desktop',
|
|
20
|
+
osBuildNumber: '0.1',
|
|
21
|
+
localeLanguageIso6391: 'en',
|
|
22
|
+
mnc: '000',
|
|
23
|
+
mcc: '000',
|
|
24
|
+
localeCountryIso31661Alpha2: config.countryCode
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
const PLATFORM_MAP = {
|
|
28
|
+
'Mac OS': proto.ClientPayload.WebInfo.WebSubPlatform.DARWIN,
|
|
29
|
+
Windows: proto.ClientPayload.WebInfo.WebSubPlatform.WIN32
|
|
30
|
+
};
|
|
31
|
+
const getWebInfo = (config) => {
|
|
32
|
+
let webSubPlatform = proto.ClientPayload.WebInfo.WebSubPlatform.WEB_BROWSER;
|
|
33
|
+
if (config.syncFullHistory &&
|
|
34
|
+
PLATFORM_MAP[config.browser[0]] &&
|
|
35
|
+
config.browser[1] === 'Desktop') {
|
|
36
|
+
webSubPlatform = PLATFORM_MAP[config.browser[0]];
|
|
37
|
+
}
|
|
38
|
+
return { webSubPlatform };
|
|
39
|
+
};
|
|
40
|
+
const getClientPayload = (config) => {
|
|
41
|
+
const payload = {
|
|
42
|
+
connectType: proto.ClientPayload.ConnectType.WIFI_UNKNOWN,
|
|
43
|
+
connectReason: proto.ClientPayload.ConnectReason.USER_ACTIVATED,
|
|
44
|
+
userAgent: getUserAgent(config)
|
|
45
|
+
};
|
|
46
|
+
payload.webInfo = getWebInfo(config);
|
|
47
|
+
if (config.pushName) {
|
|
48
|
+
payload.pushName = config.pushName;
|
|
49
|
+
}
|
|
50
|
+
return payload;
|
|
51
|
+
};
|
|
52
|
+
export const generateLoginNode = (userJid, config) => {
|
|
53
|
+
const { user, device } = jidDecode(userJid);
|
|
54
|
+
const payload = {
|
|
55
|
+
...getClientPayload(config),
|
|
56
|
+
passive: true,
|
|
57
|
+
pull: true,
|
|
58
|
+
username: +user,
|
|
59
|
+
device: device,
|
|
60
|
+
// Vanz@Fix (bug 49): was hardcoded false — now reads from config.lidDbMigrated (default false until investigated)
|
|
61
|
+
lidDbMigrated: config.lidDbMigrated ?? false
|
|
62
|
+
};
|
|
63
|
+
return proto.ClientPayload.fromObject(payload);
|
|
64
|
+
};
|
|
65
|
+
const getPlatformType = (platform) => {
|
|
66
|
+
const platformType = platform.toUpperCase();
|
|
67
|
+
return (proto.DeviceProps.PlatformType[platformType] ||
|
|
68
|
+
proto.DeviceProps.PlatformType.CHROME);
|
|
69
|
+
};
|
|
70
|
+
export const generateRegistrationNode = ({ registrationId, signedPreKey, signedIdentityKey }, config) => {
|
|
71
|
+
// the app version needs to be md5 hashed
|
|
72
|
+
// and passed in
|
|
73
|
+
const appVersionBuf = createHash('md5')
|
|
74
|
+
.update(config.version.join('.')) // join as string
|
|
75
|
+
.digest();
|
|
76
|
+
const companion = {
|
|
77
|
+
os: config.browser[0],
|
|
78
|
+
platformType: getPlatformType(config.browser[1]),
|
|
79
|
+
requireFullSync: config.syncFullHistory,
|
|
80
|
+
historySyncConfig: {
|
|
81
|
+
storageQuotaMb: 10240,
|
|
82
|
+
inlineInitialPayloadInE2EeMsg: true,
|
|
83
|
+
recentSyncDaysLimit: undefined,
|
|
84
|
+
supportCallLogHistory: false,
|
|
85
|
+
supportBotUserAgentChatHistory: true,
|
|
86
|
+
supportCagReactionsAndPolls: true,
|
|
87
|
+
supportBizHostedMsg: true,
|
|
88
|
+
supportRecentSyncChunkMessageCountTuning: true,
|
|
89
|
+
supportHostedGroupMsg: true,
|
|
90
|
+
supportFbidBotChatHistory: true,
|
|
91
|
+
supportAddOnHistorySyncMigration: undefined,
|
|
92
|
+
supportMessageAssociation: true,
|
|
93
|
+
supportGroupHistory: false,
|
|
94
|
+
onDemandReady: undefined,
|
|
95
|
+
supportGuestChat: undefined
|
|
96
|
+
},
|
|
97
|
+
version: COMPANION_DEVICE_VERSION
|
|
98
|
+
};
|
|
99
|
+
const companionProto = proto.DeviceProps.encode(companion).finish();
|
|
100
|
+
const registerPayload = {
|
|
101
|
+
...getClientPayload(config),
|
|
102
|
+
passive: false,
|
|
103
|
+
pull: false,
|
|
104
|
+
devicePairingData: {
|
|
105
|
+
buildHash: appVersionBuf,
|
|
106
|
+
deviceProps: companionProto,
|
|
107
|
+
eRegid: encodeBigEndian(registrationId),
|
|
108
|
+
eKeytype: KEY_BUNDLE_TYPE,
|
|
109
|
+
eIdent: signedIdentityKey.public,
|
|
110
|
+
eSkeyId: encodeBigEndian(signedPreKey.keyId, 3),
|
|
111
|
+
eSkeyVal: signedPreKey.keyPair.public,
|
|
112
|
+
eSkeySig: signedPreKey.signature
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
return proto.ClientPayload.fromObject(registerPayload);
|
|
116
|
+
};
|
|
117
|
+
export const configureSuccessfulPairing = (stanza, { advSecretKey, signedIdentityKey, signalIdentities }) => {
|
|
118
|
+
const msgId = stanza.attrs.id;
|
|
119
|
+
const pairSuccessNode = getBinaryNodeChild(stanza, 'pair-success');
|
|
120
|
+
const deviceIdentityNode = getBinaryNodeChild(pairSuccessNode, 'device-identity');
|
|
121
|
+
const platformNode = getBinaryNodeChild(pairSuccessNode, 'platform');
|
|
122
|
+
const deviceNode = getBinaryNodeChild(pairSuccessNode, 'device');
|
|
123
|
+
const businessNode = getBinaryNodeChild(pairSuccessNode, 'biz');
|
|
124
|
+
if (!deviceIdentityNode || !deviceNode) {
|
|
125
|
+
throw new Boom('Missing device-identity or device in pair success node', { data: stanza });
|
|
126
|
+
}
|
|
127
|
+
const bizName = businessNode?.attrs.name;
|
|
128
|
+
const jid = deviceNode.attrs.jid;
|
|
129
|
+
const lid = deviceNode.attrs.lid;
|
|
130
|
+
const { details, hmac, accountType } = proto.ADVSignedDeviceIdentityHMAC.decode(deviceIdentityNode.content);
|
|
131
|
+
let hmacPrefix = Buffer.from([]);
|
|
132
|
+
if (accountType !== undefined && accountType === proto.ADVEncryptionType.HOSTED) {
|
|
133
|
+
hmacPrefix = WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX;
|
|
134
|
+
}
|
|
135
|
+
const advSign = hmacSign(Buffer.concat([hmacPrefix, details]), Buffer.from(advSecretKey, 'base64'));
|
|
136
|
+
if (Buffer.compare(hmac, advSign) !== 0) {
|
|
137
|
+
throw new Boom('Invalid account signature');
|
|
138
|
+
}
|
|
139
|
+
const account = proto.ADVSignedDeviceIdentity.decode(details);
|
|
140
|
+
const { accountSignatureKey, accountSignature, details: deviceDetails } = account;
|
|
141
|
+
const deviceIdentity = proto.ADVDeviceIdentity.decode(deviceDetails);
|
|
142
|
+
const accountSignaturePrefix = deviceIdentity.deviceType === proto.ADVEncryptionType.HOSTED
|
|
143
|
+
? WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX
|
|
144
|
+
: WA_ADV_ACCOUNT_SIG_PREFIX;
|
|
145
|
+
const accountMsg = Buffer.concat([accountSignaturePrefix, deviceDetails, signedIdentityKey.public]);
|
|
146
|
+
if (!Curve.verify(accountSignatureKey, accountMsg, accountSignature)) {
|
|
147
|
+
throw new Boom('Failed to verify account signature');
|
|
148
|
+
}
|
|
149
|
+
const deviceMsg = Buffer.concat([
|
|
150
|
+
WA_ADV_DEVICE_SIG_PREFIX,
|
|
151
|
+
deviceDetails,
|
|
152
|
+
signedIdentityKey.public,
|
|
153
|
+
accountSignatureKey
|
|
154
|
+
]);
|
|
155
|
+
account.deviceSignature = Curve.sign(signedIdentityKey.private, deviceMsg);
|
|
156
|
+
const identity = createSignalIdentity(lid, accountSignatureKey);
|
|
157
|
+
const accountEnc = encodeSignedDeviceIdentity(account, false);
|
|
158
|
+
const reply = {
|
|
159
|
+
tag: 'iq',
|
|
160
|
+
attrs: {
|
|
161
|
+
to: S_WHATSAPP_NET,
|
|
162
|
+
type: 'result',
|
|
163
|
+
id: msgId
|
|
164
|
+
},
|
|
165
|
+
content: [
|
|
166
|
+
{
|
|
167
|
+
tag: 'pair-device-sign',
|
|
168
|
+
attrs: {},
|
|
169
|
+
content: [
|
|
170
|
+
{
|
|
171
|
+
tag: 'device-identity',
|
|
172
|
+
attrs: { 'key-index': deviceIdentity.keyIndex.toString() },
|
|
173
|
+
content: accountEnc
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
};
|
|
179
|
+
const authUpdate = {
|
|
180
|
+
account,
|
|
181
|
+
me: { id: jid, name: bizName, lid },
|
|
182
|
+
signalIdentities: [...(signalIdentities || []), identity],
|
|
183
|
+
platform: platformNode?.attrs.name
|
|
184
|
+
};
|
|
185
|
+
return {
|
|
186
|
+
creds: authUpdate,
|
|
187
|
+
reply
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
export const encodeSignedDeviceIdentity = (account, includeSignatureKey) => {
|
|
191
|
+
account = { ...account };
|
|
192
|
+
// set to null if we are not to include the signature key
|
|
193
|
+
// or if we are including the signature key but it is empty
|
|
194
|
+
if (!includeSignatureKey || !account.accountSignatureKey?.length) {
|
|
195
|
+
account.accountSignatureKey = null;
|
|
196
|
+
}
|
|
197
|
+
return proto.ADVSignedDeviceIdentity.encode(account).finish();
|
|
198
|
+
};
|
|
199
|
+
//# sourceMappingURL=validate-connection.js.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export interface ContactPhone {
|
|
2
|
+
number: string;
|
|
3
|
+
type?: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ContactEmail {
|
|
7
|
+
email: string;
|
|
8
|
+
type?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ContactUrl {
|
|
11
|
+
url: string;
|
|
12
|
+
type?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ContactAddress {
|
|
15
|
+
street?: string;
|
|
16
|
+
city?: string;
|
|
17
|
+
state?: string;
|
|
18
|
+
postalCode?: string;
|
|
19
|
+
country?: string;
|
|
20
|
+
type?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ContactData {
|
|
23
|
+
fullName: string;
|
|
24
|
+
displayName?: string;
|
|
25
|
+
organization?: string;
|
|
26
|
+
title?: string;
|
|
27
|
+
phones?: ContactPhone[];
|
|
28
|
+
emails?: ContactEmail[];
|
|
29
|
+
urls?: ContactUrl[];
|
|
30
|
+
addresses?: ContactAddress[];
|
|
31
|
+
birthday?: string;
|
|
32
|
+
note?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare const escapeVCard: (s: string) => string;
|
|
35
|
+
export declare const formatPhone: (p: string) => string;
|
|
36
|
+
export declare const generateVCard: (c: ContactData) => string;
|
|
37
|
+
export declare const generateVCards: (contacts: ContactData[]) => string;
|
|
38
|
+
export declare const parseVCard: (vcard: string) => Partial<ContactData>;
|
|
39
|
+
export declare const createContactCard: (contact: ContactData) => {
|
|
40
|
+
contacts: {
|
|
41
|
+
displayName: string;
|
|
42
|
+
contacts: {
|
|
43
|
+
vcard: string;
|
|
44
|
+
}[];
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export declare const createContactCards: (contacts: ContactData[]) => {
|
|
48
|
+
contacts: {
|
|
49
|
+
displayName: string;
|
|
50
|
+
contacts: {
|
|
51
|
+
vcard: string;
|
|
52
|
+
}[];
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
export declare const quickContact: (name: string, phone: string, options?: {
|
|
56
|
+
organization?: string;
|
|
57
|
+
email?: string;
|
|
58
|
+
}) => ContactData;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Vanz@Add --- ported from Bail-master addons/vcard.ts (type-only
|
|
2
|
+
// annotations dropped; behavior unchanged).
|
|
3
|
+
export const escapeVCard = (s) => s.replace(/\\/g, '\\\\').replace(/;/g, '\\;').replace(/,/g, '\\,').replace(/\n/g, '\\n');
|
|
4
|
+
// Vanz@Fix 30-08-26 --- the old inline unescape used for FN/ORG/TITLE,
|
|
5
|
+
// `value.replace(/\\([;,n\\])/g, '$1')`, mishandled the `\n` case: it matched
|
|
6
|
+
// the backslash + literal "n" produced by escapeVCard's `\n` escape, then
|
|
7
|
+
// substituted back just the captured "n" character instead of a real newline
|
|
8
|
+
// (`$1` is literally the char "n", not the escape sequence). So a name/org/
|
|
9
|
+
// title containing a real newline round-tripped as "n" inserted in place of
|
|
10
|
+
// the line break instead of the original newline. NOTE already unescaped
|
|
11
|
+
// `\n` correctly on its own, separately. This single helper now reverses
|
|
12
|
+
// every escape escapeVCard() produces (backslash, semicolon, comma, newline)
|
|
13
|
+
// the same correct way, and is reused for all four fields below.
|
|
14
|
+
export const unescapeVCard = (s) => s.replace(/\\(.)/g, (_, ch) => (ch === 'n' ? '\n' : ch));
|
|
15
|
+
export const formatPhone = (p) => p.replace(/[^\d+]/g, '');
|
|
16
|
+
/** Build a VCARD 3.0 string from structured contact data. */
|
|
17
|
+
export const generateVCard = (c) => {
|
|
18
|
+
const lines = ['BEGIN:VCARD', 'VERSION:3.0', `FN:${escapeVCard(c.fullName)}`];
|
|
19
|
+
const parts = c.fullName.split(' ');
|
|
20
|
+
if (parts.length >= 2) {
|
|
21
|
+
const last = parts[parts.length - 1] || '';
|
|
22
|
+
const first = parts.slice(0, -1).join(' ');
|
|
23
|
+
lines.push(`N:${escapeVCard(last)};${escapeVCard(first)};;;`);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
lines.push(`N:${escapeVCard(c.fullName)};;;;`);
|
|
27
|
+
}
|
|
28
|
+
if (c.organization)
|
|
29
|
+
lines.push(`ORG:${escapeVCard(c.organization)}`);
|
|
30
|
+
if (c.title)
|
|
31
|
+
lines.push(`TITLE:${escapeVCard(c.title)}`);
|
|
32
|
+
for (const p of c.phones ?? []) {
|
|
33
|
+
const t = p.type || 'CELL';
|
|
34
|
+
const n = formatPhone(p.number);
|
|
35
|
+
lines.push(p.label ? `TEL;type=${t};type=VOICE;X-ABLabel=${escapeVCard(p.label)}:${n}` : `TEL;type=${t};type=VOICE:${n}`);
|
|
36
|
+
}
|
|
37
|
+
for (const e of c.emails ?? [])
|
|
38
|
+
lines.push(`EMAIL;type=${e.type || 'OTHER'}:${e.email}`);
|
|
39
|
+
for (const u of c.urls ?? [])
|
|
40
|
+
lines.push(`URL;type=${u.type || 'OTHER'}:${u.url}`);
|
|
41
|
+
for (const a of c.addresses ?? []) {
|
|
42
|
+
const t = a.type || 'OTHER';
|
|
43
|
+
const parts = ['', '', a.street || '', a.city || '', a.state || '', a.postalCode || '', a.country || ''].map((v) => escapeVCard(v));
|
|
44
|
+
lines.push(`ADR;type=${t}:${parts.join(';')}`);
|
|
45
|
+
}
|
|
46
|
+
if (c.birthday)
|
|
47
|
+
lines.push(`BDAY:${c.birthday}`);
|
|
48
|
+
if (c.note)
|
|
49
|
+
lines.push(`NOTE:${escapeVCard(c.note)}`);
|
|
50
|
+
lines.push('END:VCARD');
|
|
51
|
+
return lines.join('\r\n');
|
|
52
|
+
};
|
|
53
|
+
export const generateVCards = (contacts) => contacts.map(generateVCard).join('\r\n');
|
|
54
|
+
/** Parse a subset of VCARD fields back into structured data. */
|
|
55
|
+
export const parseVCard = (vcard) => {
|
|
56
|
+
const contact = {};
|
|
57
|
+
for (const line of vcard.split(/\r?\n/)) {
|
|
58
|
+
const [key, ...vp] = line.split(':');
|
|
59
|
+
if (!key)
|
|
60
|
+
continue;
|
|
61
|
+
const value = vp.join(':');
|
|
62
|
+
if (key.startsWith('FN'))
|
|
63
|
+
contact.fullName = unescapeVCard(value);
|
|
64
|
+
else if (key.startsWith('ORG'))
|
|
65
|
+
contact.organization = unescapeVCard(value);
|
|
66
|
+
else if (key.startsWith('TITLE'))
|
|
67
|
+
contact.title = unescapeVCard(value);
|
|
68
|
+
else if (key.startsWith('TEL')) {
|
|
69
|
+
contact.phones = contact.phones || [];
|
|
70
|
+
const tm = key.match(/type=(\w+)/i);
|
|
71
|
+
contact.phones.push({ number: value, type: tm?.[1]?.toUpperCase() || 'CELL' });
|
|
72
|
+
}
|
|
73
|
+
else if (key.startsWith('EMAIL')) {
|
|
74
|
+
contact.emails = contact.emails || [];
|
|
75
|
+
const tm = key.match(/type=(\w+)/i);
|
|
76
|
+
contact.emails.push({ email: value, type: tm?.[1]?.toUpperCase() || 'OTHER' });
|
|
77
|
+
}
|
|
78
|
+
else if (key.startsWith('BDAY'))
|
|
79
|
+
contact.birthday = value;
|
|
80
|
+
else if (key.startsWith('NOTE'))
|
|
81
|
+
contact.note = unescapeVCard(value);
|
|
82
|
+
}
|
|
83
|
+
return contact;
|
|
84
|
+
};
|
|
85
|
+
/** Ready-to-send `contacts` message content for a single contact. */
|
|
86
|
+
export const createContactCard = (contact) => ({
|
|
87
|
+
contacts: {
|
|
88
|
+
displayName: contact.displayName || contact.fullName,
|
|
89
|
+
contacts: [{ vcard: generateVCard(contact) }]
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
/** Ready-to-send `contacts` message content for multiple contacts. */
|
|
93
|
+
export const createContactCards = (contacts) => ({
|
|
94
|
+
contacts: {
|
|
95
|
+
displayName: contacts.length === 1 ? contacts[0]?.displayName || contacts[0]?.fullName || '' : `${contacts.length} Contacts`,
|
|
96
|
+
contacts: contacts.map((c) => ({ vcard: generateVCard(c) }))
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
export const quickContact = (name, phone, options) => ({
|
|
100
|
+
fullName: name,
|
|
101
|
+
phones: [{ number: phone, type: 'CELL' }],
|
|
102
|
+
organization: options?.organization,
|
|
103
|
+
emails: options?.email ? [{ email: options.email, type: 'WORK' }] : undefined
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=vcard.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class AudioFeeder {
|
|
2
|
+
#private;
|
|
3
|
+
private readonly sampleRate;
|
|
4
|
+
private readonly channels;
|
|
5
|
+
private readonly framesPerChunk;
|
|
6
|
+
private readonly onChunk;
|
|
7
|
+
private readonly source;
|
|
8
|
+
droppedChunks: number;
|
|
9
|
+
underflowChunks: number;
|
|
10
|
+
bytesProduced: number;
|
|
11
|
+
chunksEmitted: number;
|
|
12
|
+
constructor(sampleRate: number, channels: number, framesPerChunk: number, onChunk: (chunk: Float32Array) => void, source?: string);
|
|
13
|
+
start: () => void;
|
|
14
|
+
stop: () => void;
|
|
15
|
+
}
|