@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,151 @@
|
|
|
1
|
+
// Vanz@Add --- ported from Bail-master addons/templates.ts (type-only
|
|
2
|
+
// annotations dropped; behavior unchanged).
|
|
3
|
+
export class TemplateManager {
|
|
4
|
+
templates = new Map();
|
|
5
|
+
generateId() {
|
|
6
|
+
return `tpl_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
7
|
+
}
|
|
8
|
+
extractVariables(content) {
|
|
9
|
+
const regex = /\{\{(\w+)(?::([^}]*))?\}\}/g;
|
|
10
|
+
const variables = [];
|
|
11
|
+
const seen = new Set();
|
|
12
|
+
let match;
|
|
13
|
+
while ((match = regex.exec(content)) !== null) {
|
|
14
|
+
const name = match[1];
|
|
15
|
+
if (!name || seen.has(name))
|
|
16
|
+
continue;
|
|
17
|
+
seen.add(name);
|
|
18
|
+
variables.push({ name, defaultValue: match[2], required: !match[2] });
|
|
19
|
+
}
|
|
20
|
+
return variables;
|
|
21
|
+
}
|
|
22
|
+
create(options) {
|
|
23
|
+
const template = {
|
|
24
|
+
id: options.id ?? this.generateId(),
|
|
25
|
+
name: options.name,
|
|
26
|
+
content: options.content,
|
|
27
|
+
description: options.description,
|
|
28
|
+
category: options.category,
|
|
29
|
+
variables: this.extractVariables(options.content),
|
|
30
|
+
createdAt: new Date(),
|
|
31
|
+
updatedAt: new Date()
|
|
32
|
+
};
|
|
33
|
+
this.templates.set(template.id, template);
|
|
34
|
+
return template;
|
|
35
|
+
}
|
|
36
|
+
get(id) {
|
|
37
|
+
return this.templates.get(id);
|
|
38
|
+
}
|
|
39
|
+
getByName(name) {
|
|
40
|
+
return Array.from(this.templates.values()).find((t) => t.name === name);
|
|
41
|
+
}
|
|
42
|
+
getAll() {
|
|
43
|
+
return Array.from(this.templates.values());
|
|
44
|
+
}
|
|
45
|
+
getByCategory(category) {
|
|
46
|
+
return Array.from(this.templates.values()).filter((t) => t.category === category);
|
|
47
|
+
}
|
|
48
|
+
update(id, updates) {
|
|
49
|
+
const template = this.templates.get(id);
|
|
50
|
+
if (!template)
|
|
51
|
+
return undefined;
|
|
52
|
+
if (updates.content)
|
|
53
|
+
updates.variables = this.extractVariables(updates.content);
|
|
54
|
+
const updated = { ...template, ...updates, updatedAt: new Date() };
|
|
55
|
+
this.templates.set(id, updated);
|
|
56
|
+
return updated;
|
|
57
|
+
}
|
|
58
|
+
delete(id) {
|
|
59
|
+
return this.templates.delete(id);
|
|
60
|
+
}
|
|
61
|
+
renderContent(content, data = {}) {
|
|
62
|
+
return content.replace(/\{\{(\w+)(?::([^}]*))?\}\}/g, (match, name, defaultValue) => {
|
|
63
|
+
const value = data[name];
|
|
64
|
+
if (value !== undefined && value !== null)
|
|
65
|
+
return String(value);
|
|
66
|
+
if (defaultValue !== undefined)
|
|
67
|
+
return defaultValue;
|
|
68
|
+
return match;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
render(id, data = {}) {
|
|
72
|
+
const template = this.templates.get(id);
|
|
73
|
+
if (!template)
|
|
74
|
+
throw new Error(`Template not found: ${id}`);
|
|
75
|
+
return this.renderContent(template.content, data);
|
|
76
|
+
}
|
|
77
|
+
validate(id, data) {
|
|
78
|
+
const template = this.templates.get(id);
|
|
79
|
+
if (!template)
|
|
80
|
+
throw new Error(`Template not found: ${id}`);
|
|
81
|
+
const missing = template.variables.filter((v) => v.required && !(v.name in data)).map((v) => v.name);
|
|
82
|
+
return { valid: missing.length === 0, missing };
|
|
83
|
+
}
|
|
84
|
+
export() {
|
|
85
|
+
return JSON.stringify(Array.from(this.templates.values()), null, 2);
|
|
86
|
+
}
|
|
87
|
+
import(json, overwrite = false) {
|
|
88
|
+
const templates = JSON.parse(json);
|
|
89
|
+
let imported = 0;
|
|
90
|
+
for (const t of templates) {
|
|
91
|
+
if (!overwrite && this.templates.has(t.id))
|
|
92
|
+
continue;
|
|
93
|
+
this.templates.set(t.id, { ...t, createdAt: new Date(t.createdAt), updatedAt: new Date(t.updatedAt) });
|
|
94
|
+
imported++;
|
|
95
|
+
}
|
|
96
|
+
return imported;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** Ready-made templates covering common bot scenarios (order, welcome, reminder, etc). */
|
|
100
|
+
export const PRESET_TEMPLATES = {
|
|
101
|
+
ORDER_CONFIRMATION: {
|
|
102
|
+
name: 'Order Confirmation',
|
|
103
|
+
category: 'order',
|
|
104
|
+
content: `✅ *Order Confirmed!*\n\nOrder ID: #{{orderId}}\nCustomer: {{customerName}}\nDate: {{orderDate}}\n\n📦 *Items:*\n{{items}}\n\n💰 *Total: {{total}}*\n\nThank you! 🙏`
|
|
105
|
+
},
|
|
106
|
+
WELCOME: {
|
|
107
|
+
name: 'Welcome Message',
|
|
108
|
+
category: 'greeting',
|
|
109
|
+
content: `👋 *Welcome, {{name}}!*\n\nThank you for joining {{companyName:us}}!\nNeed help? Reply to this message!`
|
|
110
|
+
},
|
|
111
|
+
REMINDER: {
|
|
112
|
+
name: 'Reminder',
|
|
113
|
+
category: 'notification',
|
|
114
|
+
content: `⏰ *Reminder*\n\nHi {{name}},\n\n📋 {{subject}}\n📅 Date: {{date}}\n🕐 Time: {{time}}\n📍 Location: {{location:TBD}}`
|
|
115
|
+
},
|
|
116
|
+
SUPPORT_TICKET: {
|
|
117
|
+
name: 'Support Ticket',
|
|
118
|
+
category: 'support',
|
|
119
|
+
content: `🎫 *Support Ticket Created*\n\nTicket #: {{ticketId}}\nSubject: {{subject}}\n\nHi {{name}},\n\nWe received your request! Response time: {{responseTime:24 hours}} 🙏`
|
|
120
|
+
},
|
|
121
|
+
BIRTHDAY: {
|
|
122
|
+
name: 'Birthday Wishes',
|
|
123
|
+
category: 'greeting',
|
|
124
|
+
content: `🎂 *Happy Birthday, {{name}}!* 🎉\n\nWishing you a wonderful day!\n\n🎁 Use code: {{code}} for {{discount:10}}% off! 🥳`
|
|
125
|
+
},
|
|
126
|
+
INVOICE: {
|
|
127
|
+
name: 'Invoice',
|
|
128
|
+
category: 'invoice',
|
|
129
|
+
content: `🧾 *Invoice {{invoiceNumber}}*\n\nBilled to: {{customerName}}\nInvoice date: {{invoiceDate}}\nDue date: {{dueDate:on receipt}}\n\n📋 *Items:*\n{{items}}\n\nSubtotal: {{subtotal}}\n💰 *Total: {{total}}*\n\nThank you for your business! 🙏`
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
export const createTemplateManager = (includePresets = true) => {
|
|
133
|
+
const manager = new TemplateManager();
|
|
134
|
+
if (includePresets) {
|
|
135
|
+
for (const [key, template] of Object.entries(PRESET_TEMPLATES)) {
|
|
136
|
+
manager.create({ ...template, id: key.toLowerCase() });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return manager;
|
|
140
|
+
};
|
|
141
|
+
export const renderTemplate = (content, data = {}) => {
|
|
142
|
+
return content.replace(/\{\{(\w+)(?::([^}]*))?\}\}/g, (match, name, defaultValue) => {
|
|
143
|
+
const value = data[name];
|
|
144
|
+
if (value !== undefined && value !== null)
|
|
145
|
+
return String(value);
|
|
146
|
+
if (defaultValue !== undefined)
|
|
147
|
+
return defaultValue;
|
|
148
|
+
return match;
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AuthenticationState } from '../Types/index.js';
|
|
2
|
+
/** Minimal interface compatible with any cache-manager v5 store (Redis, Memcached, keyv, @cacheable/node-cache, etc). */
|
|
3
|
+
export type CacheManagerStore = {
|
|
4
|
+
set(key: string, value: string, ttl?: number): Promise<void>;
|
|
5
|
+
get(key: string): Promise<string | undefined | null>;
|
|
6
|
+
del(key: string): Promise<void>;
|
|
7
|
+
keys(pattern?: string): Promise<string[]>;
|
|
8
|
+
};
|
|
9
|
+
export declare const useCacheManagerAuthState: (store: CacheManagerStore, sessionKey: string) => Promise<{
|
|
10
|
+
state: AuthenticationState;
|
|
11
|
+
saveCreds: () => Promise<void>;
|
|
12
|
+
clearState: () => Promise<void>;
|
|
13
|
+
}>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Ported from @queenanya/baileys `addons/use-cache-manager-auth-state.ts`
|
|
2
|
+
// (that fork credits it to `@innovatorssoft/baileys` make-cache-manager-store.js).
|
|
3
|
+
// Adjustments for @vanzxy/baileys: import paths rewired to this fork's
|
|
4
|
+
// Utils layout (auth-utils.js / generics.js), otherwise logic-for-logic
|
|
5
|
+
// identical to the original — including the 2-year TTL on `creds` and the
|
|
6
|
+
// `sessionKey*` wildcard sweep in `clearState()`.
|
|
7
|
+
//
|
|
8
|
+
// Store interface required (matches any cache-manager v5-compatible store,
|
|
9
|
+
// e.g. Redis/Memcached/keyv, or this fork's own @cacheable/node-cache dep):
|
|
10
|
+
// store.get(key) -> string | undefined | null
|
|
11
|
+
// store.set(key, value, ttl?) -> void
|
|
12
|
+
// store.del(key) -> void
|
|
13
|
+
// store.keys(pattern?) -> string[] (used by clearState() for the wildcard sweep)
|
|
14
|
+
import { proto } from '../../WAProto/index.js';
|
|
15
|
+
import { initAuthCreds } from './auth-utils.js';
|
|
16
|
+
import { BufferJSON } from './generics.js';
|
|
17
|
+
|
|
18
|
+
export const useCacheManagerAuthState = async (store, sessionKey) => {
|
|
19
|
+
const defaultKey = (file) => `${sessionKey}:${file}`;
|
|
20
|
+
const writeData = async (file, data) => {
|
|
21
|
+
const ttl = file === 'creds' ? 63115200 : undefined; // 2 years for creds
|
|
22
|
+
await store.set(defaultKey(file), JSON.stringify(data, BufferJSON.replacer), ttl);
|
|
23
|
+
};
|
|
24
|
+
const readData = async (file) => {
|
|
25
|
+
try {
|
|
26
|
+
const data = await store.get(defaultKey(file));
|
|
27
|
+
return data !== null && data !== undefined ? JSON.parse(data, BufferJSON.reviver) : null;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const removeData = async (file) => {
|
|
34
|
+
try {
|
|
35
|
+
await store.del(defaultKey(file));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
console.error(`[useCacheManagerAuthState] Error removing ${file} from session ${sessionKey}`);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const clearState = async () => {
|
|
42
|
+
try {
|
|
43
|
+
const keys = await store.keys(`${sessionKey}*`);
|
|
44
|
+
await Promise.all(keys.map((key) => store.del(key)));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// best-effort — not every store backend supports pattern listing
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const creds = (await readData('creds')) || initAuthCreds();
|
|
51
|
+
return {
|
|
52
|
+
clearState,
|
|
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 = proto.Message.AppStateSyncKeyData.fromObject(value);
|
|
62
|
+
}
|
|
63
|
+
data[id] = value;
|
|
64
|
+
}));
|
|
65
|
+
return data;
|
|
66
|
+
},
|
|
67
|
+
set: async (data) => {
|
|
68
|
+
const tasks = [];
|
|
69
|
+
for (const category in data) {
|
|
70
|
+
for (const id in data[category]) {
|
|
71
|
+
const value = data[category][id];
|
|
72
|
+
const key = `${category}-${id}`;
|
|
73
|
+
tasks.push(value ? writeData(key, value) : removeData(key));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
await Promise.all(tasks);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
saveCreds: () => writeData('creds', creds)
|
|
81
|
+
};
|
|
82
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { Mutex } from 'async-mutex';
|
|
2
|
+
import { mkdir, readFile, readdir, stat, unlink, writeFile } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { proto } from '../../WAProto/index.js';
|
|
5
|
+
import { initAuthCreds } from './auth-utils.js';
|
|
6
|
+
import { BufferJSON } from './generics.js';
|
|
7
|
+
// We need to lock files due to the fact that we are using async functions to read and write files
|
|
8
|
+
// https://github.com/WhiskeySockets/Baileys/issues/794
|
|
9
|
+
// https://github.com/nodejs/node/issues/26338
|
|
10
|
+
// Use a Map to store mutexes for each file path
|
|
11
|
+
const fileLocks = new Map();
|
|
12
|
+
// Get or create a mutex for a specific file path
|
|
13
|
+
const getFileLock = (path) => {
|
|
14
|
+
let mutex = fileLocks.get(path);
|
|
15
|
+
if (!mutex) {
|
|
16
|
+
mutex = new Mutex();
|
|
17
|
+
fileLocks.set(path, mutex);
|
|
18
|
+
}
|
|
19
|
+
return mutex;
|
|
20
|
+
};
|
|
21
|
+
// Vanz@Fix 25-08-26 (ENOSPC guard) --- useMultiFileAuthState writes one small file PER key id
|
|
22
|
+
// (session-*, sender-key-*, sender-key-memory-*, pre-key-*, app-state-sync-key-*, ...) and never
|
|
23
|
+
// prunes any of them on its own. Over months of uptime — especially in busy groups, where a
|
|
24
|
+
// sender-key-memory file is created per (group, participant) pair — this silently accumulates into
|
|
25
|
+
// hundreds of thousands of tiny files. That can hit the filesystem's inode/file-count ceiling and
|
|
26
|
+
// start throwing ENOSPC on writes long before disk *space* usage looks anywhere near full (a
|
|
27
|
+
// classic symptom: panel shows plenty of free MiB/GiB, but writes still fail with ENOSPC). When
|
|
28
|
+
// that happens mid-session, auth writes (including the app-state-sync key from the "App state key
|
|
29
|
+
// not present!" issue) fail silently and never actually persist.
|
|
30
|
+
//
|
|
31
|
+
// `sender-key-memory-*` entries are pure dedup/anti-replay cache — safe to delete anytime; Baileys
|
|
32
|
+
// regenerates them on demand with zero functional loss (worst case: one redundant re-decrypt). They
|
|
33
|
+
// also tend to be the single biggest contributor to file count in active groups, so they're the
|
|
34
|
+
// safest and highest-impact thing to prune automatically. Everything else (creds, real sessions,
|
|
35
|
+
// pre-keys, app-state-sync-keys) is left completely untouched — this never touches those.
|
|
36
|
+
export const pruneStaleAuthFiles = async (folder, { maxAgeDays = 14, categories = ['sender-key-memory'], dryRun = false } = {}) => {
|
|
37
|
+
let entries;
|
|
38
|
+
try {
|
|
39
|
+
entries = await readdir(folder);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return { scanned: 0, removed: 0 };
|
|
43
|
+
}
|
|
44
|
+
const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1000;
|
|
45
|
+
let scanned = 0;
|
|
46
|
+
let removed = 0;
|
|
47
|
+
await Promise.all(entries.map(async (name) => {
|
|
48
|
+
if (!categories.some((cat) => name.startsWith(`${cat}-`) && name.endsWith('.json'))) return;
|
|
49
|
+
scanned++;
|
|
50
|
+
const filePath = join(folder, name);
|
|
51
|
+
try {
|
|
52
|
+
const info = await stat(filePath);
|
|
53
|
+
if (info.mtimeMs < cutoff) {
|
|
54
|
+
if (!dryRun) await unlink(filePath).catch(() => { });
|
|
55
|
+
removed++;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// file vanished between readdir and stat — fine, nothing to prune
|
|
60
|
+
}
|
|
61
|
+
}));
|
|
62
|
+
return { scanned, removed };
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* stores the full authentication state in a single folder.
|
|
66
|
+
* Far more efficient than singlefileauthstate
|
|
67
|
+
*
|
|
68
|
+
* Again, I wouldn't endorse this for any production level use other than perhaps a bot.
|
|
69
|
+
* Would recommend writing an auth state for use with a proper SQL or No-SQL DB
|
|
70
|
+
* */
|
|
71
|
+
export const useMultiFileAuthState = async (folder) => {
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
+
const writeData = async (data, file) => {
|
|
74
|
+
const filePath = join(folder, fixFileName(file));
|
|
75
|
+
const mutex = getFileLock(filePath);
|
|
76
|
+
return mutex.acquire().then(async (release) => {
|
|
77
|
+
try {
|
|
78
|
+
await writeFile(filePath, JSON.stringify(data, BufferJSON.replacer));
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
release();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
const readData = async (file) => {
|
|
86
|
+
try {
|
|
87
|
+
const filePath = join(folder, fixFileName(file));
|
|
88
|
+
const mutex = getFileLock(filePath);
|
|
89
|
+
return await mutex.acquire().then(async (release) => {
|
|
90
|
+
try {
|
|
91
|
+
const data = await readFile(filePath, { encoding: 'utf-8' });
|
|
92
|
+
return JSON.parse(data, BufferJSON.reviver);
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
release();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const removeData = async (file) => {
|
|
104
|
+
try {
|
|
105
|
+
const filePath = join(folder, fixFileName(file));
|
|
106
|
+
const mutex = getFileLock(filePath);
|
|
107
|
+
return mutex.acquire().then(async (release) => {
|
|
108
|
+
try {
|
|
109
|
+
await unlink(filePath);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
release();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch { }
|
|
119
|
+
};
|
|
120
|
+
const folderInfo = await stat(folder).catch(() => { });
|
|
121
|
+
if (folderInfo) {
|
|
122
|
+
if (!folderInfo.isDirectory()) {
|
|
123
|
+
throw new Error(`found something that is not a directory at ${folder}, either delete it or specify a different location`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
await mkdir(folder, { recursive: true });
|
|
128
|
+
}
|
|
129
|
+
// Vanz@Fix 25-08-26 (ENOSPC guard) --- best-effort prune on every startup. Failures here must
|
|
130
|
+
// never block auth from loading, so this is intentionally fire-and-forget with its own catch.
|
|
131
|
+
pruneStaleAuthFiles(folder).catch(() => { });
|
|
132
|
+
const fixFileName = (file) => file?.replace(/\//g, '__')?.replace(/:/g, '-');
|
|
133
|
+
const creds = (await readData('creds.json')) || initAuthCreds();
|
|
134
|
+
return {
|
|
135
|
+
state: {
|
|
136
|
+
creds,
|
|
137
|
+
keys: {
|
|
138
|
+
get: async (type, ids) => {
|
|
139
|
+
const data = {};
|
|
140
|
+
await Promise.all(ids.map(async (id) => {
|
|
141
|
+
let value = await readData(`${type}-${id}.json`);
|
|
142
|
+
if (type === 'app-state-sync-key' && value) {
|
|
143
|
+
value = proto.Message.AppStateSyncKeyData.fromObject(value);
|
|
144
|
+
}
|
|
145
|
+
data[id] = value;
|
|
146
|
+
}));
|
|
147
|
+
return data;
|
|
148
|
+
},
|
|
149
|
+
set: async (data) => {
|
|
150
|
+
const tasks = [];
|
|
151
|
+
for (const category in data) {
|
|
152
|
+
for (const id in data[category]) {
|
|
153
|
+
const value = data[category][id];
|
|
154
|
+
const file = `${category}-${id}.json`;
|
|
155
|
+
tasks.push(value ? writeData(value, file) : removeData(file));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
await Promise.all(tasks);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
saveCreds: async () => {
|
|
163
|
+
return writeData(creds, 'creds.json');
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
//# sourceMappingURL=use-multi-file-auth-state.js.map
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { readFile, rename, stat, writeFile } from 'fs/promises';
|
|
2
|
+
import { DEFAULT_CACHE_TTLS } from '../Defaults/index.js';
|
|
3
|
+
import { proto } from '../../WAProto/index.js';
|
|
4
|
+
import { initAuthCreds } from './auth-utils.js';
|
|
5
|
+
import { BufferJSON } from './generics.js';
|
|
6
|
+
import { LRUCache } from 'lru-cache';
|
|
7
|
+
import { Mutex } from 'async-mutex';
|
|
8
|
+
import defaultLogger from './logger.js';
|
|
9
|
+
// Lia@Changes 25-03-26 --- Add useSingleFileAuthState with integrated cache
|
|
10
|
+
const FLUSH_TIMEOUT_MS = 3000;
|
|
11
|
+
// Lia@Changes 22-04-26 --- Enhanced useSingleFileAuthState with LRUCache
|
|
12
|
+
export const useSingleFileAuthState = async (fileName) => {
|
|
13
|
+
const cache = new LRUCache({
|
|
14
|
+
max: 20000,
|
|
15
|
+
ttl: 1000 * DEFAULT_CACHE_TTLS.SIGNAL_STORE,
|
|
16
|
+
updateAgeOnGet: false,
|
|
17
|
+
updateAgeOnHas: false,
|
|
18
|
+
ttlAutopurge: true
|
|
19
|
+
});
|
|
20
|
+
// Lia@Changes 26-04-26 --- Add mutex for prevent race condition
|
|
21
|
+
const mutex = new Mutex();
|
|
22
|
+
let fileData = {};
|
|
23
|
+
let isLoaded = false;
|
|
24
|
+
let flushTimeout = null;
|
|
25
|
+
const loadKey = async () => {
|
|
26
|
+
return await mutex.runExclusive(async () => {
|
|
27
|
+
if (isLoaded)
|
|
28
|
+
return;
|
|
29
|
+
try {
|
|
30
|
+
const data = JSON.parse(await readFile(fileName, 'utf-8'), BufferJSON.reviver);
|
|
31
|
+
fileData = data || {};
|
|
32
|
+
for (const [keyName, value] of Object.entries(fileData)) {
|
|
33
|
+
cache.set(keyName, value);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
fileData = {};
|
|
38
|
+
}
|
|
39
|
+
isLoaded = true;
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
const flushKey = () => {
|
|
43
|
+
if (flushTimeout)
|
|
44
|
+
return;
|
|
45
|
+
flushTimeout = setTimeout(async () => {
|
|
46
|
+
flushTimeout = null;
|
|
47
|
+
await mutex.runExclusive(async () => {
|
|
48
|
+
try {
|
|
49
|
+
const tempFile = fileName + '.temp';
|
|
50
|
+
await writeFile(tempFile, JSON.stringify(fileData, BufferJSON.replacer));
|
|
51
|
+
await rename(tempFile, fileName);
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
// Vanz@Fix (bug 58): was silently swallowed — auth session could fail
|
|
55
|
+
// to persist (disk full, permission error, etc.) with zero trace.
|
|
56
|
+
defaultLogger.error({ err, fileName }, 'failed to flush auth state to disk');
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}, FLUSH_TIMEOUT_MS);
|
|
60
|
+
};
|
|
61
|
+
const writeKey = (keyName, value) => {
|
|
62
|
+
cache.set(keyName, value);
|
|
63
|
+
fileData[keyName] = value;
|
|
64
|
+
flushKey();
|
|
65
|
+
};
|
|
66
|
+
const removeKey = (keyName) => {
|
|
67
|
+
cache.delete(keyName);
|
|
68
|
+
delete fileData[keyName];
|
|
69
|
+
flushKey();
|
|
70
|
+
};
|
|
71
|
+
const fileInfo = await stat(fileName).catch(() => null);
|
|
72
|
+
if (!fileInfo) {
|
|
73
|
+
await writeFile(fileName, '{}');
|
|
74
|
+
}
|
|
75
|
+
else if (!fileInfo.isFile()) {
|
|
76
|
+
throw new Error(`found something that is not a file at ${fileName}, either delete it or specify a different location`);
|
|
77
|
+
}
|
|
78
|
+
await loadKey();
|
|
79
|
+
const creds = fileData['creds'] || initAuthCreds();
|
|
80
|
+
return {
|
|
81
|
+
state: {
|
|
82
|
+
creds,
|
|
83
|
+
keys: {
|
|
84
|
+
get: (type, ids) => {
|
|
85
|
+
const data = {};
|
|
86
|
+
for (const id of ids) {
|
|
87
|
+
const keyName = type + id;
|
|
88
|
+
let value = cache.get(keyName);
|
|
89
|
+
if (value === undefined && fileData[keyName] !== undefined) {
|
|
90
|
+
value = fileData[keyName];
|
|
91
|
+
cache.set(keyName, value);
|
|
92
|
+
}
|
|
93
|
+
if (type === 'app-state-sync-key' && value) {
|
|
94
|
+
value = proto.Message.AppStateSyncKeyData.fromObject(value);
|
|
95
|
+
}
|
|
96
|
+
data[id] = value;
|
|
97
|
+
}
|
|
98
|
+
return data;
|
|
99
|
+
},
|
|
100
|
+
set: (data) => {
|
|
101
|
+
for (const category in data) {
|
|
102
|
+
for (const id in data[category]) {
|
|
103
|
+
const keyName = category + id;
|
|
104
|
+
const value = data[category][id];
|
|
105
|
+
value ? writeKey(keyName, value) : removeKey(keyName);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
saveCreds: () => writeKey('creds', creds)
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=use-single-file-auth-state.js.map
|