brave-real-browser-mcp-server 2.9.21 → 2.11.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/dist/handlers/advanced-extraction-handlers.js +483 -0
- package/dist/handlers/advanced-video-media-handlers.js +150 -43
- package/dist/handlers/api-integration-handlers.js +2 -1
- package/dist/handlers/captcha-handlers.js +2 -1
- package/dist/handlers/dynamic-session-handlers.js +41 -9
- package/dist/handlers/pagination-handlers.js +5 -5
- package/dist/handlers/smart-data-extractors.js +4 -4
- package/dist/handlers/visual-tools-handlers.js +2 -1
- package/dist/index.js +231 -106
- package/dist/mcp-response-validator.js +145 -0
- package/dist/tool-definitions.js +50 -0
- package/package.json +1 -1
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
// Advanced Video Extraction Handlers
|
|
2
|
+
// Ad-Protection Bypass, Obfuscation Detection, Hidden Video Source Extraction
|
|
3
|
+
// @ts-nocheck
|
|
4
|
+
import { getCurrentPage } from '../browser-manager.js';
|
|
5
|
+
import { validateWorkflow } from '../workflow-validation.js';
|
|
6
|
+
import { withErrorHandling, sleep } from '../system-utils.js';
|
|
7
|
+
/**
|
|
8
|
+
* Advanced Video Source Extractor - Bypass ad-protection and extract all video sources
|
|
9
|
+
*/
|
|
10
|
+
export async function handleAdvancedVideoExtraction(args) {
|
|
11
|
+
return await withErrorHandling(async () => {
|
|
12
|
+
validateWorkflow('advanced_video_extraction', {
|
|
13
|
+
requireBrowser: true,
|
|
14
|
+
requirePage: true,
|
|
15
|
+
});
|
|
16
|
+
const page = getCurrentPage();
|
|
17
|
+
const waitTime = args.waitTime || 10000;
|
|
18
|
+
// Collect all video-related data
|
|
19
|
+
const videoData = {
|
|
20
|
+
directVideoUrls: [],
|
|
21
|
+
m3u8Streams: [],
|
|
22
|
+
mpdStreams: [],
|
|
23
|
+
iframeSources: [],
|
|
24
|
+
obfuscatedUrls: [],
|
|
25
|
+
redirectChains: [],
|
|
26
|
+
hostingPlatforms: [],
|
|
27
|
+
downloadLinks: [],
|
|
28
|
+
timestamp: new Date().toISOString()
|
|
29
|
+
};
|
|
30
|
+
// Monitor network for video content
|
|
31
|
+
const networkRequests = [];
|
|
32
|
+
const requestHandler = (request) => {
|
|
33
|
+
const url = request.url();
|
|
34
|
+
const resourceType = request.resourceType();
|
|
35
|
+
networkRequests.push({
|
|
36
|
+
url,
|
|
37
|
+
method: request.method(),
|
|
38
|
+
resourceType,
|
|
39
|
+
headers: request.headers()
|
|
40
|
+
});
|
|
41
|
+
// Detect video URLs
|
|
42
|
+
if (resourceType === 'media' ||
|
|
43
|
+
url.includes('.mp4') ||
|
|
44
|
+
url.includes('.m3u8') ||
|
|
45
|
+
url.includes('.mpd') ||
|
|
46
|
+
url.includes('.webm') ||
|
|
47
|
+
url.includes('video')) {
|
|
48
|
+
videoData.directVideoUrls.push({
|
|
49
|
+
url,
|
|
50
|
+
type: resourceType,
|
|
51
|
+
detected: 'network_monitor'
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const responseHandler = async (response) => {
|
|
56
|
+
try {
|
|
57
|
+
const url = response.url();
|
|
58
|
+
const contentType = response.headers()['content-type'] || '';
|
|
59
|
+
// Check for video content
|
|
60
|
+
if (contentType.includes('video') || contentType.includes('application/vnd.apple.mpegurl')) {
|
|
61
|
+
videoData.directVideoUrls.push({
|
|
62
|
+
url,
|
|
63
|
+
contentType,
|
|
64
|
+
status: response.status(),
|
|
65
|
+
detected: 'response_monitor'
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
// Check for m3u8 playlists
|
|
69
|
+
if (url.includes('.m3u8')) {
|
|
70
|
+
videoData.m3u8Streams.push({
|
|
71
|
+
url,
|
|
72
|
+
status: response.status(),
|
|
73
|
+
type: 'HLS'
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// Check for DASH manifests
|
|
77
|
+
if (url.includes('.mpd')) {
|
|
78
|
+
videoData.mpdStreams.push({
|
|
79
|
+
url,
|
|
80
|
+
status: response.status(),
|
|
81
|
+
type: 'DASH'
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
// Ignore errors
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
page.on('request', requestHandler);
|
|
90
|
+
page.on('response', responseHandler);
|
|
91
|
+
// Extract page content
|
|
92
|
+
const pageAnalysis = await page.evaluate(() => {
|
|
93
|
+
const results = {
|
|
94
|
+
iframes: [],
|
|
95
|
+
videoElements: [],
|
|
96
|
+
obfuscatedScripts: [],
|
|
97
|
+
possibleHosts: [],
|
|
98
|
+
downloadButtons: []
|
|
99
|
+
};
|
|
100
|
+
// 1. Extract all iframes
|
|
101
|
+
document.querySelectorAll('iframe').forEach((iframe) => {
|
|
102
|
+
results.iframes.push({
|
|
103
|
+
src: iframe.src,
|
|
104
|
+
dataSrc: iframe.getAttribute('data-src'),
|
|
105
|
+
id: iframe.id,
|
|
106
|
+
className: iframe.className
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
// 2. Extract video elements
|
|
110
|
+
document.querySelectorAll('video').forEach((video) => {
|
|
111
|
+
const sources = [];
|
|
112
|
+
if (video.src)
|
|
113
|
+
sources.push({ src: video.src, type: 'direct' });
|
|
114
|
+
video.querySelectorAll('source').forEach((source) => {
|
|
115
|
+
sources.push({
|
|
116
|
+
src: source.src,
|
|
117
|
+
type: source.type,
|
|
118
|
+
quality: source.dataset.quality
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
results.videoElements.push({
|
|
122
|
+
sources,
|
|
123
|
+
poster: video.poster,
|
|
124
|
+
currentSrc: video.currentSrc
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
// 3. Detect obfuscated JavaScript
|
|
128
|
+
document.querySelectorAll('script').forEach((script) => {
|
|
129
|
+
const content = script.textContent || '';
|
|
130
|
+
// Check for common obfuscation patterns
|
|
131
|
+
if (content.includes('eval(') ||
|
|
132
|
+
content.includes('atob(') ||
|
|
133
|
+
content.includes('\\x') ||
|
|
134
|
+
content.match(/0x[0-9a-f]{4}/gi) ||
|
|
135
|
+
content.includes('_0x')) {
|
|
136
|
+
// Try to extract URLs from obfuscated code
|
|
137
|
+
const urlPatterns = [
|
|
138
|
+
/https?:\/\/[^\s"']+\.m3u8[^\s"']*/gi,
|
|
139
|
+
/https?:\/\/[^\s"']+\.mp4[^\s"']*/gi,
|
|
140
|
+
/https?:\/\/[^\s"']+\.mpd[^\s"']*/gi,
|
|
141
|
+
/https?:\/\/[^\s"']+video[^\s"']*/gi
|
|
142
|
+
];
|
|
143
|
+
const foundUrls = [];
|
|
144
|
+
urlPatterns.forEach(pattern => {
|
|
145
|
+
const matches = content.match(pattern);
|
|
146
|
+
if (matches)
|
|
147
|
+
foundUrls.push(...matches);
|
|
148
|
+
});
|
|
149
|
+
results.obfuscatedScripts.push({
|
|
150
|
+
hasObfuscation: true,
|
|
151
|
+
patterns: {
|
|
152
|
+
hasEval: content.includes('eval('),
|
|
153
|
+
hasAtob: content.includes('atob('),
|
|
154
|
+
hasHexEncoding: content.includes('\\x'),
|
|
155
|
+
hasObfuscatedVars: content.includes('_0x')
|
|
156
|
+
},
|
|
157
|
+
extractedUrls: foundUrls,
|
|
158
|
+
snippet: content.substring(0, 200)
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
// Extract video hosting domains
|
|
162
|
+
const hostPatterns = [
|
|
163
|
+
/streamtape/gi,
|
|
164
|
+
/doodstream/gi,
|
|
165
|
+
/filemoon/gi,
|
|
166
|
+
/streamwish/gi,
|
|
167
|
+
/mixdrop/gi,
|
|
168
|
+
/upstream/gi,
|
|
169
|
+
/voe\.sx/gi,
|
|
170
|
+
/streamlare/gi,
|
|
171
|
+
/upns\.online/gi
|
|
172
|
+
];
|
|
173
|
+
hostPatterns.forEach(pattern => {
|
|
174
|
+
if (pattern.test(content)) {
|
|
175
|
+
results.possibleHosts.push(pattern.source);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
// 4. Find download buttons and links
|
|
180
|
+
const downloadSelectors = [
|
|
181
|
+
'a[download]',
|
|
182
|
+
'a[href*="download"]',
|
|
183
|
+
'button[data-download]',
|
|
184
|
+
'a[href*=".mp4"]',
|
|
185
|
+
'a[href*=".mkv"]',
|
|
186
|
+
'a[class*="download"]'
|
|
187
|
+
];
|
|
188
|
+
downloadSelectors.forEach(selector => {
|
|
189
|
+
document.querySelectorAll(selector).forEach((el) => {
|
|
190
|
+
results.downloadButtons.push({
|
|
191
|
+
href: el.href || el.getAttribute('href'),
|
|
192
|
+
text: el.textContent?.trim(),
|
|
193
|
+
selector
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
return results;
|
|
198
|
+
});
|
|
199
|
+
// Merge page analysis into videoData
|
|
200
|
+
videoData.iframeSources = pageAnalysis.iframes;
|
|
201
|
+
videoData.obfuscatedUrls = pageAnalysis.obfuscatedScripts;
|
|
202
|
+
videoData.hostingPlatforms = [...new Set(pageAnalysis.possibleHosts)];
|
|
203
|
+
videoData.downloadLinks = pageAnalysis.downloadButtons;
|
|
204
|
+
// Wait for dynamic content
|
|
205
|
+
await sleep(waitTime);
|
|
206
|
+
// Try to click play buttons to trigger video loading
|
|
207
|
+
try {
|
|
208
|
+
const playButton = await page.$('button[class*="play"], .play-button, [aria-label*="Play"]');
|
|
209
|
+
if (playButton) {
|
|
210
|
+
await playButton.click();
|
|
211
|
+
await sleep(3000);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
catch (e) {
|
|
215
|
+
// Play button not found or not clickable
|
|
216
|
+
}
|
|
217
|
+
page.off('request', requestHandler);
|
|
218
|
+
page.off('response', responseHandler);
|
|
219
|
+
// Deduplicate URLs
|
|
220
|
+
videoData.directVideoUrls = [...new Map(videoData.directVideoUrls.map((item) => [item.url, item])).values()];
|
|
221
|
+
videoData.m3u8Streams = [...new Map(videoData.m3u8Streams.map((item) => [item.url, item])).values()];
|
|
222
|
+
// Create summary
|
|
223
|
+
const summary = `
|
|
224
|
+
🎬 Advanced Video Extraction Results
|
|
225
|
+
════════════════════════════════════
|
|
226
|
+
|
|
227
|
+
📊 Summary:
|
|
228
|
+
• Direct Video URLs: ${videoData.directVideoUrls.length}
|
|
229
|
+
• HLS Streams (m3u8): ${videoData.m3u8Streams.length}
|
|
230
|
+
• DASH Streams (mpd): ${videoData.mpdStreams.length}
|
|
231
|
+
• IFrame Sources: ${videoData.iframeSources.length}
|
|
232
|
+
• Obfuscated Scripts: ${videoData.obfuscatedUrls.length}
|
|
233
|
+
• Download Links: ${videoData.downloadLinks.length}
|
|
234
|
+
• Detected Platforms: ${videoData.hostingPlatforms.length}
|
|
235
|
+
|
|
236
|
+
${videoData.directVideoUrls.length > 0 ? `
|
|
237
|
+
🎥 Direct Video URLs:
|
|
238
|
+
${videoData.directVideoUrls.map((v, i) => ` ${i + 1}. ${v.url}\n Type: ${v.type || 'unknown'}\n Detected: ${v.detected}`).join('\n')}
|
|
239
|
+
` : ''}
|
|
240
|
+
|
|
241
|
+
${videoData.m3u8Streams.length > 0 ? `
|
|
242
|
+
📺 HLS Streams:
|
|
243
|
+
${videoData.m3u8Streams.map((s, i) => ` ${i + 1}. ${s.url}`).join('\n')}
|
|
244
|
+
` : ''}
|
|
245
|
+
|
|
246
|
+
${videoData.iframeSources.length > 0 ? `
|
|
247
|
+
🔗 IFrame Sources:
|
|
248
|
+
${videoData.iframeSources.map((f, i) => ` ${i + 1}. ${f.src || f.dataSrc}`).join('\n')}
|
|
249
|
+
` : ''}
|
|
250
|
+
|
|
251
|
+
${videoData.hostingPlatforms.length > 0 ? `
|
|
252
|
+
🌐 Detected Hosting Platforms:
|
|
253
|
+
${videoData.hostingPlatforms.map((h, i) => ` ${i + 1}. ${h}`).join('\n')}
|
|
254
|
+
` : ''}
|
|
255
|
+
|
|
256
|
+
${videoData.obfuscatedUrls.length > 0 ? `
|
|
257
|
+
🔐 Obfuscated Content Detected:
|
|
258
|
+
• Scripts with obfuscation: ${videoData.obfuscatedUrls.length}
|
|
259
|
+
• URLs extracted from obfuscated code: ${videoData.obfuscatedUrls.reduce((acc, s) => acc + (s.extractedUrls?.length || 0), 0)}
|
|
260
|
+
` : ''}
|
|
261
|
+
|
|
262
|
+
${videoData.downloadLinks.length > 0 ? `
|
|
263
|
+
⬇️ Download Links:
|
|
264
|
+
${videoData.downloadLinks.slice(0, 5).map((d, i) => ` ${i + 1}. ${d.text}: ${d.href}`).join('\n')}
|
|
265
|
+
${videoData.downloadLinks.length > 5 ? ` ... and ${videoData.downloadLinks.length - 5} more` : ''}
|
|
266
|
+
` : ''}
|
|
267
|
+
|
|
268
|
+
📋 Full Data (JSON):
|
|
269
|
+
${JSON.stringify(videoData, null, 2)}
|
|
270
|
+
`;
|
|
271
|
+
return {
|
|
272
|
+
content: [{
|
|
273
|
+
type: 'text',
|
|
274
|
+
text: summary
|
|
275
|
+
}]
|
|
276
|
+
};
|
|
277
|
+
}, 'Failed to extract advanced video sources');
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Deobfuscate JavaScript - Attempt to decode obfuscated JavaScript
|
|
281
|
+
*/
|
|
282
|
+
export async function handleDeobfuscateJS(args) {
|
|
283
|
+
return await withErrorHandling(async () => {
|
|
284
|
+
validateWorkflow('deobfuscate_js', {
|
|
285
|
+
requireBrowser: true,
|
|
286
|
+
requirePage: true,
|
|
287
|
+
});
|
|
288
|
+
const page = getCurrentPage();
|
|
289
|
+
const deobfuscationResults = await page.evaluate(() => {
|
|
290
|
+
const results = [];
|
|
291
|
+
document.querySelectorAll('script').forEach((script, index) => {
|
|
292
|
+
const content = script.textContent || '';
|
|
293
|
+
if (content.length < 100)
|
|
294
|
+
return;
|
|
295
|
+
const analysis = {
|
|
296
|
+
scriptIndex: index,
|
|
297
|
+
obfuscationType: [],
|
|
298
|
+
extractedData: {
|
|
299
|
+
urls: [],
|
|
300
|
+
domains: [],
|
|
301
|
+
apiKeys: [],
|
|
302
|
+
base64Strings: []
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
// Detect obfuscation types
|
|
306
|
+
if (content.includes('eval('))
|
|
307
|
+
analysis.obfuscationType.push('eval');
|
|
308
|
+
if (content.includes('atob('))
|
|
309
|
+
analysis.obfuscationType.push('base64');
|
|
310
|
+
if (content.match(/0x[0-9a-f]{4}/gi))
|
|
311
|
+
analysis.obfuscationType.push('hex');
|
|
312
|
+
if (content.match(/_0x[0-9a-f]+/gi))
|
|
313
|
+
analysis.obfuscationType.push('identifier_obfuscation');
|
|
314
|
+
if (content.includes('\\x'))
|
|
315
|
+
analysis.obfuscationType.push('hex_escape');
|
|
316
|
+
if (analysis.obfuscationType.length === 0)
|
|
317
|
+
return;
|
|
318
|
+
// Extract URLs
|
|
319
|
+
const urlPattern = /https?:\/\/[^\s"'<>]+/gi;
|
|
320
|
+
const urls = content.match(urlPattern);
|
|
321
|
+
if (urls) {
|
|
322
|
+
analysis.extractedData.urls = [...new Set(urls)];
|
|
323
|
+
}
|
|
324
|
+
// Extract base64 encoded strings
|
|
325
|
+
const base64Pattern = /["']([A-Za-z0-9+/]{20,}={0,2})["']/g;
|
|
326
|
+
let match;
|
|
327
|
+
while ((match = base64Pattern.exec(content)) !== null) {
|
|
328
|
+
try {
|
|
329
|
+
const decoded = atob(match[1]);
|
|
330
|
+
if (decoded.includes('http') || decoded.includes('video') || decoded.includes('.m3u8')) {
|
|
331
|
+
analysis.extractedData.base64Strings.push({
|
|
332
|
+
original: match[1].substring(0, 50) + '...',
|
|
333
|
+
decoded: decoded.substring(0, 200)
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch (e) {
|
|
338
|
+
// Not valid base64
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
// Extract potential domains
|
|
342
|
+
const domainPattern = /[a-z0-9][a-z0-9-]*\.(com|net|org|io|tv|online|xyz|cc)/gi;
|
|
343
|
+
const domains = content.match(domainPattern);
|
|
344
|
+
if (domains) {
|
|
345
|
+
analysis.extractedData.domains = [...new Set(domains)];
|
|
346
|
+
}
|
|
347
|
+
results.push(analysis);
|
|
348
|
+
});
|
|
349
|
+
return results.filter(r => r.obfuscationType.length > 0);
|
|
350
|
+
});
|
|
351
|
+
return {
|
|
352
|
+
content: [{
|
|
353
|
+
type: 'text',
|
|
354
|
+
text: `🔓 Deobfuscation Results:\n\nFound ${deobfuscationResults.length} obfuscated scripts\n\n${JSON.stringify(deobfuscationResults, null, 2)}`
|
|
355
|
+
}]
|
|
356
|
+
};
|
|
357
|
+
}, 'Failed to deobfuscate JavaScript');
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Multi-Layer Redirect Tracer - Follow multiple redirect layers to find final video source
|
|
361
|
+
*/
|
|
362
|
+
export async function handleMultiLayerRedirectTrace(args) {
|
|
363
|
+
return await withErrorHandling(async () => {
|
|
364
|
+
validateWorkflow('multi_layer_redirect_trace', {
|
|
365
|
+
requireBrowser: true,
|
|
366
|
+
requirePage: true,
|
|
367
|
+
});
|
|
368
|
+
const page = getCurrentPage();
|
|
369
|
+
const startUrl = args.url;
|
|
370
|
+
const maxDepth = args.maxDepth || 5;
|
|
371
|
+
if (!startUrl) {
|
|
372
|
+
throw new Error('URL is required');
|
|
373
|
+
}
|
|
374
|
+
const redirectChain = [];
|
|
375
|
+
let currentDepth = 0;
|
|
376
|
+
let currentUrl = startUrl;
|
|
377
|
+
while (currentDepth < maxDepth) {
|
|
378
|
+
try {
|
|
379
|
+
const allRequests = [];
|
|
380
|
+
const responseHandler = (response) => {
|
|
381
|
+
allRequests.push({
|
|
382
|
+
url: response.url(),
|
|
383
|
+
status: response.status(),
|
|
384
|
+
redirected: response.request().redirectChain().length > 0,
|
|
385
|
+
finalUrl: response.url()
|
|
386
|
+
});
|
|
387
|
+
};
|
|
388
|
+
page.on('response', responseHandler);
|
|
389
|
+
await page.goto(currentUrl, {
|
|
390
|
+
waitUntil: 'networkidle0',
|
|
391
|
+
timeout: 30000
|
|
392
|
+
});
|
|
393
|
+
await sleep(2000);
|
|
394
|
+
page.off('response', responseHandler);
|
|
395
|
+
const finalUrl = page.url();
|
|
396
|
+
// Check for iframe redirects
|
|
397
|
+
const iframes = await page.evaluate(() => {
|
|
398
|
+
return Array.from(document.querySelectorAll('iframe')).map((f) => f.src);
|
|
399
|
+
});
|
|
400
|
+
redirectChain.push({
|
|
401
|
+
depth: currentDepth,
|
|
402
|
+
startUrl: currentUrl,
|
|
403
|
+
finalUrl,
|
|
404
|
+
iframes,
|
|
405
|
+
requests: allRequests.length
|
|
406
|
+
});
|
|
407
|
+
// If we found an iframe, follow it
|
|
408
|
+
if (iframes.length > 0 && iframes[0] !== currentUrl) {
|
|
409
|
+
currentUrl = iframes[0];
|
|
410
|
+
currentDepth++;
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
catch (e) {
|
|
417
|
+
redirectChain.push({
|
|
418
|
+
depth: currentDepth,
|
|
419
|
+
error: e.message
|
|
420
|
+
});
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
content: [{
|
|
426
|
+
type: 'text',
|
|
427
|
+
text: `🔄 Multi-Layer Redirect Trace:\n\nTotal Layers: ${redirectChain.length}\nMax Depth Reached: ${currentDepth >= maxDepth}\n\n${JSON.stringify(redirectChain, null, 2)}`
|
|
428
|
+
}]
|
|
429
|
+
};
|
|
430
|
+
}, 'Failed to trace multi-layer redirects');
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Ad Blocker Detector - Detect and report ad-protection mechanisms
|
|
434
|
+
*/
|
|
435
|
+
export async function handleAdProtectionDetector(args) {
|
|
436
|
+
return await withErrorHandling(async () => {
|
|
437
|
+
validateWorkflow('ad_protection_detector', {
|
|
438
|
+
requireBrowser: true,
|
|
439
|
+
requirePage: true,
|
|
440
|
+
});
|
|
441
|
+
const page = getCurrentPage();
|
|
442
|
+
const adProtection = await page.evaluate(() => {
|
|
443
|
+
const results = {
|
|
444
|
+
adBlockDetection: false,
|
|
445
|
+
antiDebugger: false,
|
|
446
|
+
obfuscatedCode: false,
|
|
447
|
+
popupLayers: 0,
|
|
448
|
+
hiddenElements: 0,
|
|
449
|
+
suspiciousScripts: []
|
|
450
|
+
};
|
|
451
|
+
// Check for common ad-block detection
|
|
452
|
+
const adBlockIndicators = [
|
|
453
|
+
'adblock',
|
|
454
|
+
'ublock',
|
|
455
|
+
'adguard',
|
|
456
|
+
'please disable',
|
|
457
|
+
'turn off ad blocker'
|
|
458
|
+
];
|
|
459
|
+
const bodyText = document.body.textContent?.toLowerCase() || '';
|
|
460
|
+
results.adBlockDetection = adBlockIndicators.some(indicator => bodyText.includes(indicator));
|
|
461
|
+
// Check for anti-debugger code
|
|
462
|
+
document.querySelectorAll('script').forEach((script) => {
|
|
463
|
+
const content = script.textContent || '';
|
|
464
|
+
if (content.includes('debugger') || content.includes('devtools')) {
|
|
465
|
+
results.antiDebugger = true;
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
// Count popup layers
|
|
469
|
+
const overlays = document.querySelectorAll('[style*="position: fixed"], [style*="z-index"]');
|
|
470
|
+
results.popupLayers = overlays.length;
|
|
471
|
+
// Check for hidden elements
|
|
472
|
+
const hidden = document.querySelectorAll('[style*="display: none"], [style*="visibility: hidden"]');
|
|
473
|
+
results.hiddenElements = hidden.length;
|
|
474
|
+
return results;
|
|
475
|
+
});
|
|
476
|
+
return {
|
|
477
|
+
content: [{
|
|
478
|
+
type: 'text',
|
|
479
|
+
text: `🛡️ Ad Protection Analysis:\n\n${JSON.stringify(adProtection, null, 2)}`
|
|
480
|
+
}]
|
|
481
|
+
};
|
|
482
|
+
}, 'Failed to detect ad protection');
|
|
483
|
+
}
|