s3db.js 13.6.0 → 14.0.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/README.md +139 -43
- package/dist/s3db.cjs +72425 -38970
- package/dist/s3db.cjs.map +1 -1
- package/dist/s3db.es.js +72177 -38764
- package/dist/s3db.es.js.map +1 -1
- package/mcp/lib/base-handler.js +157 -0
- package/mcp/lib/handlers/connection-handler.js +280 -0
- package/mcp/lib/handlers/query-handler.js +533 -0
- package/mcp/lib/handlers/resource-handler.js +428 -0
- package/mcp/lib/tool-registry.js +336 -0
- package/mcp/lib/tools/connection-tools.js +161 -0
- package/mcp/lib/tools/query-tools.js +267 -0
- package/mcp/lib/tools/resource-tools.js +404 -0
- package/package.json +94 -49
- package/src/clients/memory-client.class.js +346 -191
- package/src/clients/memory-storage.class.js +300 -84
- package/src/clients/s3-client.class.js +7 -6
- package/src/concerns/geo-encoding.js +19 -2
- package/src/concerns/ip.js +59 -9
- package/src/concerns/money.js +8 -1
- package/src/concerns/password-hashing.js +49 -8
- package/src/concerns/plugin-storage.js +186 -18
- package/src/concerns/storage-drivers/filesystem-driver.js +284 -0
- package/src/database.class.js +139 -29
- package/src/errors.js +332 -42
- package/src/plugins/api/auth/oidc-auth.js +66 -17
- package/src/plugins/api/auth/strategies/base-strategy.class.js +74 -0
- package/src/plugins/api/auth/strategies/factory.class.js +63 -0
- package/src/plugins/api/auth/strategies/global-strategy.class.js +44 -0
- package/src/plugins/api/auth/strategies/path-based-strategy.class.js +83 -0
- package/src/plugins/api/auth/strategies/path-rules-strategy.class.js +118 -0
- package/src/plugins/api/concerns/failban-manager.js +106 -57
- package/src/plugins/api/concerns/opengraph-helper.js +116 -0
- package/src/plugins/api/concerns/route-context.js +601 -0
- package/src/plugins/api/concerns/state-machine.js +288 -0
- package/src/plugins/api/index.js +180 -41
- package/src/plugins/api/routes/auth-routes.js +198 -30
- package/src/plugins/api/routes/resource-routes.js +19 -4
- package/src/plugins/api/server/health-manager.class.js +163 -0
- package/src/plugins/api/server/middleware-chain.class.js +310 -0
- package/src/plugins/api/server/router.class.js +472 -0
- package/src/plugins/api/server.js +280 -1303
- package/src/plugins/api/utils/custom-routes.js +17 -5
- package/src/plugins/api/utils/guards.js +76 -17
- package/src/plugins/api/utils/openapi-generator-cached.class.js +133 -0
- package/src/plugins/api/utils/openapi-generator.js +7 -6
- package/src/plugins/api/utils/template-engine.js +77 -3
- package/src/plugins/audit.plugin.js +30 -8
- package/src/plugins/backup.plugin.js +110 -14
- package/src/plugins/cache/cache.class.js +22 -5
- package/src/plugins/cache/filesystem-cache.class.js +116 -19
- package/src/plugins/cache/memory-cache.class.js +211 -57
- package/src/plugins/cache/multi-tier-cache.class.js +371 -0
- package/src/plugins/cache/partition-aware-filesystem-cache.class.js +168 -47
- package/src/plugins/cache/redis-cache.class.js +552 -0
- package/src/plugins/cache/s3-cache.class.js +17 -8
- package/src/plugins/cache.plugin.js +176 -61
- package/src/plugins/cloud-inventory/drivers/alibaba-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/aws-driver.js +60 -29
- package/src/plugins/cloud-inventory/drivers/azure-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/base-driver.js +16 -2
- package/src/plugins/cloud-inventory/drivers/cloudflare-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/digitalocean-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/hetzner-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/linode-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/mongodb-atlas-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/vultr-driver.js +8 -1
- package/src/plugins/cloud-inventory/index.js +29 -8
- package/src/plugins/cloud-inventory/registry.js +64 -42
- package/src/plugins/cloud-inventory.plugin.js +240 -138
- package/src/plugins/concerns/plugin-dependencies.js +54 -0
- package/src/plugins/concerns/resource-names.js +100 -0
- package/src/plugins/consumers/index.js +10 -2
- package/src/plugins/consumers/sqs-consumer.js +12 -2
- package/src/plugins/cookie-farm-suite.plugin.js +278 -0
- package/src/plugins/cookie-farm.errors.js +73 -0
- package/src/plugins/cookie-farm.plugin.js +869 -0
- package/src/plugins/costs.plugin.js +7 -1
- package/src/plugins/eventual-consistency/analytics.js +94 -19
- package/src/plugins/eventual-consistency/config.js +15 -7
- package/src/plugins/eventual-consistency/consolidation.js +29 -11
- package/src/plugins/eventual-consistency/garbage-collection.js +3 -1
- package/src/plugins/eventual-consistency/helpers.js +39 -14
- package/src/plugins/eventual-consistency/install.js +21 -2
- package/src/plugins/eventual-consistency/utils.js +32 -10
- package/src/plugins/fulltext.plugin.js +38 -11
- package/src/plugins/geo.plugin.js +61 -9
- package/src/plugins/identity/concerns/config.js +61 -0
- package/src/plugins/identity/concerns/mfa-manager.js +15 -2
- package/src/plugins/identity/concerns/rate-limit.js +124 -0
- package/src/plugins/identity/concerns/resource-schemas.js +9 -1
- package/src/plugins/identity/concerns/token-generator.js +29 -4
- package/src/plugins/identity/drivers/auth-driver.interface.js +76 -0
- package/src/plugins/identity/drivers/client-credentials-driver.js +127 -0
- package/src/plugins/identity/drivers/index.js +18 -0
- package/src/plugins/identity/drivers/password-driver.js +122 -0
- package/src/plugins/identity/email-service.js +17 -2
- package/src/plugins/identity/index.js +413 -69
- package/src/plugins/identity/oauth2-server.js +413 -30
- package/src/plugins/identity/oidc-discovery.js +16 -8
- package/src/plugins/identity/rsa-keys.js +115 -35
- package/src/plugins/identity/server.js +166 -45
- package/src/plugins/identity/session-manager.js +53 -7
- package/src/plugins/identity/ui/pages/mfa-verification.js +17 -15
- package/src/plugins/identity/ui/routes.js +363 -255
- package/src/plugins/importer/index.js +153 -20
- package/src/plugins/index.js +9 -2
- package/src/plugins/kubernetes-inventory/index.js +6 -0
- package/src/plugins/kubernetes-inventory/k8s-driver.js +867 -0
- package/src/plugins/kubernetes-inventory/resource-types.js +274 -0
- package/src/plugins/kubernetes-inventory.plugin.js +980 -0
- package/src/plugins/metrics.plugin.js +64 -16
- package/src/plugins/ml/base-model.class.js +25 -15
- package/src/plugins/ml/regression-model.class.js +1 -1
- package/src/plugins/ml.errors.js +57 -25
- package/src/plugins/ml.plugin.js +28 -4
- package/src/plugins/namespace.js +210 -0
- package/src/plugins/plugin.class.js +180 -8
- package/src/plugins/puppeteer/console-monitor.js +729 -0
- package/src/plugins/puppeteer/cookie-manager.js +492 -0
- package/src/plugins/puppeteer/network-monitor.js +816 -0
- package/src/plugins/puppeteer/performance-manager.js +746 -0
- package/src/plugins/puppeteer/proxy-manager.js +478 -0
- package/src/plugins/puppeteer/stealth-manager.js +556 -0
- package/src/plugins/puppeteer.errors.js +81 -0
- package/src/plugins/puppeteer.plugin.js +1327 -0
- package/src/plugins/queue-consumer.plugin.js +69 -14
- package/src/plugins/recon/behaviors/uptime-behavior.js +691 -0
- package/src/plugins/recon/concerns/command-runner.js +148 -0
- package/src/plugins/recon/concerns/diff-detector.js +372 -0
- package/src/plugins/recon/concerns/fingerprint-builder.js +307 -0
- package/src/plugins/recon/concerns/process-manager.js +338 -0
- package/src/plugins/recon/concerns/report-generator.js +478 -0
- package/src/plugins/recon/concerns/security-analyzer.js +571 -0
- package/src/plugins/recon/concerns/target-normalizer.js +68 -0
- package/src/plugins/recon/config/defaults.js +321 -0
- package/src/plugins/recon/config/resources.js +370 -0
- package/src/plugins/recon/index.js +778 -0
- package/src/plugins/recon/managers/dependency-manager.js +174 -0
- package/src/plugins/recon/managers/scheduler-manager.js +179 -0
- package/src/plugins/recon/managers/storage-manager.js +745 -0
- package/src/plugins/recon/managers/target-manager.js +274 -0
- package/src/plugins/recon/stages/asn-stage.js +314 -0
- package/src/plugins/recon/stages/certificate-stage.js +84 -0
- package/src/plugins/recon/stages/dns-stage.js +107 -0
- package/src/plugins/recon/stages/dnsdumpster-stage.js +362 -0
- package/src/plugins/recon/stages/fingerprint-stage.js +71 -0
- package/src/plugins/recon/stages/google-dorks-stage.js +440 -0
- package/src/plugins/recon/stages/http-stage.js +89 -0
- package/src/plugins/recon/stages/latency-stage.js +148 -0
- package/src/plugins/recon/stages/massdns-stage.js +302 -0
- package/src/plugins/recon/stages/osint-stage.js +1373 -0
- package/src/plugins/recon/stages/ports-stage.js +169 -0
- package/src/plugins/recon/stages/screenshot-stage.js +94 -0
- package/src/plugins/recon/stages/secrets-stage.js +514 -0
- package/src/plugins/recon/stages/subdomains-stage.js +295 -0
- package/src/plugins/recon/stages/tls-audit-stage.js +78 -0
- package/src/plugins/recon/stages/vulnerability-stage.js +78 -0
- package/src/plugins/recon/stages/web-discovery-stage.js +113 -0
- package/src/plugins/recon/stages/whois-stage.js +349 -0
- package/src/plugins/recon.plugin.js +75 -0
- package/src/plugins/recon.plugin.js.backup +2635 -0
- package/src/plugins/relation.errors.js +87 -14
- package/src/plugins/replicator.plugin.js +514 -137
- package/src/plugins/replicators/base-replicator.class.js +89 -1
- package/src/plugins/replicators/bigquery-replicator.class.js +66 -22
- package/src/plugins/replicators/dynamodb-replicator.class.js +22 -15
- package/src/plugins/replicators/mongodb-replicator.class.js +22 -15
- package/src/plugins/replicators/mysql-replicator.class.js +52 -17
- package/src/plugins/replicators/planetscale-replicator.class.js +30 -4
- package/src/plugins/replicators/postgres-replicator.class.js +62 -27
- package/src/plugins/replicators/s3db-replicator.class.js +25 -18
- package/src/plugins/replicators/schema-sync.helper.js +3 -3
- package/src/plugins/replicators/sqs-replicator.class.js +8 -2
- package/src/plugins/replicators/turso-replicator.class.js +23 -3
- package/src/plugins/replicators/webhook-replicator.class.js +42 -4
- package/src/plugins/s3-queue.plugin.js +464 -65
- package/src/plugins/scheduler.plugin.js +20 -6
- package/src/plugins/state-machine.plugin.js +40 -9
- package/src/plugins/tfstate/README.md +126 -126
- package/src/plugins/tfstate/base-driver.js +28 -4
- package/src/plugins/tfstate/errors.js +65 -10
- package/src/plugins/tfstate/filesystem-driver.js +52 -8
- package/src/plugins/tfstate/index.js +163 -90
- package/src/plugins/tfstate/s3-driver.js +64 -6
- package/src/plugins/ttl.plugin.js +72 -17
- package/src/plugins/vector/distances.js +18 -12
- package/src/plugins/vector/kmeans.js +26 -4
- package/src/resource.class.js +115 -19
- package/src/testing/factory.class.js +20 -3
- package/src/testing/seeder.class.js +7 -1
- package/src/clients/memory-client.md +0 -917
- package/src/plugins/cloud-inventory/drivers/mock-drivers.js +0 -449
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CookieManager - Manages cookie farming, rotation, and reputation tracking
|
|
3
|
+
*
|
|
4
|
+
* Strategies:
|
|
5
|
+
* 1. Warmup Sessions - Visit trusted sites to build cookie reputation
|
|
6
|
+
* 2. Reputation Tracking - Monitor success rates and retire bad cookies
|
|
7
|
+
* 3. Age-Based Rotation - Older cookies are more trustworthy
|
|
8
|
+
*/
|
|
9
|
+
import { CookieManagerError } from '../puppeteer.errors.js';
|
|
10
|
+
|
|
11
|
+
export class CookieManager {
|
|
12
|
+
constructor(plugin) {
|
|
13
|
+
this.plugin = plugin;
|
|
14
|
+
this.config = plugin.config.cookies;
|
|
15
|
+
this.storage = null;
|
|
16
|
+
this.cookiePool = new Map(); // sessionId -> cookie data
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Initialize cookie manager
|
|
21
|
+
*/
|
|
22
|
+
async initialize() {
|
|
23
|
+
this.storage = await this.plugin.database.getResource(this.config.storage.resource);
|
|
24
|
+
|
|
25
|
+
// Load existing cookies into pool if enabled
|
|
26
|
+
if (this.config.farming.enabled) {
|
|
27
|
+
await this._loadCookiePool();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Load cookie pool from storage
|
|
33
|
+
* @private
|
|
34
|
+
*/
|
|
35
|
+
async _loadCookiePool() {
|
|
36
|
+
const limit = this.config.farming.rotation.poolSize;
|
|
37
|
+
const cookies = await this.storage.list({ limit });
|
|
38
|
+
|
|
39
|
+
for (const cookie of cookies) {
|
|
40
|
+
this.cookiePool.set(cookie.sessionId, cookie);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
this.plugin.emit('cookieManager.poolLoaded', {
|
|
44
|
+
size: this.cookiePool.size
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Load cookies into page
|
|
50
|
+
* @param {Page} page - Puppeteer page
|
|
51
|
+
* @param {string} sessionId - Session identifier
|
|
52
|
+
*/
|
|
53
|
+
async loadSession(page, sessionId) {
|
|
54
|
+
// Try to get from pool first
|
|
55
|
+
let session = this.cookiePool.get(sessionId);
|
|
56
|
+
|
|
57
|
+
// If not in pool, try to get from storage
|
|
58
|
+
if (!session) {
|
|
59
|
+
try {
|
|
60
|
+
session = await this.storage.get(sessionId);
|
|
61
|
+
this.cookiePool.set(sessionId, session);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
// Session doesn't exist yet
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Set cookies
|
|
69
|
+
if (session.cookies && session.cookies.length > 0) {
|
|
70
|
+
await page.setCookie(...session.cookies);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Set user agent if available
|
|
74
|
+
if (session.userAgent) {
|
|
75
|
+
await page.setUserAgent(session.userAgent);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Set viewport if available
|
|
79
|
+
if (session.viewport) {
|
|
80
|
+
await page.setViewport(session.viewport);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Update last used timestamp
|
|
84
|
+
session.metadata.lastUsed = Date.now();
|
|
85
|
+
session.metadata.requestCount = (session.metadata.requestCount || 0) + 1;
|
|
86
|
+
|
|
87
|
+
this.plugin.emit('cookieManager.sessionLoaded', {
|
|
88
|
+
sessionId,
|
|
89
|
+
cookieCount: session.cookies.length
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Save cookies from page
|
|
95
|
+
* @param {Page} page - Puppeteer page
|
|
96
|
+
* @param {string} sessionId - Session identifier
|
|
97
|
+
* @param {Object} options - Save options
|
|
98
|
+
*/
|
|
99
|
+
async saveSession(page, sessionId, options = {}) {
|
|
100
|
+
const { success = true } = options;
|
|
101
|
+
|
|
102
|
+
// Get cookies from page
|
|
103
|
+
const cookies = await page.cookies();
|
|
104
|
+
|
|
105
|
+
// Get existing session or create new
|
|
106
|
+
let session = this.cookiePool.get(sessionId) || {
|
|
107
|
+
sessionId,
|
|
108
|
+
cookies: [],
|
|
109
|
+
userAgent: page._userAgent,
|
|
110
|
+
viewport: page._viewport,
|
|
111
|
+
proxyId: page._proxyId || null, // IMMUTABLE: Proxy binding
|
|
112
|
+
domain: this._extractMainDomain(cookies),
|
|
113
|
+
date: new Date().toISOString().split('T')[0], // YYYY-MM-DD
|
|
114
|
+
reputation: {
|
|
115
|
+
successCount: 0,
|
|
116
|
+
failCount: 0,
|
|
117
|
+
successRate: 1.0,
|
|
118
|
+
lastUsed: Date.now()
|
|
119
|
+
},
|
|
120
|
+
metadata: {
|
|
121
|
+
createdAt: Date.now(),
|
|
122
|
+
expiresAt: Date.now() + this.config.farming.rotation.maxAge,
|
|
123
|
+
requestCount: 0,
|
|
124
|
+
age: 0
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Update cookies
|
|
129
|
+
session.cookies = cookies;
|
|
130
|
+
|
|
131
|
+
// Update domain (in case it changed)
|
|
132
|
+
session.domain = this._extractMainDomain(cookies);
|
|
133
|
+
session.date = new Date().toISOString().split('T')[0];
|
|
134
|
+
|
|
135
|
+
// Update reputation
|
|
136
|
+
if (this.config.farming.reputation.enabled && this.config.farming.reputation.trackSuccess) {
|
|
137
|
+
if (success) {
|
|
138
|
+
session.reputation.successCount++;
|
|
139
|
+
} else {
|
|
140
|
+
session.reputation.failCount++;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const total = session.reputation.successCount + session.reputation.failCount;
|
|
144
|
+
session.reputation.successRate = session.reputation.successCount / total;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Update age
|
|
148
|
+
session.metadata.age = Date.now() - session.metadata.createdAt;
|
|
149
|
+
|
|
150
|
+
// Save to storage if auto-save enabled
|
|
151
|
+
if (this.config.storage.autoSave) {
|
|
152
|
+
try {
|
|
153
|
+
const existing = await this.storage.get(sessionId);
|
|
154
|
+
await this.storage.update(sessionId, session);
|
|
155
|
+
} catch (err) {
|
|
156
|
+
await this.storage.insert(session);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Update pool
|
|
161
|
+
this.cookiePool.set(sessionId, session);
|
|
162
|
+
|
|
163
|
+
this.plugin.emit('cookieManager.sessionSaved', {
|
|
164
|
+
sessionId,
|
|
165
|
+
cookieCount: cookies.length,
|
|
166
|
+
reputation: session.reputation
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Farm cookies for a session
|
|
172
|
+
* @param {string} sessionId - Session identifier
|
|
173
|
+
* @returns {Promise<void>}
|
|
174
|
+
*/
|
|
175
|
+
async farmCookies(sessionId) {
|
|
176
|
+
if (!this.config.farming.enabled || !this.config.farming.warmup.enabled) {
|
|
177
|
+
throw new CookieManagerError('Cookie farming is not enabled', {
|
|
178
|
+
operation: 'farmCookies',
|
|
179
|
+
retriable: false,
|
|
180
|
+
suggestion: 'Enable config.farming.enabled and config.farming.warmup.enabled to farm cookies.'
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const warmupConfig = this.config.farming.warmup;
|
|
185
|
+
const pages = [...warmupConfig.pages];
|
|
186
|
+
|
|
187
|
+
// Randomize order if enabled
|
|
188
|
+
if (warmupConfig.randomOrder) {
|
|
189
|
+
pages.sort(() => Math.random() - 0.5);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
this.plugin.emit('cookieManager.farmingStarted', {
|
|
193
|
+
sessionId,
|
|
194
|
+
pages: pages.length
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Visit each warmup page
|
|
198
|
+
for (const url of pages) {
|
|
199
|
+
try {
|
|
200
|
+
const page = await this.plugin.navigate(url, { useSession: sessionId });
|
|
201
|
+
|
|
202
|
+
// Wait random time on page
|
|
203
|
+
const timeOnPage = warmupConfig.timePerPage.min +
|
|
204
|
+
Math.random() * (warmupConfig.timePerPage.max - warmupConfig.timePerPage.min);
|
|
205
|
+
|
|
206
|
+
// Perform interactions if enabled
|
|
207
|
+
if (warmupConfig.interactions.scroll) {
|
|
208
|
+
await this._randomScroll(page);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (warmupConfig.interactions.hover) {
|
|
212
|
+
await this._randomHover(page);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (warmupConfig.interactions.click) {
|
|
216
|
+
await this._randomClick(page);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Wait remaining time
|
|
220
|
+
await this._delay(timeOnPage);
|
|
221
|
+
|
|
222
|
+
// Save cookies with success=true
|
|
223
|
+
await this.saveSession(page, sessionId, { success: true });
|
|
224
|
+
|
|
225
|
+
// Close page
|
|
226
|
+
await page.close();
|
|
227
|
+
|
|
228
|
+
this.plugin.emit('cookieManager.warmupPageCompleted', {
|
|
229
|
+
sessionId,
|
|
230
|
+
url
|
|
231
|
+
});
|
|
232
|
+
} catch (err) {
|
|
233
|
+
this.plugin.emit('cookieManager.warmupPageFailed', {
|
|
234
|
+
sessionId,
|
|
235
|
+
url,
|
|
236
|
+
error: err.message
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
this.plugin.emit('cookieManager.farmingCompleted', { sessionId });
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Get best cookie from pool based on reputation
|
|
246
|
+
* @param {Object} options - Selection options
|
|
247
|
+
* @returns {Promise<Object>}
|
|
248
|
+
*/
|
|
249
|
+
async getBestCookie(options = {}) {
|
|
250
|
+
if (!this.config.farming.enabled || !this.config.farming.reputation.enabled) {
|
|
251
|
+
throw new CookieManagerError('Cookie farming reputation must be enabled to select best cookies', {
|
|
252
|
+
operation: 'getBestCookie',
|
|
253
|
+
retriable: false,
|
|
254
|
+
suggestion: 'Enable config.farming.reputation.enabled before calling getBestCookie().'
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const candidates = Array.from(this.cookiePool.values())
|
|
259
|
+
.filter(session => {
|
|
260
|
+
// Filter out retired cookies
|
|
261
|
+
if (session.reputation.successRate < this.config.farming.reputation.retireThreshold) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Filter out expired cookies
|
|
266
|
+
if (Date.now() > session.metadata.expiresAt) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Filter out overused cookies
|
|
271
|
+
if (session.metadata.requestCount >= this.config.farming.rotation.requestsPerCookie) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return true;
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
if (candidates.length === 0) {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Score cookies based on reputation and age
|
|
283
|
+
const scored = candidates.map(session => {
|
|
284
|
+
let score = session.reputation.successRate;
|
|
285
|
+
|
|
286
|
+
// Age boost - older cookies are more trustworthy
|
|
287
|
+
if (this.config.farming.reputation.ageBoost) {
|
|
288
|
+
const ageInHours = session.metadata.age / (1000 * 60 * 60);
|
|
289
|
+
const ageBoost = Math.min(ageInHours / 24, 1) * 0.2; // Up to 20% boost
|
|
290
|
+
score += ageBoost;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return { session, score };
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Sort by score descending
|
|
297
|
+
scored.sort((a, b) => b.score - a.score);
|
|
298
|
+
|
|
299
|
+
return scored[0].session;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Rotate cookies - remove expired/overused cookies
|
|
304
|
+
* @returns {Promise<number>}
|
|
305
|
+
*/
|
|
306
|
+
async rotateCookies() {
|
|
307
|
+
if (!this.config.farming.enabled || !this.config.farming.rotation.enabled) {
|
|
308
|
+
return 0;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
let removed = 0;
|
|
312
|
+
const now = Date.now();
|
|
313
|
+
|
|
314
|
+
for (const [sessionId, session] of this.cookiePool.entries()) {
|
|
315
|
+
let shouldRemove = false;
|
|
316
|
+
|
|
317
|
+
// Check expiration
|
|
318
|
+
if (now > session.metadata.expiresAt) {
|
|
319
|
+
shouldRemove = true;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Check request count
|
|
323
|
+
if (session.metadata.requestCount >= this.config.farming.rotation.requestsPerCookie) {
|
|
324
|
+
shouldRemove = true;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Check reputation
|
|
328
|
+
if (this.config.farming.reputation.enabled &&
|
|
329
|
+
session.reputation.successRate < this.config.farming.reputation.retireThreshold) {
|
|
330
|
+
shouldRemove = true;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (shouldRemove) {
|
|
334
|
+
this.cookiePool.delete(sessionId);
|
|
335
|
+
|
|
336
|
+
// Remove from storage
|
|
337
|
+
try {
|
|
338
|
+
await this.storage.remove(sessionId);
|
|
339
|
+
} catch (err) {
|
|
340
|
+
// Ignore errors
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
removed++;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (removed > 0) {
|
|
348
|
+
this.plugin.emit('cookieManager.cookiesRotated', { removed });
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return removed;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Get cookie pool statistics
|
|
356
|
+
* @returns {Promise<Object>}
|
|
357
|
+
*/
|
|
358
|
+
async getStats() {
|
|
359
|
+
const sessions = Array.from(this.cookiePool.values());
|
|
360
|
+
|
|
361
|
+
const stats = {
|
|
362
|
+
total: sessions.length,
|
|
363
|
+
healthy: 0,
|
|
364
|
+
expired: 0,
|
|
365
|
+
overused: 0,
|
|
366
|
+
lowReputation: 0,
|
|
367
|
+
averageAge: 0,
|
|
368
|
+
averageSuccessRate: 0,
|
|
369
|
+
averageRequestCount: 0
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
if (sessions.length === 0) {
|
|
373
|
+
return stats;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const now = Date.now();
|
|
377
|
+
let totalAge = 0;
|
|
378
|
+
let totalSuccessRate = 0;
|
|
379
|
+
let totalRequestCount = 0;
|
|
380
|
+
|
|
381
|
+
for (const session of sessions) {
|
|
382
|
+
// Count expired
|
|
383
|
+
if (now > session.metadata.expiresAt) {
|
|
384
|
+
stats.expired++;
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Count overused
|
|
389
|
+
if (session.metadata.requestCount >= this.config.farming.rotation.requestsPerCookie) {
|
|
390
|
+
stats.overused++;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Count low reputation
|
|
395
|
+
if (session.reputation.successRate < this.config.farming.reputation.retireThreshold) {
|
|
396
|
+
stats.lowReputation++;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Count healthy
|
|
401
|
+
stats.healthy++;
|
|
402
|
+
|
|
403
|
+
// Accumulate metrics
|
|
404
|
+
totalAge += session.metadata.age;
|
|
405
|
+
totalSuccessRate += session.reputation.successRate;
|
|
406
|
+
totalRequestCount += session.metadata.requestCount;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Calculate averages
|
|
410
|
+
stats.averageAge = totalAge / stats.healthy || 0;
|
|
411
|
+
stats.averageSuccessRate = totalSuccessRate / stats.healthy || 0;
|
|
412
|
+
stats.averageRequestCount = totalRequestCount / stats.healthy || 0;
|
|
413
|
+
|
|
414
|
+
return stats;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Random scroll helper
|
|
419
|
+
* @private
|
|
420
|
+
*/
|
|
421
|
+
async _randomScroll(page) {
|
|
422
|
+
const scrollDistance = Math.floor(Math.random() * 500) + 200;
|
|
423
|
+
await page.evaluate((distance) => {
|
|
424
|
+
window.scrollBy(0, distance);
|
|
425
|
+
}, scrollDistance);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Random hover helper
|
|
430
|
+
* @private
|
|
431
|
+
*/
|
|
432
|
+
async _randomHover(page) {
|
|
433
|
+
try {
|
|
434
|
+
const elements = await page.$$('a, button');
|
|
435
|
+
if (elements.length > 0) {
|
|
436
|
+
const randomElement = elements[Math.floor(Math.random() * elements.length)];
|
|
437
|
+
await randomElement.hover();
|
|
438
|
+
}
|
|
439
|
+
} catch (err) {
|
|
440
|
+
// Ignore errors
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Random click helper
|
|
446
|
+
* @private
|
|
447
|
+
*/
|
|
448
|
+
async _randomClick(page) {
|
|
449
|
+
try {
|
|
450
|
+
// Find clickable elements that won't navigate away
|
|
451
|
+
const elements = await page.$$('button:not([type="submit"]), div[role="button"]');
|
|
452
|
+
if (elements.length > 0) {
|
|
453
|
+
const randomElement = elements[Math.floor(Math.random() * elements.length)];
|
|
454
|
+
await randomElement.click();
|
|
455
|
+
}
|
|
456
|
+
} catch (err) {
|
|
457
|
+
// Ignore errors
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Extract main domain from cookies
|
|
463
|
+
* @private
|
|
464
|
+
*/
|
|
465
|
+
_extractMainDomain(cookies) {
|
|
466
|
+
if (!cookies || cookies.length === 0) {
|
|
467
|
+
return 'unknown';
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Get most common domain from cookies
|
|
471
|
+
const domains = {};
|
|
472
|
+
cookies.forEach(cookie => {
|
|
473
|
+
const domain = cookie.domain || 'unknown';
|
|
474
|
+
domains[domain] = (domains[domain] || 0) + 1;
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
// Return domain with most cookies
|
|
478
|
+
return Object.entries(domains)
|
|
479
|
+
.sort((a, b) => b[1] - a[1])[0][0]
|
|
480
|
+
.replace(/^\./, ''); // Remove leading dot
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Delay helper
|
|
485
|
+
* @private
|
|
486
|
+
*/
|
|
487
|
+
async _delay(ms) {
|
|
488
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
export default CookieManager;
|