@manybot/manybot 5.1.0 → 5.2.1

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.
Files changed (51) hide show
  1. package/README.md +5 -7
  2. package/dist/client/banner.js +35 -0
  3. package/dist/client/store.js +135 -0
  4. package/dist/config.js +363 -0
  5. package/dist/core/adapter.js +12 -0
  6. package/dist/core/capabilities.js +16 -0
  7. package/dist/core/types.js +6 -0
  8. package/dist/download/queue.js +49 -0
  9. package/dist/drivers/index.js +14 -0
  10. package/dist/drivers/patches/index.js +9 -0
  11. package/dist/drivers/patches/libsignal.js +16 -0
  12. package/dist/drivers/patches/patch.js +1 -0
  13. package/dist/drivers/whatsapp/adapter.js +7 -0
  14. package/dist/drivers/whatsapp/api/index.js +1311 -0
  15. package/dist/drivers/whatsapp/index.js +164 -0
  16. package/dist/drivers/whatsapp/loginPrompt.js +81 -0
  17. package/dist/drivers/whatsapp/messageHandler.js +111 -0
  18. package/dist/drivers/whatsapp/sdk/baileysSock.js +124 -0
  19. package/dist/i18n/index.js +202 -0
  20. package/dist/kernel/pluginApi.js +11 -0
  21. package/dist/kernel/pluginGuard.js +88 -0
  22. package/dist/kernel/pluginLoader.js +322 -0
  23. package/dist/kernel/scheduler.js +110 -0
  24. package/dist/kernel/sendGuard.js +121 -0
  25. package/dist/kernel/settingsDb.js +205 -0
  26. package/{src → dist}/locales/en.json +18 -33
  27. package/dist/locales/es.json +52 -0
  28. package/{src → dist}/locales/pt.json +18 -34
  29. package/dist/logger/logger.js +16 -0
  30. package/dist/main.js +82 -0
  31. package/dist/types.js +16 -0
  32. package/{src → dist}/utils/file.js +3 -3
  33. package/package.json +35 -26
  34. package/src/client/banner.js +0 -57
  35. package/src/client/whatsappClient.js +0 -185
  36. package/src/config.js +0 -288
  37. package/src/download/queue.js +0 -55
  38. package/src/i18n/index.js +0 -235
  39. package/src/kernel/messageHandler.js +0 -88
  40. package/src/kernel/pluginApi.js +0 -630
  41. package/src/kernel/pluginGuard.js +0 -78
  42. package/src/kernel/pluginLoader.js +0 -177
  43. package/src/kernel/pluginState.js +0 -99
  44. package/src/kernel/scheduler.js +0 -48
  45. package/src/kernel/sendGuard.js +0 -166
  46. package/src/locales/es.json +0 -62
  47. package/src/logger/logger.js +0 -32
  48. package/src/main.js +0 -136
  49. package/src/utils/getChatId.js +0 -3
  50. package/src/utils/get_id.js +0 -177
  51. package/src/utils/pluginI18n.js +0 -129
