nothing-browser 0.0.20 → 0.1.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/LICENSE +1 -1
- package/dist/human/index.js +25 -1
- package/dist/launch/detect.js +13 -0
- package/dist/launch/spawn.js +13 -0
- package/dist/piggy/captcha/index.d.ts +39 -0
- package/dist/piggy/captcha/index.d.ts.map +1 -0
- package/dist/piggy/capture/index.d.ts +48 -0
- package/dist/piggy/capture/index.d.ts.map +1 -0
- package/dist/piggy/dialog/index.d.ts +28 -0
- package/dist/piggy/dialog/index.d.ts.map +1 -0
- package/dist/piggy/export/index.d.ts +62 -0
- package/dist/piggy/export/index.d.ts.map +1 -0
- package/dist/piggy/find/index.d.ts +90 -0
- package/dist/piggy/find/index.d.ts.map +1 -0
- package/dist/piggy/http/index.d.ts +14 -0
- package/dist/piggy/http/index.d.ts.map +1 -0
- package/dist/piggy/human/index.d.ts +36 -4
- package/dist/piggy/human/index.d.ts.map +1 -1
- package/dist/piggy/iframe/index.d.ts +53 -0
- package/dist/piggy/iframe/index.d.ts.map +1 -0
- package/dist/piggy/interactions/index.d.ts +24 -0
- package/dist/piggy/interactions/index.d.ts.map +1 -0
- package/dist/piggy/launch/detect.d.ts +1 -1
- package/dist/piggy/launch/detect.d.ts.map +1 -1
- package/dist/piggy/launch/spawn.d.ts.map +1 -1
- package/dist/piggy/media/index.d.ts +11 -0
- package/dist/piggy/media/index.d.ts.map +1 -0
- package/dist/piggy/navigation/index.d.ts +16 -0
- package/dist/piggy/navigation/index.d.ts.map +1 -0
- package/dist/piggy/provide/index.d.ts +81 -0
- package/dist/piggy/provide/index.d.ts.map +1 -0
- package/dist/piggy/proxy/index.d.ts +94 -0
- package/dist/piggy/proxy/index.d.ts.map +1 -0
- package/dist/piggy/register/index.d.ts.map +1 -1
- package/dist/piggy/router/index.d.ts +38 -0
- package/dist/piggy/router/index.d.ts.map +1 -0
- package/dist/piggy/session/index.d.ts +27 -0
- package/dist/piggy/session/index.d.ts.map +1 -0
- package/dist/piggy/tabs/index.d.ts +10 -0
- package/dist/piggy/tabs/index.d.ts.map +1 -0
- package/dist/piggy/wait/index.d.ts +28 -0
- package/dist/piggy/wait/index.d.ts.map +1 -0
- package/dist/piggy.d.ts.map +1 -1
- package/dist/piggy.js +914 -181
- package/dist/register/index.js +39 -86
- package/package.json +1 -1
- package/piggy/captcha/index.d.ts +35 -0
- package/piggy/captcha/index.ts +93 -0
- package/piggy/capture/index.ts +76 -0
- package/piggy/dialog/index.d.ts +29 -0
- package/piggy/dialog/index.ts +85 -0
- package/piggy/export/index.d.ts +117 -0
- package/piggy/export/index.ts +147 -0
- package/piggy/find/index.d.ts +79 -0
- package/piggy/find/index.ts +165 -0
- package/piggy/http/index.ts +65 -0
- package/piggy/human/index.ts +115 -53
- package/piggy/iframe/index.ts +79 -0
- package/piggy/interactions/index.ts +79 -0
- package/piggy/launch/detect.ts +19 -2
- package/piggy/launch/spawn.ts +1 -8
- package/piggy/media/index.ts +46 -0
- package/piggy/navigation/index.ts +52 -0
- package/piggy/provide/index.ts +144 -0
- package/piggy/proxy/index.ts +154 -0
- package/piggy/register/index.ts +41 -59
- package/piggy/router/index.ts +69 -0
- package/piggy/session/index.ts +76 -0
- package/piggy/tabs/index.ts +22 -0
- package/piggy/wait/index.ts +90 -0
- package/piggy.ts +94 -39
- package/dist/piggy/open/index.d.ts +0 -4
- package/dist/piggy/open/index.d.ts.map +0 -1
- package/piggy/open/index.d.ts +0 -4
- package/piggy/open/index.d.ts.map +0 -1
- package/piggy/open/index.ts +0 -5
package/dist/register/index.js
CHANGED
|
@@ -6805,6 +6805,26 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
6805
6805
|
module.exports.SqliteError = require_sqlite_error();
|
|
6806
6806
|
});
|
|
6807
6807
|
|
|
6808
|
+
// piggy/human/index.ts
|
|
6809
|
+
class HumanClient {
|
|
6810
|
+
client;
|
|
6811
|
+
constructor(client) {
|
|
6812
|
+
this.client = client;
|
|
6813
|
+
}
|
|
6814
|
+
set(opts, tabId = "default") {
|
|
6815
|
+
return this.client.send("human.set", { ...opts, tabId });
|
|
6816
|
+
}
|
|
6817
|
+
get(tabId = "default") {
|
|
6818
|
+
return this.client.send("human.get", { tabId });
|
|
6819
|
+
}
|
|
6820
|
+
type(opts, tabId = "default") {
|
|
6821
|
+
return this.client.send("human.type", { ...opts, tabId });
|
|
6822
|
+
}
|
|
6823
|
+
click(opts, tabId = "default") {
|
|
6824
|
+
return this.client.send("human.click", { ...opts, tabId });
|
|
6825
|
+
}
|
|
6826
|
+
}
|
|
6827
|
+
|
|
6808
6828
|
// piggy/logger/index.ts
|
|
6809
6829
|
var import_ernest_logger = __toESM(require_ernest_logger(), 1);
|
|
6810
6830
|
var logger = import_ernest_logger.createLogger({
|
|
@@ -22570,61 +22590,6 @@ var store = new Map;
|
|
|
22570
22590
|
var routeRegistry = new Map;
|
|
22571
22591
|
var keepAliveSites = new Set;
|
|
22572
22592
|
|
|
22573
|
-
// piggy/human/index.ts
|
|
22574
|
-
function randomDelay(min, max) {
|
|
22575
|
-
return new Promise((r) => setTimeout(r, Math.floor(Math.random() * (max - min + 1)) + min));
|
|
22576
|
-
}
|
|
22577
|
-
function humanTypeSequence(text) {
|
|
22578
|
-
const adjacent = {
|
|
22579
|
-
a: ["q", "w", "s", "z"],
|
|
22580
|
-
b: ["v", "g", "h", "n"],
|
|
22581
|
-
c: ["x", "d", "f", "v"],
|
|
22582
|
-
d: ["s", "e", "r", "f", "c", "x"],
|
|
22583
|
-
e: ["w", "r", "d", "s"],
|
|
22584
|
-
f: ["d", "r", "t", "g", "v", "c"],
|
|
22585
|
-
g: ["f", "t", "y", "h", "b", "v"],
|
|
22586
|
-
h: ["g", "y", "u", "j", "n", "b"],
|
|
22587
|
-
i: ["u", "o", "k", "j"],
|
|
22588
|
-
j: ["h", "u", "i", "k", "m", "n"],
|
|
22589
|
-
k: ["j", "i", "o", "l", "m"],
|
|
22590
|
-
l: ["k", "o", "p"],
|
|
22591
|
-
m: ["n", "j", "k"],
|
|
22592
|
-
n: ["b", "h", "j", "m"],
|
|
22593
|
-
o: ["i", "p", "l", "k"],
|
|
22594
|
-
p: ["o", "l"],
|
|
22595
|
-
q: ["w", "a"],
|
|
22596
|
-
r: ["e", "t", "f", "d"],
|
|
22597
|
-
s: ["a", "w", "e", "d", "x", "z"],
|
|
22598
|
-
t: ["r", "y", "g", "f"],
|
|
22599
|
-
u: ["y", "i", "h", "j"],
|
|
22600
|
-
v: ["c", "f", "g", "b"],
|
|
22601
|
-
w: ["q", "e", "a", "s"],
|
|
22602
|
-
x: ["z", "s", "d", "c"],
|
|
22603
|
-
y: ["t", "u", "g", "h"],
|
|
22604
|
-
z: ["a", "s", "x"]
|
|
22605
|
-
};
|
|
22606
|
-
const actions = [];
|
|
22607
|
-
const typoIndices = new Set;
|
|
22608
|
-
if (text.length > 4) {
|
|
22609
|
-
let tries = 0;
|
|
22610
|
-
while (typoIndices.size < 2 && tries < 20) {
|
|
22611
|
-
typoIndices.add(Math.floor(Math.random() * text.length));
|
|
22612
|
-
tries++;
|
|
22613
|
-
}
|
|
22614
|
-
}
|
|
22615
|
-
for (let i = 0;i < text.length; i++) {
|
|
22616
|
-
if (typoIndices.has(i)) {
|
|
22617
|
-
const ch = text[i].toLowerCase();
|
|
22618
|
-
const neighbors = adjacent[ch];
|
|
22619
|
-
const typo = neighbors ? neighbors[Math.floor(Math.random() * neighbors.length)] ?? ch : ch;
|
|
22620
|
-
actions.push(typo);
|
|
22621
|
-
actions.push("BACKSPACE");
|
|
22622
|
-
}
|
|
22623
|
-
actions.push(text[i]);
|
|
22624
|
-
}
|
|
22625
|
-
return actions;
|
|
22626
|
-
}
|
|
22627
|
-
|
|
22628
22593
|
// piggy/intercept/scripts.ts
|
|
22629
22594
|
function buildRespondScript(pattern, status2, contentType, body) {
|
|
22630
22595
|
const safePattern = pattern.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
@@ -23035,7 +23000,7 @@ function createSiteObject(name, registeredUrl, client, tabId, pool) {
|
|
|
23035
23000
|
},
|
|
23036
23001
|
click: (selector, opts) => withErrScreen(() => withTab((t2) => retry(name, async () => {
|
|
23037
23002
|
if (humanMode)
|
|
23038
|
-
await
|
|
23003
|
+
await new Promise((r) => setTimeout(r, 80 + Math.random() * 140));
|
|
23039
23004
|
await client.waitForSelector(selector, opts?.timeout ?? 15000, t2);
|
|
23040
23005
|
const ok = await client.click(selector, t2);
|
|
23041
23006
|
if (!ok)
|
|
@@ -23045,48 +23010,36 @@ function createSiteObject(name, registeredUrl, client, tabId, pool) {
|
|
|
23045
23010
|
}, opts?.retries ?? 2)), `click(${selector})`),
|
|
23046
23011
|
doubleClick: (selector) => withErrScreen(() => withTab(async (t2) => {
|
|
23047
23012
|
if (humanMode)
|
|
23048
|
-
await
|
|
23013
|
+
await new Promise((r) => setTimeout(r, 80 + Math.random() * 120));
|
|
23049
23014
|
return client.doubleClick(selector, t2);
|
|
23050
23015
|
}), `dblclick(${selector})`),
|
|
23051
23016
|
hover: (selector) => withErrScreen(() => withTab(async (t2) => {
|
|
23052
23017
|
if (humanMode)
|
|
23053
|
-
await
|
|
23018
|
+
await new Promise((r) => setTimeout(r, 50 + Math.random() * 100));
|
|
23054
23019
|
return client.hover(selector, t2);
|
|
23055
23020
|
}), `hover(${selector})`),
|
|
23056
23021
|
type: (selector, text, opts) => withErrScreen(() => withTab(async (t2) => {
|
|
23057
23022
|
await client.waitForSelector(selector, 30000, t2);
|
|
23058
|
-
if (humanMode
|
|
23059
|
-
const
|
|
23060
|
-
|
|
23061
|
-
|
|
23062
|
-
|
|
23063
|
-
|
|
23064
|
-
|
|
23065
|
-
|
|
23023
|
+
if (humanMode) {
|
|
23024
|
+
const human = new HumanClient(client);
|
|
23025
|
+
await human.type({
|
|
23026
|
+
selector,
|
|
23027
|
+
text,
|
|
23028
|
+
clear: opts?.clear ?? false,
|
|
23029
|
+
speed: opts?.speed
|
|
23030
|
+
}, t2);
|
|
23031
|
+
} else {
|
|
23032
|
+
if (opts?.clear) {
|
|
23066
23033
|
await client.evaluate(`
|
|
23067
|
-
|
|
23068
|
-
|
|
23069
|
-
|
|
23070
|
-
nativeSetter.call(el, '${current.replace(/'/g, "\\'")}');
|
|
23071
|
-
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
23072
|
-
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
23073
|
-
})()
|
|
23074
|
-
`, t2);
|
|
23075
|
-
const wpm = opts?.wpm ?? 120;
|
|
23076
|
-
const msPerChar = Math.round(60000 / (wpm * 5));
|
|
23077
|
-
await randomDelay(msPerChar * 0.5, msPerChar * 1.8);
|
|
23078
|
-
}
|
|
23079
|
-
} else if (opts?.delay) {
|
|
23080
|
-
for (const ch of text) {
|
|
23081
|
-
await client.type(selector, ch, t2);
|
|
23082
|
-
await new Promise((r) => setTimeout(r, opts.delay));
|
|
23034
|
+
const el = document.querySelector('${selector.replace(/'/g, "\\'")}');
|
|
23035
|
+
if (el) { el.value = ''; el.dispatchEvent(new Event('input', { bubbles: true })); }
|
|
23036
|
+
`, t2);
|
|
23083
23037
|
}
|
|
23084
|
-
} else {
|
|
23085
23038
|
await client.type(selector, text, t2);
|
|
23086
23039
|
}
|
|
23087
23040
|
await client.evaluate(`
|
|
23088
|
-
|
|
23089
|
-
|
|
23041
|
+
document.querySelector('${selector.replace(/'/g, "\\'")}')?.dispatchEvent(new Event('blur', { bubbles: true }));
|
|
23042
|
+
`, t2);
|
|
23090
23043
|
logger_default.success(`[${name}] typed into: ${selector}`);
|
|
23091
23044
|
return true;
|
|
23092
23045
|
}), `type(${selector})`),
|
|
@@ -23111,7 +23064,7 @@ function createSiteObject(name, registeredUrl, client, tabId, pool) {
|
|
|
23111
23064
|
const chunk = px / steps;
|
|
23112
23065
|
for (let i = 0;i < steps; i++) {
|
|
23113
23066
|
await client.scrollBy(chunk, t2);
|
|
23114
|
-
await
|
|
23067
|
+
await new Promise((r) => setTimeout(r, 30 + Math.random() * 50));
|
|
23115
23068
|
}
|
|
23116
23069
|
} else {
|
|
23117
23070
|
await client.scrollBy(px, t2);
|
package/package.json
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// piggy/captcha/index.d.ts
|
|
2
|
+
import { PiggyClient } from "../client";
|
|
3
|
+
|
|
4
|
+
export interface CaptchaState {
|
|
5
|
+
detected: boolean;
|
|
6
|
+
paused: boolean;
|
|
7
|
+
type: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface BlockState {
|
|
11
|
+
detected: boolean;
|
|
12
|
+
type: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export declare class CaptchaClient {
|
|
16
|
+
constructor(client: PiggyClient);
|
|
17
|
+
|
|
18
|
+
status(tabId?: string): Promise<CaptchaState>;
|
|
19
|
+
resolve(tabId?: string): Promise<void>;
|
|
20
|
+
pause(tabId?: string): Promise<void>;
|
|
21
|
+
check(tabId?: string): Promise<void>;
|
|
22
|
+
setAutoRetry(enabled: boolean): Promise<void>;
|
|
23
|
+
|
|
24
|
+
blockStatus(tabId?: string): Promise<BlockState>;
|
|
25
|
+
blockRetry(tabId?: string): Promise<void>;
|
|
26
|
+
|
|
27
|
+
onCaptcha(tabId: string, handler: (data: { captchaType: string; tabId: string }) => void): () => void;
|
|
28
|
+
onCaptchaResolved(tabId: string, handler: (data: { tabId: string }) => void): () => void;
|
|
29
|
+
onBlocked(tabId: string, handler: (data: { blockType: string; tabId: string }) => void): () => void;
|
|
30
|
+
onBlockRetry(tabId: string, handler: (data: { tabId: string; proxy: string }) => void): () => void;
|
|
31
|
+
|
|
32
|
+
waitForResolution(tabId?: string, timeoutMs?: number): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export declare function createCaptchaAPI(client: PiggyClient): CaptchaClient;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// piggy/captcha/index.ts
|
|
2
|
+
import { PiggyClient } from "../client";
|
|
3
|
+
import logger from "../logger";
|
|
4
|
+
|
|
5
|
+
export interface CaptchaState {
|
|
6
|
+
detected: boolean;
|
|
7
|
+
paused: boolean;
|
|
8
|
+
type: string; // "cloudflare" | "recaptcha" | "hcaptcha" | "generic"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface BlockState {
|
|
12
|
+
detected: boolean;
|
|
13
|
+
type: string; // "403" | "access-denied" | "firewall" | "rate-limit"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class CaptchaClient {
|
|
17
|
+
constructor(private client: PiggyClient) {}
|
|
18
|
+
|
|
19
|
+
// ── Captcha ───────────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
status(tabId = "default"): Promise<CaptchaState> {
|
|
22
|
+
return this.client.send("captcha.status", { tabId });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
resolve(tabId = "default"): Promise<void> {
|
|
26
|
+
return this.client.send("captcha.resolve", { tabId });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
pause(tabId = "default"): Promise<void> {
|
|
30
|
+
return this.client.send("captcha.pause", { tabId });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
check(tabId = "default"): Promise<void> {
|
|
34
|
+
return this.client.send("captcha.check", { tabId });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setAutoRetry(enabled: boolean): Promise<void> {
|
|
38
|
+
return this.client.send("captcha.autoRetry", { enabled });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ── Block ─────────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
blockStatus(tabId = "default"): Promise<BlockState> {
|
|
44
|
+
return this.client.send("block.status", { tabId });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
blockRetry(tabId = "default"): Promise<void> {
|
|
48
|
+
return this.client.send("block.retry", { tabId });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ── Event subscriptions ───────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
onCaptcha(tabId: string, handler: (data: { captchaType: string; tabId: string }) => void): () => void {
|
|
54
|
+
return this.client.onEvent("captcha", tabId, handler);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
onCaptchaResolved(tabId: string, handler: (data: { tabId: string }) => void): () => void {
|
|
58
|
+
return this.client.onEvent("captcha:resolved", tabId, handler);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
onBlocked(tabId: string, handler: (data: { blockType: string; tabId: string }) => void): () => void {
|
|
62
|
+
return this.client.onEvent("blocked", tabId, handler);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
onBlockRetry(tabId: string, handler: (data: { tabId: string; proxy: string }) => void): () => void {
|
|
66
|
+
return this.client.onEvent("block:retry", tabId, handler);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ── Convenience: wait until captcha is resolved ───────────────────────────
|
|
70
|
+
|
|
71
|
+
waitForResolution(tabId = "default", timeoutMs = 300_000): Promise<void> {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
const timer = setTimeout(() => {
|
|
74
|
+
unsub();
|
|
75
|
+
reject(new Error(`captcha.waitForResolution: timed out after ${timeoutMs}ms`));
|
|
76
|
+
}, timeoutMs);
|
|
77
|
+
|
|
78
|
+
const unsub = this.onCaptchaResolved(tabId, () => {
|
|
79
|
+
clearTimeout(timer);
|
|
80
|
+
unsub();
|
|
81
|
+
resolve();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
logger.warn(`[captcha] waiting for manual resolution on tab ${tabId}…`);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ── Factory helper so site objects can expose a .captcha sub-namespace ────────
|
|
90
|
+
|
|
91
|
+
export function createCaptchaAPI(client: PiggyClient): CaptchaClient {
|
|
92
|
+
return new CaptchaClient(client);
|
|
93
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// piggy/capture/index.ts
|
|
2
|
+
import { PiggyClient } from "../client";
|
|
3
|
+
|
|
4
|
+
export interface CapturedRequest {
|
|
5
|
+
method: string;
|
|
6
|
+
url: string;
|
|
7
|
+
status: string;
|
|
8
|
+
type: string;
|
|
9
|
+
mime: string;
|
|
10
|
+
reqHeaders: string;
|
|
11
|
+
reqBody: string;
|
|
12
|
+
resHeaders: string;
|
|
13
|
+
resBody: string;
|
|
14
|
+
size: number;
|
|
15
|
+
timestamp: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface WebSocketFrame {
|
|
19
|
+
connectionId: string;
|
|
20
|
+
url: string;
|
|
21
|
+
direction: string;
|
|
22
|
+
data: string;
|
|
23
|
+
binary: boolean;
|
|
24
|
+
timestamp: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface CapturedCookie {
|
|
28
|
+
name: string;
|
|
29
|
+
value: string;
|
|
30
|
+
domain: string;
|
|
31
|
+
path: string;
|
|
32
|
+
httpOnly: boolean;
|
|
33
|
+
secure: boolean;
|
|
34
|
+
expires: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface StorageEntry {
|
|
38
|
+
key: string;
|
|
39
|
+
value: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class CaptureClient {
|
|
43
|
+
constructor(private client: PiggyClient) {}
|
|
44
|
+
|
|
45
|
+
start(tabId = "default"): Promise<void> {
|
|
46
|
+
return this.client.send("capture.start", { tabId });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
stop(tabId = "default"): Promise<void> {
|
|
50
|
+
return this.client.send("capture.stop", { tabId });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
requests(tabId = "default"): Promise<CapturedRequest[]> {
|
|
54
|
+
return this.client.send("capture.requests", { tabId });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
ws(tabId = "default"): Promise<WebSocketFrame[]> {
|
|
58
|
+
return this.client.send("capture.ws", { tabId });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
cookies(tabId = "default"): Promise<CapturedCookie[]> {
|
|
62
|
+
return this.client.send("capture.cookies", { tabId });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
storage(tabId = "default"): Promise<StorageEntry[]> {
|
|
66
|
+
return this.client.send("capture.storage", { tabId });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
clear(tabId = "default"): Promise<void> {
|
|
70
|
+
return this.client.send("capture.clear", { tabId });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function createCaptureAPI(client: PiggyClient): CaptureClient {
|
|
75
|
+
return new CaptureClient(client);
|
|
76
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// piggy/dialog/index.d.ts
|
|
2
|
+
import { PiggyClient } from "../client";
|
|
3
|
+
|
|
4
|
+
export interface DialogState {
|
|
5
|
+
pending: boolean;
|
|
6
|
+
type: string;
|
|
7
|
+
message: string;
|
|
8
|
+
defaultValue: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export declare class DialogClient {
|
|
12
|
+
constructor(client: PiggyClient);
|
|
13
|
+
|
|
14
|
+
accept(tabId?: string, text?: string): Promise<void>;
|
|
15
|
+
dismiss(tabId?: string): Promise<void>;
|
|
16
|
+
status(tabId?: string): Promise<DialogState>;
|
|
17
|
+
setAutoAction(tabId?: string, action: "accept" | "dismiss" | ""): Promise<void>;
|
|
18
|
+
upload(selector: string, filePath: string, tabId?: string): Promise<void>;
|
|
19
|
+
|
|
20
|
+
onDialog(
|
|
21
|
+
tabId: string,
|
|
22
|
+
handler: (data: { dialogType: string; message: string; defaultValue: string; tabId: string }) => void
|
|
23
|
+
): () => void;
|
|
24
|
+
|
|
25
|
+
waitAndAccept(tabId?: string, text?: string, timeoutMs?: number): Promise<DialogState>;
|
|
26
|
+
waitAndDismiss(tabId?: string, timeoutMs?: number): Promise<DialogState>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export declare function createDialogAPI(client: PiggyClient): DialogClient;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// piggy/dialog/index.ts
|
|
2
|
+
import { PiggyClient } from "../client";
|
|
3
|
+
import logger from "../logger";
|
|
4
|
+
|
|
5
|
+
export interface DialogState {
|
|
6
|
+
pending: boolean;
|
|
7
|
+
type: string; // "alert" | "confirm" | "prompt" | "beforeunload"
|
|
8
|
+
message: string;
|
|
9
|
+
defaultValue: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Event data from C++ (doesn't include pending)
|
|
13
|
+
interface DialogEventData {
|
|
14
|
+
dialogType: string;
|
|
15
|
+
message: string;
|
|
16
|
+
defaultValue: string;
|
|
17
|
+
tabId: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class DialogClient {
|
|
21
|
+
constructor(private client: PiggyClient) {}
|
|
22
|
+
|
|
23
|
+
accept(tabId = "default", text?: string): Promise<void> {
|
|
24
|
+
return this.client.send("dialog.accept", { tabId, ...(text !== undefined ? { text } : {}) });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
dismiss(tabId = "default"): Promise<void> {
|
|
28
|
+
return this.client.send("dialog.dismiss", { tabId });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
status(tabId = "default"): Promise<DialogState> {
|
|
32
|
+
return this.client.send("dialog.status", { tabId });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setAutoAction(tabId = "default", action: "accept" | "dismiss" | ""): Promise<void> {
|
|
36
|
+
return this.client.send("dialog.onDialog", { tabId, action });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
upload(selector: string, filePath: string, tabId = "default"): Promise<void> {
|
|
40
|
+
return this.client.send("upload", { selector, path: filePath, tabId });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onDialog(
|
|
44
|
+
tabId: string,
|
|
45
|
+
handler: (data: DialogEventData) => void
|
|
46
|
+
): () => void {
|
|
47
|
+
return this.client.onEvent("dialog", tabId, handler);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
waitAndAccept(tabId = "default", text?: string, timeoutMs = 30_000): Promise<DialogEventData> {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const timer = setTimeout(() => {
|
|
53
|
+
unsub();
|
|
54
|
+
reject(new Error(`dialog.waitAndAccept: timed out after ${timeoutMs}ms`));
|
|
55
|
+
}, timeoutMs);
|
|
56
|
+
|
|
57
|
+
const unsub = this.onDialog(tabId, async (data) => {
|
|
58
|
+
clearTimeout(timer);
|
|
59
|
+
unsub();
|
|
60
|
+
await this.accept(tabId, text);
|
|
61
|
+
resolve(data);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
waitAndDismiss(tabId = "default", timeoutMs = 30_000): Promise<DialogEventData> {
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
const timer = setTimeout(() => {
|
|
69
|
+
unsub();
|
|
70
|
+
reject(new Error(`dialog.waitAndDismiss: timed out after ${timeoutMs}ms`));
|
|
71
|
+
}, timeoutMs);
|
|
72
|
+
|
|
73
|
+
const unsub = this.onDialog(tabId, async (data) => {
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
unsub();
|
|
76
|
+
await this.dismiss(tabId);
|
|
77
|
+
resolve(data);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function createDialogAPI(client: PiggyClient): DialogClient {
|
|
84
|
+
return new DialogClient(client);
|
|
85
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// piggy/export/index.d.ts
|
|
2
|
+
import { PiggyClient } from "../client";
|
|
3
|
+
|
|
4
|
+
export interface CookieSetOptions {
|
|
5
|
+
name: string;
|
|
6
|
+
value: string;
|
|
7
|
+
domain: string;
|
|
8
|
+
/** @default "/" */
|
|
9
|
+
path?: string;
|
|
10
|
+
/** @default false */
|
|
11
|
+
httpOnly?: boolean;
|
|
12
|
+
/** @default false */
|
|
13
|
+
secure?: boolean;
|
|
14
|
+
/** Unix epoch seconds. Omit for a session cookie. */
|
|
15
|
+
expiry?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface CookieDeleteOptions {
|
|
19
|
+
name: string;
|
|
20
|
+
domain: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface CapturedRequest {
|
|
24
|
+
method: string;
|
|
25
|
+
url: string;
|
|
26
|
+
status: string;
|
|
27
|
+
type: string;
|
|
28
|
+
mime: string;
|
|
29
|
+
reqHeaders: string;
|
|
30
|
+
reqBody: string;
|
|
31
|
+
resHeaders: string;
|
|
32
|
+
resBody: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface WebSocketFrame {
|
|
36
|
+
url: string;
|
|
37
|
+
direction: string;
|
|
38
|
+
data: string;
|
|
39
|
+
binary: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface CapturedCookie {
|
|
43
|
+
name: string;
|
|
44
|
+
value: string;
|
|
45
|
+
domain: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface SessionExport {
|
|
49
|
+
url: string;
|
|
50
|
+
requests: CapturedRequest[];
|
|
51
|
+
ws: WebSocketFrame[];
|
|
52
|
+
cookies: CapturedCookie[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface SessionPaths {
|
|
56
|
+
workDir: string;
|
|
57
|
+
cookies: string;
|
|
58
|
+
profile: string;
|
|
59
|
+
ws: string;
|
|
60
|
+
pings: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface InterceptRule {
|
|
64
|
+
pattern: string;
|
|
65
|
+
block?: boolean;
|
|
66
|
+
redirect?: string;
|
|
67
|
+
setHeaders?: Record<string, string>;
|
|
68
|
+
removeHeaders?: string[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface ExposedFunctionCall {
|
|
72
|
+
name: string;
|
|
73
|
+
callId: string;
|
|
74
|
+
data: string;
|
|
75
|
+
tabId: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export declare class ExportClient {
|
|
79
|
+
constructor(client: PiggyClient);
|
|
80
|
+
|
|
81
|
+
// Cookies
|
|
82
|
+
setCookie(opts: CookieSetOptions, tabId?: string): Promise<void>;
|
|
83
|
+
deleteCookie(opts: CookieDeleteOptions, tabId?: string): Promise<void>;
|
|
84
|
+
|
|
85
|
+
// Session
|
|
86
|
+
sessionReload(tabId?: string): Promise<void>;
|
|
87
|
+
cookiesPath(tabId?: string): Promise<string>;
|
|
88
|
+
profilePath(tabId?: string): Promise<string>;
|
|
89
|
+
wsPath(tabId?: string): Promise<string>;
|
|
90
|
+
pingsPath(tabId?: string): Promise<string>;
|
|
91
|
+
sessionPaths(tabId?: string): Promise<SessionPaths>;
|
|
92
|
+
setWsSave(enabled: boolean, tabId?: string): Promise<void>;
|
|
93
|
+
setPingsSave(enabled: boolean, tabId?: string): Promise<void>;
|
|
94
|
+
|
|
95
|
+
// Intercept rules
|
|
96
|
+
addInterceptRule(rule: InterceptRule, tabId?: string): Promise<void>;
|
|
97
|
+
clearInterceptRules(tabId?: string): Promise<void>;
|
|
98
|
+
|
|
99
|
+
// Session export / import
|
|
100
|
+
exportSession(tabId?: string): Promise<SessionExport>;
|
|
101
|
+
importSession(data: SessionExport, tabId?: string): Promise<void>;
|
|
102
|
+
|
|
103
|
+
// Exposed functions
|
|
104
|
+
exposeFunction(name: string, tabId?: string): Promise<void>;
|
|
105
|
+
resolveExposed(callId: string, result: string, isError?: boolean, tabId?: string): Promise<void>;
|
|
106
|
+
|
|
107
|
+
// Init scripts
|
|
108
|
+
addInitScript(js: string, tabId?: string): Promise<void>;
|
|
109
|
+
|
|
110
|
+
// Events
|
|
111
|
+
onExposedFunctionCalled(
|
|
112
|
+
tabId: string,
|
|
113
|
+
handler: (call: ExposedFunctionCall) => void
|
|
114
|
+
): () => void;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export declare function createExportAPI(client: PiggyClient): ExportClient;
|