@doppelgangerdev/doppelganger 0.4.0 → 0.4.3
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 +1 -1
- package/agent.js +49 -40
- package/dist/assets/index-D68YZVOp.js +19 -0
- package/dist/assets/index-WbwoTnJa.css +1 -0
- package/dist/index.html +3 -3
- package/headful.js +23 -23
- package/package.json +1 -1
- package/proxy-rotation.js +245 -230
- package/scrape.js +25 -25
- package/server.js +343 -296
- package/dist/assets/index-B7ntJ0pF.js +0 -18
- package/dist/assets/index-OOTrc7_f.css +0 -1
- package/dist/screenshots/agent_1768764625684.png +0 -0
- package/dist/screenshots/agent_1768765565909.png +0 -0
- package/dist/screenshots/agent_1768765581979.png +0 -0
- package/dist/screenshots/scrape_1768764416615.png +0 -0
- package/dist/screenshots/scrape_1768764452033.png +0 -0
- package/dist/screenshots/scrape_1768765064688.png +0 -0
- package/dist/screenshots/scrape_1768765090587.png +0 -0
- package/dist/screenshots/scrape_1768765100798.png +0 -0
- package/dist/screenshots/scrape_1768765114782.png +0 -0
- package/dist/screenshots/scrape_1768765127463.png +0 -0
- package/public/screenshots/agent_1768764625684.png +0 -0
- package/public/screenshots/agent_1768765565909.png +0 -0
- package/public/screenshots/agent_1768765581979.png +0 -0
- package/public/screenshots/scrape_1768764416615.png +0 -0
- package/public/screenshots/scrape_1768764452033.png +0 -0
- package/public/screenshots/scrape_1768765064688.png +0 -0
- package/public/screenshots/scrape_1768765090587.png +0 -0
- package/public/screenshots/scrape_1768765100798.png +0 -0
- package/public/screenshots/scrape_1768765114782.png +0 -0
- package/public/screenshots/scrape_1768765127463.png +0 -0
- package/public/screenshots/scrape_1768769463201.png +0 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Doppelganger -
|
|
1
|
+
# Doppelganger - Browser Automation for Everyone
|
|
2
2
|
|
|
3
3
|
[](https://hub.docker.com/r/mnemosyneai/doppelganger)
|
|
4
4
|
[](#getting-started)
|
package/agent.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const { chromium } = require('playwright');
|
|
2
|
-
const { JSDOM } = require('jsdom');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { getProxySelection } = require('./proxy-rotation');
|
|
1
|
+
const { chromium } = require('playwright');
|
|
2
|
+
const { JSDOM } = require('jsdom');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { getProxySelection } = require('./proxy-rotation');
|
|
6
6
|
|
|
7
7
|
const STORAGE_STATE_PATH = path.join(__dirname, 'storage_state.json');
|
|
8
8
|
const STORAGE_STATE_FILE = (() => {
|
|
@@ -168,7 +168,7 @@ async function humanType(page, selector, text, options = {}) {
|
|
|
168
168
|
|
|
169
169
|
async function handleAgent(req, res) {
|
|
170
170
|
const data = (req.method === 'POST') ? req.body : req.query;
|
|
171
|
-
let { url, actions, wait: globalWait, rotateUserAgents, rotateProxies, humanTyping, stealth = {} } = data;
|
|
171
|
+
let { url, actions, wait: globalWait, rotateUserAgents, rotateProxies, humanTyping, stealth = {} } = data;
|
|
172
172
|
const runId = data.runId ? String(data.runId) : null;
|
|
173
173
|
const includeShadowDomRaw = data.includeShadowDom ?? req.query.includeShadowDom;
|
|
174
174
|
const includeShadowDom = includeShadowDomRaw === undefined
|
|
@@ -198,7 +198,9 @@ async function handleAgent(req, res) {
|
|
|
198
198
|
});
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
const
|
|
201
|
+
const localPort = req.socket && req.socket.localPort;
|
|
202
|
+
const localHost = localPort ? `127.0.0.1:${localPort}` : req.get('host');
|
|
203
|
+
const baseUrl = `${req.protocol || 'http'}://${localHost}`;
|
|
202
204
|
const runtimeVars = { ...(data.taskVariables || data.variables || {}) };
|
|
203
205
|
let lastBlockOutput = null;
|
|
204
206
|
runtimeVars['block.output'] = lastBlockOutput;
|
|
@@ -396,24 +398,24 @@ async function handleAgent(req, res) {
|
|
|
396
398
|
|
|
397
399
|
let browser;
|
|
398
400
|
try {
|
|
399
|
-
const launchOptions = {
|
|
400
|
-
headless: true,
|
|
401
|
-
channel: 'chrome',
|
|
402
|
-
args: [
|
|
403
|
-
'--no-sandbox',
|
|
404
|
-
'--disable-setuid-sandbox',
|
|
405
|
-
'--disable-blink-features=AutomationControlled',
|
|
406
|
-
'--hide-scrollbars',
|
|
407
|
-
'--mute-audio'
|
|
408
|
-
]
|
|
409
|
-
};
|
|
410
|
-
const useRotateProxies = String(rotateProxies).toLowerCase() === 'true' || rotateProxies === true;
|
|
411
|
-
const selection = getProxySelection(useRotateProxies);
|
|
412
|
-
if (selection.proxy) {
|
|
413
|
-
launchOptions.proxy = selection.proxy;
|
|
414
|
-
}
|
|
415
|
-
console.log(`[PROXY] Mode: ${selection.mode}; Target: ${selection.proxy ? selection.proxy.server : 'host_ip'}`);
|
|
416
|
-
browser = await chromium.launch(launchOptions);
|
|
401
|
+
const launchOptions = {
|
|
402
|
+
headless: true,
|
|
403
|
+
channel: 'chrome',
|
|
404
|
+
args: [
|
|
405
|
+
'--no-sandbox',
|
|
406
|
+
'--disable-setuid-sandbox',
|
|
407
|
+
'--disable-blink-features=AutomationControlled',
|
|
408
|
+
'--hide-scrollbars',
|
|
409
|
+
'--mute-audio'
|
|
410
|
+
]
|
|
411
|
+
};
|
|
412
|
+
const useRotateProxies = String(rotateProxies).toLowerCase() === 'true' || rotateProxies === true;
|
|
413
|
+
const selection = getProxySelection(useRotateProxies);
|
|
414
|
+
if (selection.proxy) {
|
|
415
|
+
launchOptions.proxy = selection.proxy;
|
|
416
|
+
}
|
|
417
|
+
console.log(`[PROXY] Mode: ${selection.mode}; Target: ${selection.proxy ? selection.proxy.server : 'host_ip'}`);
|
|
418
|
+
browser = await chromium.launch(launchOptions);
|
|
417
419
|
|
|
418
420
|
const contextOptions = {
|
|
419
421
|
userAgent: selectedUA,
|
|
@@ -827,18 +829,24 @@ async function handleAgent(req, res) {
|
|
|
827
829
|
case 'start': {
|
|
828
830
|
const taskId = resolveMaybe(act.value);
|
|
829
831
|
if (!taskId) throw new Error('Missing task id.');
|
|
830
|
-
const apiKey = loadApiKey() || data.apiKey || data.key;
|
|
831
|
-
if (!apiKey)
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
832
|
+
const apiKey = loadApiKey() || data.apiKey || data.key;
|
|
833
|
+
if (!apiKey) {
|
|
834
|
+
logs.push('No API key available; attempting internal start.');
|
|
835
|
+
}
|
|
836
|
+
logs.push(`Starting task: ${taskId}`);
|
|
837
|
+
const headers = {
|
|
838
|
+
'Content-Type': 'application/json',
|
|
839
|
+
'x-internal-run': '1'
|
|
840
|
+
};
|
|
841
|
+
if (apiKey) {
|
|
842
|
+
headers['x-api-key'] = apiKey;
|
|
843
|
+
}
|
|
844
|
+
const response = await fetch(`${baseUrl}/tasks/${taskId}/api`, {
|
|
845
|
+
method: 'POST',
|
|
846
|
+
headers,
|
|
847
|
+
body: JSON.stringify({
|
|
848
|
+
variables: runtimeVars,
|
|
849
|
+
taskVariables: runtimeVars,
|
|
842
850
|
runSource: 'agent_block',
|
|
843
851
|
taskId
|
|
844
852
|
})
|
|
@@ -848,9 +856,10 @@ async function handleAgent(req, res) {
|
|
|
848
856
|
const detail = payload?.error || payload?.message || response.statusText;
|
|
849
857
|
throw new Error(`Start task failed: ${detail}`);
|
|
850
858
|
}
|
|
851
|
-
result = payload?.data ?? payload?.html ?? payload;
|
|
852
|
-
|
|
853
|
-
|
|
859
|
+
result = payload?.data ?? payload?.html ?? payload;
|
|
860
|
+
setBlockOutput(result);
|
|
861
|
+
break;
|
|
862
|
+
}
|
|
854
863
|
}
|
|
855
864
|
return result;
|
|
856
865
|
};
|