@prototypevip/baileys 0.1.0 → 0.1.2
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/lib/Defaults/index.js +3 -3
- package/lib/Defaults/index.js.bak-1788476907801 +187 -0
- package/lib/Defaults/index.js.bak-1788479166288 +187 -0
- package/lib/Socket/groups.js.bak-1788476973954 +475 -0
- package/lib/Socket/index.js +42 -126
- package/lib/Socket/index.js.bak-1788479281092 +38 -0
- package/lib/Socket/messages-send.js +88 -51
- package/lib/Store/prototype-store.js +34 -22
- package/lib/Store/prototype-store.js.bak-1788477006895 +983 -0
- package/lib/Utils/index.js +2 -0
- package/lib/Utils/integrity-guard.js +281 -0
- package/lib/Utils/interactive-message-handler.js +28 -8
- package/lib/Utils/interactive-message-handler.js.bak-1788476898661 +478 -0
- package/lib/Utils/socket-guard.js +154 -0
- package/package.json +2 -2
- package/lib/AntiBan/antiban.js +0 -922
- package/lib/AntiBan/banRecoveryOrchestrator.js +0 -284
- package/lib/AntiBan/cli.js +0 -177
- package/lib/AntiBan/contactGraph.js +0 -236
- package/lib/AntiBan/contentVariator.js +0 -150
- package/lib/AntiBan/credsSnapshot.js +0 -121
- package/lib/AntiBan/deliveryTracker.js +0 -107
- package/lib/AntiBan/deviceFingerprint.js +0 -106
- package/lib/AntiBan/fleetEventStore.js +0 -157
- package/lib/AntiBan/groupOperationGuard.js +0 -116
- package/lib/AntiBan/health.js +0 -207
- package/lib/AntiBan/humanEntropy.js +0 -337
- package/lib/AntiBan/index.js +0 -77
- package/lib/AntiBan/instanceCoordinator.js +0 -175
- package/lib/AntiBan/jidCanonicalizer.js +0 -256
- package/lib/AntiBan/jidCircuitBreaker.js +0 -186
- package/lib/AntiBan/legitimacySignalInjector.js +0 -231
- package/lib/AntiBan/lidFirstResolver.js +0 -174
- package/lib/AntiBan/lidResolver.js +0 -324
- package/lib/AntiBan/messageQueue.js +0 -187
- package/lib/AntiBan/messageRecovery.js +0 -283
- package/lib/AntiBan/messageTypeRegistry.js +0 -369
- package/lib/AntiBan/observability.js +0 -145
- package/lib/AntiBan/patch.js +0 -302
- package/lib/AntiBan/persist.js +0 -87
- package/lib/AntiBan/presenceChoreographer.js +0 -430
- package/lib/AntiBan/presets.js +0 -105
- package/lib/AntiBan/profiles.js +0 -31
- package/lib/AntiBan/proxyRotator.js +0 -306
- package/lib/AntiBan/rateLimiter.js +0 -261
- package/lib/AntiBan/readReceiptVariance.js +0 -88
- package/lib/AntiBan/reconnectThrottle.js +0 -180
- package/lib/AntiBan/replyRatio.js +0 -161
- package/lib/AntiBan/reputationVoucher.js +0 -373
- package/lib/AntiBan/retryReason.js +0 -91
- package/lib/AntiBan/retryTracker.js +0 -172
- package/lib/AntiBan/scheduler.js +0 -111
- package/lib/AntiBan/sessionFingerprint.js +0 -248
- package/lib/AntiBan/sessionStability.js +0 -330
- package/lib/AntiBan/stateAdapter.js +0 -73
- package/lib/AntiBan/stateExport.js +0 -152
- package/lib/AntiBan/stealthConnect.js +0 -130
- package/lib/AntiBan/timelockGuard.js +0 -181
- package/lib/AntiBan/topologyThrottler.js +0 -339
- package/lib/AntiBan/warmup.js +0 -140
- package/lib/AntiBan/webhooks.js +0 -80
- package/lib/AntiBan/wrapper.js +0 -456
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Observability — Prometheus metrics export + pluggable structured logging
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* // Logging
|
|
6
|
-
* import { createConsoleLogger } from 'baileys-antiban';
|
|
7
|
-
* const logger = createConsoleLogger('[my-bot]');
|
|
8
|
-
* logger.info('Message sent', { recipient: jid });
|
|
9
|
-
*
|
|
10
|
-
* // Metrics export for Express
|
|
11
|
-
* import { createMetricsHandler } from 'baileys-antiban';
|
|
12
|
-
* const metricsHandler = createMetricsHandler(() => antiban.getStats());
|
|
13
|
-
* app.get('/metrics', metricsHandler.handle);
|
|
14
|
-
*
|
|
15
|
-
* // Periodic push to external system
|
|
16
|
-
* import { createPeriodicExporter } from 'baileys-antiban';
|
|
17
|
-
* const exporter = createPeriodicExporter(() => antiban.getStats(), {
|
|
18
|
-
* intervalMs: 30_000,
|
|
19
|
-
* onMetrics: (text) => pushToVictoriaMetrics(text),
|
|
20
|
-
* });
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* Create a simple console logger with timestamps and prefix
|
|
24
|
-
*/
|
|
25
|
-
export function createConsoleLogger(prefix = '[baileys-antiban]') {
|
|
26
|
-
const format = (level, msg, meta) => {
|
|
27
|
-
const timestamp = new Date().toISOString();
|
|
28
|
-
const metaStr = meta ? ' ' + JSON.stringify(meta) : '';
|
|
29
|
-
return `${timestamp} ${level} ${prefix} ${msg}${metaStr}`;
|
|
30
|
-
};
|
|
31
|
-
return {
|
|
32
|
-
debug: (msg, meta) => console.log(format('DEBUG', msg, meta)),
|
|
33
|
-
info: (msg, meta) => console.log(format('INFO', msg, meta)),
|
|
34
|
-
warn: (msg, meta) => console.warn(format('WARN', msg, meta)),
|
|
35
|
-
error: (msg, meta) => console.error(format('ERROR', msg, meta)),
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Export AntiBan stats as Prometheus text format (exposition format v0.0.4)
|
|
40
|
-
*/
|
|
41
|
-
export function exportPrometheusMetrics(stats, labels) {
|
|
42
|
-
const labelMap = { instance: 'default', ...labels };
|
|
43
|
-
const labelStr = Object.entries(labelMap)
|
|
44
|
-
.map(([k, v]) => `${k}="${v}"`)
|
|
45
|
-
.join(',');
|
|
46
|
-
const lines = [];
|
|
47
|
-
const addMetric = (name, type, help, value) => {
|
|
48
|
-
lines.push(`# HELP ${name} ${help}`);
|
|
49
|
-
lines.push(`# TYPE ${name} ${type}`);
|
|
50
|
-
lines.push(`${name}{${labelStr}} ${value}`);
|
|
51
|
-
};
|
|
52
|
-
// Counters
|
|
53
|
-
addMetric('antiban_messages_allowed_total', 'counter', 'Total messages allowed by AntiBan', stats.messagesAllowed);
|
|
54
|
-
addMetric('antiban_messages_blocked_total', 'counter', 'Total messages blocked by AntiBan', stats.messagesBlocked);
|
|
55
|
-
addMetric('antiban_total_delay_ms_total', 'counter', 'Total delay imposed (milliseconds)', stats.totalDelayMs);
|
|
56
|
-
// Health gauges
|
|
57
|
-
const riskMap = { low: 0, medium: 1, high: 2, critical: 3 };
|
|
58
|
-
addMetric('antiban_health_score', 'gauge', 'Current health score (0=best, 100=worst)', stats.health.score);
|
|
59
|
-
addMetric('antiban_health_risk', 'gauge', 'Risk level encoded as number (0=low, 1=medium, 2=high, 3=critical)', riskMap[stats.health.risk] ?? 0);
|
|
60
|
-
addMetric('antiban_disconnects_last_hour', 'gauge', 'Disconnects in last hour', stats.health.stats.disconnectsLastHour);
|
|
61
|
-
addMetric('antiban_failed_messages_last_hour', 'gauge', 'Failed messages in last hour', stats.health.stats.failedMessagesLastHour);
|
|
62
|
-
addMetric('antiban_uptime_ms', 'gauge', 'Session uptime in milliseconds', stats.health.stats.uptimeMs);
|
|
63
|
-
// Warm-up gauges
|
|
64
|
-
addMetric('antiban_warmup_progress', 'gauge', 'Warm-up progress (0.0 to 1.0)', stats.warmUp.progress);
|
|
65
|
-
addMetric('antiban_warmup_day', 'gauge', 'Current warm-up day', stats.warmUp.day);
|
|
66
|
-
addMetric('antiban_warmup_today_sent', 'gauge', 'Messages sent today during warm-up', stats.warmUp.todaySent);
|
|
67
|
-
addMetric('antiban_warmup_today_limit', 'gauge', 'Message limit for today during warm-up', stats.warmUp.todayLimit);
|
|
68
|
-
// Rate limiter gauges
|
|
69
|
-
addMetric('antiban_rate_last_minute', 'gauge', 'Messages sent in last minute', stats.rateLimiter.lastMinute);
|
|
70
|
-
addMetric('antiban_rate_last_hour', 'gauge', 'Messages sent in last hour', stats.rateLimiter.lastHour);
|
|
71
|
-
addMetric('antiban_rate_last_day', 'gauge', 'Messages sent in last day', stats.rateLimiter.lastDay);
|
|
72
|
-
addMetric('antiban_rate_limit_per_minute', 'gauge', 'Rate limit per minute', stats.rateLimiter.limits.perMinute);
|
|
73
|
-
addMetric('antiban_rate_limit_per_hour', 'gauge', 'Rate limit per hour', stats.rateLimiter.limits.perHour);
|
|
74
|
-
addMetric('antiban_rate_limit_per_day', 'gauge', 'Rate limit per day', stats.rateLimiter.limits.perDay);
|
|
75
|
-
addMetric('antiban_known_chats', 'gauge', 'Number of known chats', stats.rateLimiter.knownChats);
|
|
76
|
-
// Reply ratio gauges (optional)
|
|
77
|
-
if (stats.replyRatio) {
|
|
78
|
-
addMetric('antiban_contacts_on_cooldown', 'gauge', 'Contacts currently on reply cooldown', stats.replyRatio.contactsOnCooldown);
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
addMetric('antiban_contacts_on_cooldown', 'gauge', 'Contacts currently on reply cooldown', 0);
|
|
82
|
-
}
|
|
83
|
-
// Contact graph gauges (optional)
|
|
84
|
-
if (stats.contactGraph) {
|
|
85
|
-
addMetric('antiban_known_contacts', 'gauge', 'Number of known contacts', stats.contactGraph.knownContacts);
|
|
86
|
-
addMetric('antiban_pending_handshakes', 'gauge', 'Pending handshakes', stats.contactGraph.pendingHandshakes);
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
addMetric('antiban_known_contacts', 'gauge', 'Number of known contacts', 0);
|
|
90
|
-
addMetric('antiban_pending_handshakes', 'gauge', 'Pending handshakes', 0);
|
|
91
|
-
}
|
|
92
|
-
// Retry tracker gauges (optional)
|
|
93
|
-
if (stats.retryTracker) {
|
|
94
|
-
addMetric('antiban_retry_spirals', 'gauge', 'Number of retry spirals detected', stats.retryTracker.spiralsDetected);
|
|
95
|
-
addMetric('antiban_active_retries', 'gauge', 'Currently active retries', stats.retryTracker.activeRetries);
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
addMetric('antiban_retry_spirals', 'gauge', 'Number of retry spirals detected', 0);
|
|
99
|
-
addMetric('antiban_active_retries', 'gauge', 'Currently active retries', 0);
|
|
100
|
-
}
|
|
101
|
-
// Reconnect throttle gauges (optional)
|
|
102
|
-
if (stats.reconnectThrottle) {
|
|
103
|
-
addMetric('antiban_reconnect_throttled', 'gauge', 'Whether reconnect is currently throttled (0=no, 1=yes)', stats.reconnectThrottle.isThrottled ? 1 : 0);
|
|
104
|
-
addMetric('antiban_lifetime_reconnects', 'gauge', 'Total reconnects in session lifetime', stats.reconnectThrottle.lifetimeReconnects);
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
addMetric('antiban_reconnect_throttled', 'gauge', 'Whether reconnect is currently throttled (0=no, 1=yes)', 0);
|
|
108
|
-
addMetric('antiban_lifetime_reconnects', 'gauge', 'Total reconnects in session lifetime', 0);
|
|
109
|
-
}
|
|
110
|
-
return lines.join('\n') + '\n';
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Create an HTTP handler for Prometheus metrics (Express/Fastify compatible)
|
|
114
|
-
*/
|
|
115
|
-
export function createMetricsHandler(getStats, labels) {
|
|
116
|
-
return {
|
|
117
|
-
/**
|
|
118
|
-
* HTTP request handler (Express/Fastify compatible)
|
|
119
|
-
*/
|
|
120
|
-
handle: (_req, res) => {
|
|
121
|
-
const metrics = exportPrometheusMetrics(getStats(), labels);
|
|
122
|
-
res.setHeader('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');
|
|
123
|
-
res.end(metrics);
|
|
124
|
-
},
|
|
125
|
-
/**
|
|
126
|
-
* Get metrics as plain text (for non-HTTP usage)
|
|
127
|
-
*/
|
|
128
|
-
text: () => {
|
|
129
|
-
return exportPrometheusMetrics(getStats(), labels);
|
|
130
|
-
},
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Create a periodic metrics exporter that calls onMetrics on an interval
|
|
135
|
-
*/
|
|
136
|
-
export function createPeriodicExporter(getStats, config) {
|
|
137
|
-
const intervalMs = config.intervalMs ?? 30_000;
|
|
138
|
-
const intervalId = setInterval(() => {
|
|
139
|
-
const metrics = exportPrometheusMetrics(getStats(), config.labels);
|
|
140
|
-
config.onMetrics(metrics);
|
|
141
|
-
}, intervalMs);
|
|
142
|
-
return {
|
|
143
|
-
stop: () => clearInterval(intervalId),
|
|
144
|
-
};
|
|
145
|
-
}
|
package/lib/AntiBan/patch.js
DELETED
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* baileys-antiban patch command
|
|
3
|
-
*
|
|
4
|
-
* Patches an installed Baileys package to wrap makeWASocket with antiban middleware.
|
|
5
|
-
* Designed for frameworks (OpenClaw, etc.) that create the socket internally and
|
|
6
|
-
* don't expose a socket:ready hook.
|
|
7
|
-
*
|
|
8
|
-
* Idempotent: safe to re-run after plugin updates. Keeps a .antiban-backup file.
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* npx baileys-antiban patch [--path <baileys-dir>] [--dry-run] [--preset conservative|moderate|aggressive]
|
|
12
|
-
*/
|
|
13
|
-
import * as fs from 'fs';
|
|
14
|
-
import * as path from 'path';
|
|
15
|
-
const PATCH_MARKER_START = '// [BAILEYS-ANTIBAN-PATCH-START]';
|
|
16
|
-
const PATCH_MARKER_END = '// [BAILEYS-ANTIBAN-PATCH-END]';
|
|
17
|
-
function findBaileysDir(candidates) {
|
|
18
|
-
for (const candidate of candidates) {
|
|
19
|
-
if (!candidate)
|
|
20
|
-
continue;
|
|
21
|
-
const pkgPath = path.join(candidate, 'package.json');
|
|
22
|
-
if (fs.existsSync(pkgPath)) {
|
|
23
|
-
try {
|
|
24
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
25
|
-
if (pkg.name === 'baileys' || pkg.name === '@whiskeysockets/baileys' || pkg.name === '@oxidezap/baileyrs') {
|
|
26
|
-
return path.resolve(candidate);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
// not a valid package.json, skip
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
function findMakeWASocketFile(baileyDir) {
|
|
37
|
-
// Ordered by likelihood of containing the actual makeWASocket definition
|
|
38
|
-
const candidates = [
|
|
39
|
-
'lib/socket/index.js',
|
|
40
|
-
'lib/index.js',
|
|
41
|
-
'lib/socket.js',
|
|
42
|
-
'src/socket/index.js',
|
|
43
|
-
'dist/socket/index.js',
|
|
44
|
-
'dist/index.js',
|
|
45
|
-
];
|
|
46
|
-
for (const rel of candidates) {
|
|
47
|
-
const full = path.join(baileyDir, rel);
|
|
48
|
-
if (!fs.existsSync(full))
|
|
49
|
-
continue;
|
|
50
|
-
const source = fs.readFileSync(full, 'utf-8');
|
|
51
|
-
// Look for makeWASocket being defined (not just re-exported via export *)
|
|
52
|
-
if (source.includes('function makeWASocket') ||
|
|
53
|
-
source.includes('const makeWASocket') ||
|
|
54
|
-
source.includes('exports.makeWASocket') ||
|
|
55
|
-
source.includes('makeWASocket =')) {
|
|
56
|
-
const isEsm = source.includes('export function makeWASocket') ||
|
|
57
|
-
source.includes('export const makeWASocket') ||
|
|
58
|
-
source.includes('export {') ||
|
|
59
|
-
source.includes('export default');
|
|
60
|
-
return { file: full, format: isEsm ? 'esm' : 'cjs' };
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// Fallback: search lib/ directory for the defining file
|
|
64
|
-
const libDir = path.join(baileyDir, 'lib');
|
|
65
|
-
if (fs.existsSync(libDir)) {
|
|
66
|
-
const jsFiles = fs
|
|
67
|
-
.readdirSync(libDir, { recursive: true })
|
|
68
|
-
.filter((f) => typeof f === 'string' && f.endsWith('.js'))
|
|
69
|
-
.map((f) => path.join(libDir, f));
|
|
70
|
-
for (const full of jsFiles) {
|
|
71
|
-
try {
|
|
72
|
-
const source = fs.readFileSync(full, 'utf-8');
|
|
73
|
-
if (source.includes('function makeWASocket') && source.includes('makeWASocket')) {
|
|
74
|
-
const isEsm = source.includes('export');
|
|
75
|
-
return { file: full, format: isEsm ? 'esm' : 'cjs' };
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
// skip unreadable files
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
function buildCjsPatch(opts) {
|
|
86
|
-
return `
|
|
87
|
-
${PATCH_MARKER_START}
|
|
88
|
-
// Auto-generated by baileys-antiban patch. Re-run after Baileys/plugin updates.
|
|
89
|
-
(function() {
|
|
90
|
-
try {
|
|
91
|
-
const { wrapSocket } = require('baileys-antiban');
|
|
92
|
-
const _orig = module.exports.makeWASocket;
|
|
93
|
-
if (typeof _orig === 'function') {
|
|
94
|
-
module.exports.makeWASocket = function(...args) {
|
|
95
|
-
return wrapSocket(_orig.apply(this, args), {
|
|
96
|
-
preset: process.env.ANTIBAN_PRESET || '${opts.preset}',
|
|
97
|
-
delayBetweenMessages: {
|
|
98
|
-
min: parseInt(process.env.ANTIBAN_MIN_DELAY || '${opts.minDelay}'),
|
|
99
|
-
max: parseInt(process.env.ANTIBAN_MAX_DELAY || '${opts.maxDelay}'),
|
|
100
|
-
},
|
|
101
|
-
typingIndicator: (process.env.ANTIBAN_TYPING || '${opts.typing}') !== 'false',
|
|
102
|
-
});
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
} catch(e) {
|
|
106
|
-
console.warn('[baileys-antiban] patch inactive:', e.message);
|
|
107
|
-
}
|
|
108
|
-
})();
|
|
109
|
-
${PATCH_MARKER_END}
|
|
110
|
-
`;
|
|
111
|
-
}
|
|
112
|
-
function buildEsmPatch(source, opts) {
|
|
113
|
-
// Strategy A: function declaration — rename and re-export wrapped version
|
|
114
|
-
if (source.includes('export function makeWASocket')) {
|
|
115
|
-
const patched = source.replace(/export function makeWASocket\b/, 'function _antiban_makeWASocket_orig');
|
|
116
|
-
return (patched +
|
|
117
|
-
`
|
|
118
|
-
${PATCH_MARKER_START}
|
|
119
|
-
// Auto-generated by baileys-antiban patch. Re-run after Baileys/plugin updates.
|
|
120
|
-
import { wrapSocket as _antibanWrap } from 'baileys-antiban';
|
|
121
|
-
export const makeWASocket = (...args) => _antibanWrap(_antiban_makeWASocket_orig(...args), {
|
|
122
|
-
preset: process.env.ANTIBAN_PRESET || '${opts.preset}',
|
|
123
|
-
delayBetweenMessages: {
|
|
124
|
-
min: parseInt(process.env.ANTIBAN_MIN_DELAY || '${opts.minDelay}'),
|
|
125
|
-
max: parseInt(process.env.ANTIBAN_MAX_DELAY || '${opts.maxDelay}'),
|
|
126
|
-
},
|
|
127
|
-
typingIndicator: (process.env.ANTIBAN_TYPING || '${opts.typing}') !== 'false',
|
|
128
|
-
});
|
|
129
|
-
${PATCH_MARKER_END}
|
|
130
|
-
`);
|
|
131
|
-
}
|
|
132
|
-
// Strategy B: const/let declaration — rename and re-export
|
|
133
|
-
if (source.match(/export\s+(const|let)\s+makeWASocket\s*=/)) {
|
|
134
|
-
const patched = source.replace(/export\s+(const|let)\s+makeWASocket\s*=/, 'const _antiban_makeWASocket_orig =');
|
|
135
|
-
return (patched +
|
|
136
|
-
`
|
|
137
|
-
${PATCH_MARKER_START}
|
|
138
|
-
// Auto-generated by baileys-antiban patch. Re-run after Baileys/plugin updates.
|
|
139
|
-
import { wrapSocket as _antibanWrap } from 'baileys-antiban';
|
|
140
|
-
export const makeWASocket = (...args) => _antibanWrap(_antiban_makeWASocket_orig(...args), {
|
|
141
|
-
preset: process.env.ANTIBAN_PRESET || '${opts.preset}',
|
|
142
|
-
delayBetweenMessages: {
|
|
143
|
-
min: parseInt(process.env.ANTIBAN_MIN_DELAY || '${opts.minDelay}'),
|
|
144
|
-
max: parseInt(process.env.ANTIBAN_MAX_DELAY || '${opts.maxDelay}'),
|
|
145
|
-
},
|
|
146
|
-
typingIndicator: (process.env.ANTIBAN_TYPING || '${opts.typing}') !== 'false',
|
|
147
|
-
});
|
|
148
|
-
${PATCH_MARKER_END}
|
|
149
|
-
`);
|
|
150
|
-
}
|
|
151
|
-
// Strategy C: named re-export — intercept at this boundary
|
|
152
|
-
if (source.includes('makeWASocket')) {
|
|
153
|
-
// Append import + re-export override at end of file
|
|
154
|
-
return (source +
|
|
155
|
-
`
|
|
156
|
-
${PATCH_MARKER_START}
|
|
157
|
-
// Auto-generated by baileys-antiban patch. Re-run after Baileys/plugin updates.
|
|
158
|
-
// NOTE: Strategy C (named export intercept) — less precise than A/B.
|
|
159
|
-
// If this breaks, use --path to target the file where makeWASocket is defined.
|
|
160
|
-
import { wrapSocket as _antibanWrap } from 'baileys-antiban';
|
|
161
|
-
const _antiban_raw = makeWASocket;
|
|
162
|
-
export { makeWASocket }; // shadowed below if engine supports block-level export rebind
|
|
163
|
-
// Fallback: log advisory if strategy C can't reassign
|
|
164
|
-
if (typeof makeWASocket === 'function') {
|
|
165
|
-
// eslint-disable-next-line no-global-assign
|
|
166
|
-
try { makeWASocket = (...a) => _antibanWrap(_antiban_raw(...a), { preset: '${opts.preset}', delayBetweenMessages: { min: ${opts.minDelay}, max: ${opts.maxDelay} }, typingIndicator: ${opts.typing} }); } catch {}
|
|
167
|
-
}
|
|
168
|
-
${PATCH_MARKER_END}
|
|
169
|
-
`);
|
|
170
|
-
}
|
|
171
|
-
throw new Error('Could not locate makeWASocket in this file. Try --path to a different Baileys file.');
|
|
172
|
-
}
|
|
173
|
-
export function applyPatch(opts) {
|
|
174
|
-
const { preset = 'conservative', minDelay = 1500, maxDelay = 4000, typingIndicator = true, dryRun = false, } = opts;
|
|
175
|
-
// 1. Locate Baileys
|
|
176
|
-
const defaultSearchPaths = [
|
|
177
|
-
// OC-style nested location
|
|
178
|
-
'./node_modules/@openclaw/whatsapp/node_modules/baileys',
|
|
179
|
-
'./node_modules/@openclaw/whatsapp/node_modules/@whiskeysockets/baileys',
|
|
180
|
-
// Standard locations
|
|
181
|
-
'./node_modules/baileys',
|
|
182
|
-
'./node_modules/@whiskeysockets/baileys',
|
|
183
|
-
// Walk up
|
|
184
|
-
'../node_modules/baileys',
|
|
185
|
-
'../../node_modules/baileys',
|
|
186
|
-
];
|
|
187
|
-
const searchPaths = opts.baileysPaths?.length ? opts.baileysPaths : defaultSearchPaths;
|
|
188
|
-
const baileyDir = findBaileysDir(searchPaths);
|
|
189
|
-
if (!baileyDir) {
|
|
190
|
-
return {
|
|
191
|
-
success: false,
|
|
192
|
-
baileyDir: '(not found)',
|
|
193
|
-
targetFile: '(not found)',
|
|
194
|
-
alreadyPatched: false,
|
|
195
|
-
format: 'cjs',
|
|
196
|
-
message: 'Could not find Baileys package. Use --path <dir> to specify its location.\n' +
|
|
197
|
-
'Example: npx baileys-antiban patch --path ./node_modules/@openclaw/whatsapp/node_modules/baileys',
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
// 2. Find file containing makeWASocket
|
|
201
|
-
const found = findMakeWASocketFile(baileyDir);
|
|
202
|
-
if (!found) {
|
|
203
|
-
return {
|
|
204
|
-
success: false,
|
|
205
|
-
baileyDir,
|
|
206
|
-
targetFile: '(not found)',
|
|
207
|
-
alreadyPatched: false,
|
|
208
|
-
format: 'cjs',
|
|
209
|
-
message: `Found Baileys at ${baileyDir} but could not locate makeWASocket definition.\n` +
|
|
210
|
-
'The package structure may have changed. Please open an issue.',
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
const { file: targetFile, format } = found;
|
|
214
|
-
const source = fs.readFileSync(targetFile, 'utf-8');
|
|
215
|
-
// 3. Check idempotency
|
|
216
|
-
if (source.includes(PATCH_MARKER_START)) {
|
|
217
|
-
return {
|
|
218
|
-
success: true,
|
|
219
|
-
baileyDir,
|
|
220
|
-
targetFile,
|
|
221
|
-
alreadyPatched: true,
|
|
222
|
-
format,
|
|
223
|
-
message: `Already patched: ${targetFile}\nRe-run with --force to re-apply.`,
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
if (dryRun) {
|
|
227
|
-
return {
|
|
228
|
-
success: true,
|
|
229
|
-
baileyDir,
|
|
230
|
-
targetFile,
|
|
231
|
-
alreadyPatched: false,
|
|
232
|
-
format,
|
|
233
|
-
message: `[dry-run] Would patch ${targetFile} (format: ${format})`,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
// 4. Backup
|
|
237
|
-
const backupPath = targetFile + '.antiban-backup';
|
|
238
|
-
if (!fs.existsSync(backupPath)) {
|
|
239
|
-
fs.copyFileSync(targetFile, backupPath);
|
|
240
|
-
}
|
|
241
|
-
// 5. Build and apply patch
|
|
242
|
-
const patchOpts = { preset, minDelay, maxDelay, typing: typingIndicator };
|
|
243
|
-
let patched;
|
|
244
|
-
try {
|
|
245
|
-
if (format === 'cjs') {
|
|
246
|
-
patched = source + buildCjsPatch(patchOpts);
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
patched = buildEsmPatch(source, patchOpts);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
catch (e) {
|
|
253
|
-
return {
|
|
254
|
-
success: false,
|
|
255
|
-
baileyDir,
|
|
256
|
-
targetFile,
|
|
257
|
-
alreadyPatched: false,
|
|
258
|
-
format,
|
|
259
|
-
message: `Patch generation failed: ${e.message}`,
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
fs.writeFileSync(targetFile, patched, 'utf-8');
|
|
263
|
-
return {
|
|
264
|
-
success: true,
|
|
265
|
-
baileyDir,
|
|
266
|
-
targetFile,
|
|
267
|
-
alreadyPatched: false,
|
|
268
|
-
format,
|
|
269
|
-
backupPath,
|
|
270
|
-
message: `✅ Patched: ${targetFile}\n` +
|
|
271
|
-
` Format: ${format}\n` +
|
|
272
|
-
` Backup: ${backupPath}\n` +
|
|
273
|
-
` Preset: ${preset} (${minDelay}–${maxDelay}ms delays, typing=${typingIndicator})\n` +
|
|
274
|
-
`\nTo auto-re-patch after plugin updates, add to your package.json:\n` +
|
|
275
|
-
` "scripts": { "postinstall": "npx baileys-antiban patch" }\n\n` +
|
|
276
|
-
`Env overrides: ANTIBAN_PRESET, ANTIBAN_MIN_DELAY, ANTIBAN_MAX_DELAY, ANTIBAN_TYPING`,
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
export function unpatchFile(targetFile) {
|
|
280
|
-
if (!fs.existsSync(targetFile)) {
|
|
281
|
-
return { success: false, message: `File not found: ${targetFile}` };
|
|
282
|
-
}
|
|
283
|
-
const backupPath = targetFile + '.antiban-backup';
|
|
284
|
-
if (!fs.existsSync(backupPath)) {
|
|
285
|
-
// Try removing the patch block from source
|
|
286
|
-
const source = fs.readFileSync(targetFile, 'utf-8');
|
|
287
|
-
if (!source.includes(PATCH_MARKER_START)) {
|
|
288
|
-
return { success: true, message: 'File is not patched.' };
|
|
289
|
-
}
|
|
290
|
-
const startIdx = source.indexOf(PATCH_MARKER_START);
|
|
291
|
-
const endIdx = source.indexOf(PATCH_MARKER_END);
|
|
292
|
-
if (startIdx === -1 || endIdx === -1) {
|
|
293
|
-
return { success: false, message: 'Patch markers found but malformed. Restore manually from backup.' };
|
|
294
|
-
}
|
|
295
|
-
const cleaned = source.slice(0, startIdx) + source.slice(endIdx + PATCH_MARKER_END.length);
|
|
296
|
-
fs.writeFileSync(targetFile, cleaned, 'utf-8');
|
|
297
|
-
return { success: true, message: `Patch removed from ${targetFile}` };
|
|
298
|
-
}
|
|
299
|
-
fs.copyFileSync(backupPath, targetFile);
|
|
300
|
-
fs.unlinkSync(backupPath);
|
|
301
|
-
return { success: true, message: `Restored from backup: ${backupPath}` };
|
|
302
|
-
}
|
package/lib/AntiBan/persist.js
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
const KNOWN_CHATS_MAX = 1000;
|
|
4
|
-
const DEBOUNCE_MS = 5000;
|
|
5
|
-
/**
|
|
6
|
-
* Manages persisted state for a single baileys-antiban instance.
|
|
7
|
-
*
|
|
8
|
-
* **Single-writer assumption:** No file lock is used. Two processes sharing
|
|
9
|
-
* the same state file will race on concurrent writes. Use separate state
|
|
10
|
-
* files per process to avoid data corruption.
|
|
11
|
-
*/
|
|
12
|
-
export class StateManager {
|
|
13
|
-
path;
|
|
14
|
-
debounceTimer = null;
|
|
15
|
-
constructor(filePath) {
|
|
16
|
-
// Resolve to absolute path and reject null bytes to prevent path injection
|
|
17
|
-
if (filePath.includes('\0'))
|
|
18
|
-
throw new Error('[baileys-antiban] Invalid state file path: null byte');
|
|
19
|
-
this.path = path.resolve(filePath);
|
|
20
|
-
}
|
|
21
|
-
load() {
|
|
22
|
-
try {
|
|
23
|
-
const raw = fs.readFileSync(this.path, 'utf-8');
|
|
24
|
-
const parsed = JSON.parse(raw);
|
|
25
|
-
// Strict shape validation before trusting file content
|
|
26
|
-
if (typeof parsed !== 'object' || parsed === null ||
|
|
27
|
-
parsed.version !== 3 ||
|
|
28
|
-
typeof parsed.savedAt !== 'number' ||
|
|
29
|
-
!Array.isArray(parsed.knownChats)) {
|
|
30
|
-
console.warn('[baileys-antiban] WARN: corrupt state file or version mismatch, starting fresh');
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
return parsed;
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
// Missing file = silent null. Corrupt JSON = warn.
|
|
37
|
-
if (fs.existsSync(this.path)) {
|
|
38
|
-
console.warn('[baileys-antiban] WARN: corrupt state file, starting fresh');
|
|
39
|
-
}
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
/** Debounced save — called after every send (5s delay) */
|
|
44
|
-
saveDebounced(state) {
|
|
45
|
-
if (this.debounceTimer) {
|
|
46
|
-
clearTimeout(this.debounceTimer);
|
|
47
|
-
}
|
|
48
|
-
this.debounceTimer = setTimeout(() => {
|
|
49
|
-
this.writeFile(state);
|
|
50
|
-
this.debounceTimer = null;
|
|
51
|
-
}, DEBOUNCE_MS);
|
|
52
|
-
}
|
|
53
|
-
/** Immediate save — called after health events (ban/restriction) */
|
|
54
|
-
saveImmediate(state) {
|
|
55
|
-
if (this.debounceTimer) {
|
|
56
|
-
clearTimeout(this.debounceTimer);
|
|
57
|
-
this.debounceTimer = null;
|
|
58
|
-
}
|
|
59
|
-
this.writeFile(state);
|
|
60
|
-
}
|
|
61
|
-
/** Flush/cancel pending debounced write (for tests and process exit) */
|
|
62
|
-
flush() {
|
|
63
|
-
if (this.debounceTimer) {
|
|
64
|
-
clearTimeout(this.debounceTimer);
|
|
65
|
-
this.debounceTimer = null;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
destroy() {
|
|
69
|
-
this.flush();
|
|
70
|
-
}
|
|
71
|
-
writeFile(state) {
|
|
72
|
-
const toSave = {
|
|
73
|
-
...state,
|
|
74
|
-
savedAt: Date.now(),
|
|
75
|
-
// LRU eviction: keep last KNOWN_CHATS_MAX entries
|
|
76
|
-
knownChats: state.knownChats.length > KNOWN_CHATS_MAX
|
|
77
|
-
? state.knownChats.slice(-KNOWN_CHATS_MAX)
|
|
78
|
-
: state.knownChats,
|
|
79
|
-
};
|
|
80
|
-
try {
|
|
81
|
-
fs.writeFileSync(this.path, JSON.stringify(toSave, null, 2), 'utf-8');
|
|
82
|
-
}
|
|
83
|
-
catch (err) {
|
|
84
|
-
console.warn(`[baileys-antiban] WARN: failed to write state to ${this.path}:`, err);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|