package/src/i18n/index.js DELETED
@@ -1,235 +0,0 @@
1
- /**
2
- * i18n/index.js
3
- *
4
- * Internationalization system for ManyBot.
5
- * Loads translations based on LANGUAGE configuration.
6
- * Fallback is always English (en).
7
- *
8
- * Plugins can use createPluginT() to have isolated i18n.
9
- */
10
-
11
- import fs from "fs";
12
- import path from "path";
13
- import { fileURLToPath } from "url";
14
- import { CONFIG } from "#config";
15
-
16
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
- const LOCALES_DIR = path.join(__dirname, "..", "locales");
18
-
19
- // Default language (fallback)
20
- const DEFAULT_LANG = "en";
21
-
22
- // Cache of loaded translations
23
- const translations = new Map();
24
-
25
- /**
26
- * Loads a translation JSON file
27
- * @param {string} lang - language code (en, pt, es)
28
- * @returns {object|null}
29
- */
30
- function loadLocale(lang) {
31
- if (translations.has(lang)) {
32
- return translations.get(lang);
33
- }
34
-
35
- const filePath = path.join(LOCALES_DIR, `${lang}.json`);
36
-
37
- try {
38
- if (!fs.existsSync(filePath)) {
39
- return null;
40
- }
41
- const content = fs.readFileSync(filePath, "utf8");
42
- const data = JSON.parse(content);
43
- translations.set(lang, data);
44
- return data;
45
- } catch (err) {
46
- console.error(`[i18n] Failed to load locale ${lang}:`, err.message);
47
- return null;
48
- }
49
- }
50
-
51
- /**
52
- * Gets configured language or default
53
- * @returns {string}
54
- */
55
- function getConfiguredLang() {
56
- const lang = CONFIG.LANGUAGE?.trim().toLowerCase();
57
- if (!lang) return DEFAULT_LANG;
58
-
59
- // Check if file exists
60
- const filePath = path.join(LOCALES_DIR, `${lang}.json`);
61
- if (!fs.existsSync(filePath)) {
62
- console.warn(`[i18n] Language "${lang}" not found, falling back to "${DEFAULT_LANG}"`);
63
- return DEFAULT_LANG;
64
- }
65
-
66
- return lang;
67
- }
68
-
69
- // Load languages
70
- const currentLang = getConfiguredLang();
71
- const currentTranslations = loadLocale(currentLang) || {};
72
- const fallbackTranslations = loadLocale(DEFAULT_LANG) || {};
73
-
74
- /**
75
- * Gets a nested value from an object using dot path
76
- * @param {object} obj
77
- * @param {string} key - path like "system.connected"
78
- * @returns {string|undefined}
79
- */
80
- function getNestedValue(obj, key) {
81
- const parts = key.split(".");
82
- let current = obj;
83
-
84
- for (const part of parts) {
85
- if (current === null || current === undefined || typeof current !== "object") {
86
- return undefined;
87
- }
88
- current = current[part];
89
- }
90
-
91
- return current;
92
- }
93
-
94
- /**
95
- * Replaces placeholders {{key}} with values from context
96
- * @param {string} str
97
- * @param {object} context
98
- * @returns {string}
99
- */
100
- function interpolate(str, context = {}) {
101
- return str.replace(/\{\{(\w+)\}\}/g, (match, key) => {
102
- return context[key] !== undefined ? String(context[key]) : match;
103
- });
104
- }
105
-
106
- /**
107
- * Main translation function
108
- * @param {string} key - translation key (e.g., "system.connected")
109
- * @param {object} context - values to interpolate {{key}}
110
- * @returns {string}
111
- */
112
- export function t(key, context = {}) {
113
- // Try current language first
114
- let value = getNestedValue(currentTranslations, key);
115
-
116
- // Fallback to English if not found
117
- if (value === undefined) {
118
- value = getNestedValue(fallbackTranslations, key);
119
- }
120
-
121
- // If still not found, return the key
122
- if (value === undefined) {
123
- return key;
124
- }
125
-
126
- // If not string, convert
127
- if (typeof value !== "string") {
128
- return String(value);
129
- }
130
-
131
- // Interpolate values
132
- return interpolate(value, context);
133
- }
134
-
135
- /**
136
- * Creates an isolated translation function for a plugin.
137
- * Plugins should have their own locale/ folder with en.json, es.json, etc.
138
- *
139
- * Usage in plugin:
140
- * import { createPluginT } from "../../i18n/index.js";
141
- * const { t } = createPluginT(import.meta.url);
142
- *
143
- * Folder structure:
144
- * myPlugin/
145
- * index.js
146
- * locale/
147
- * en.json
148
- * es.json
149
- * pt.json
150
- *
151
- * @param {string} pluginMetaUrl - import.meta.url from the plugin
152
- * @returns {{ t: Function, lang: string }}
153
- */
154
- export function createPluginT(pluginMetaUrl) {
155
- const pluginDir = path.dirname(fileURLToPath(pluginMetaUrl));
156
- const pluginLocaleDir = path.join(pluginDir, "locale");
157
-
158
- // Get bot's configured language
159
- const targetLang = currentLang;
160
-
161
- // Load plugin translations
162
- let pluginTranslations = {};
163
- let pluginFallback = {};
164
-
165
- try {
166
- // Try to load the configured language
167
- const targetPath = path.join(pluginLocaleDir, `${targetLang}.json`);
168
- if (fs.existsSync(targetPath)) {
169
- pluginTranslations = JSON.parse(fs.readFileSync(targetPath, "utf8"));
170
- }
171
-
172
- // Always load English as fallback
173
- const fallbackPath = path.join(pluginLocaleDir, `${DEFAULT_LANG}.json`);
174
- if (fs.existsSync(fallbackPath)) {
175
- pluginFallback = JSON.parse(fs.readFileSync(fallbackPath, "utf8"));
176
- }
177
- } catch (err) {
178
- // Silent fail - plugin may not have translations
179
- }
180
-
181
- /**
182
- * Plugin-specific translation function
183
- * @param {string} key
184
- * @param {object} context
185
- * @returns {string}
186
- */
187
- function pluginT(key, context = {}) {
188
- // Try plugin's target language first
189
- let value = getNestedValue(pluginTranslations, key);
190
-
191
- // Fallback to plugin's English
192
- if (value === undefined) {
193
- value = getNestedValue(pluginFallback, key);
194
- }
195
-
196
- // If still not found, return the key
197
- if (value === undefined) {
198
- return key;
199
- }
200
-
201
- if (typeof value !== "string") {
202
- return String(value);
203
- }
204
-
205
- return interpolate(value, context);
206
- }
207
-
208
- return { t: pluginT, lang: targetLang };
209
- }
210
-
211
- /**
212
- * Reloads translations (useful for hot-reload)
213
- */
214
- export function reloadTranslations() {
215
- translations.clear();
216
- const lang = getConfiguredLang();
217
- const newTranslations = loadLocale(lang) || {};
218
- const newFallback = loadLocale(DEFAULT_LANG) || {};
219
-
220
- // Update references
221
- Object.assign(currentTranslations, newTranslations);
222
- Object.assign(fallbackTranslations, newFallback);
223
-
224
- console.log(`[i18n] Translations reloaded for language: ${lang}`);
225
- }
226
-
227
- /**
228
- * Returns current language
229
- * @returns {string}
230
- */
231
- export function getCurrentLang() {
232
- return currentLang;
233
- }
234
-
235
- export default { t, createPluginT, reloadTranslations, getCurrentLang };
@@ -1,88 +0,0 @@
1
- /**
2
- * messageHandler.js
3
- *
4
- * Central pipeline for received messages.
5
- *
6
- * Order:
7
- * 1. Filter allowed chats (CHATS from .conf)
8
- * — if CHATS is empty, accepts all chats
9
- * 2. Per-chat incoming debounce (prevents command spam from
10
- * saturating the outbound send queue)
11
- * 3. Log the message
12
- * 4. Pass context to all active plugins
13
- *
14
- * Kernel knows no commands — only distributes.
15
- * Each plugin decides on its own whether to act or ignore.
16
- *
17
- * Per-plugin overrides (via plugin.guardOptions):
18
- * typing {boolean} — set to `false` to skip the typing indicator
19
- * and clearState for this plugin. Useful for
20
- * plugins that reply instantly (e.g. sticker)
21
- * where the typing state only adds latency.
22
- */
23
- import { CHATS } from "#config";
24
- import { getChatId } from "#utils/getChatId";
25
- import { buildApi } from "#manyapi";
26
- import { pluginRegistry } from "#kernel/pluginLoader";
27
- import { runPlugin } from "#kernel/pluginGuard";
28
- import client from "#client/whatsappClient";
29
- import { logger } from "#logger";
30
-
31
- /**
32
- * Minimum ms between processing two messages from the same chat.
33
- * Does NOT drop messages — debounces rapid bursts so plugins
34
- * aren't invoked faster than the send guard can pace their replies.
35
- * Set to 0 to disable.
36
- */
37
- const INCOMING_DEBOUNCE_MS = 300;
38
-
39
- /** chatId → timestamp of last processed message */
40
- const lastProcessedAt = new Map();
41
-
42
- export async function handleMessage(msg) {
43
- const chat = await msg.getChat();
44
- const chatId = getChatId(chat);
45
-
46
- if (CHATS.length > 0 && !CHATS.includes(chatId))
47
- return;
48
-
49
- if (INCOMING_DEBOUNCE_MS > 0) {
50
- const now = Date.now();
51
- const last = lastProcessedAt.get(chatId) ?? 0;
52
- const gap = now - last;
53
- if (gap < INCOMING_DEBOUNCE_MS) {
54
- const wait = INCOMING_DEBOUNCE_MS - gap;
55
- logger.debug(`[messageHandler] ${chatId} delayed ${wait}ms`);
56
- await new Promise(r => setTimeout(r, wait));
57
- }
58
- lastProcessedAt.set(chatId, Date.now());
59
- }
60
-
61
- for (const plugin of pluginRegistry.values()) {
62
- const ctx = buildApi({
63
- msg,
64
- chat,
65
- client,
66
- pluginRegistry,
67
- pluginName: plugin.name,
68
- });
69
-
70
- const useTyping = plugin.guardOptions?.typing !== false;
71
- let typing;
72
-
73
- if (useTyping) {
74
- typing = setInterval(() => chat.sendStateTyping(), 4000);
75
- }
76
-
77
- try {
78
- await runPlugin(plugin, ctx);
79
- } finally {
80
- if (useTyping) {
81
- clearInterval(typing);
82
- try {
83
- await chat.clearState();
84
- } catch {}
85
- }
86
- }
87
- }
88
- }