@ceki/n8n-nodes-ceki 0.2.8 → 0.2.9
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 +6 -6
- package/dist/index.js +85 -238
- package/dist/index.js.map +3 -3
- package/dist/nodes/BrowserCeki/BrowserCeki.node.js +85 -238
- package/dist/nodes/BrowserCeki/BrowserCeki.node.js.map +3 -3
- package/dist/nodes/CekiContract/CekiContract.node.js.map +2 -2
- package/dist/nodes/recipes/CekiCaptchaScrape/CekiCaptchaScrape.node.js +8 -64
- package/dist/nodes/recipes/CekiCaptchaScrape/CekiCaptchaScrape.node.js.map +2 -2
- package/dist/nodes/recipes/CekiScreenshotGeo/CekiScreenshotGeo.node.js +8 -64
- package/dist/nodes/recipes/CekiScreenshotGeo/CekiScreenshotGeo.node.js.map +2 -2
- package/package.json +1 -1
|
@@ -120,53 +120,17 @@ var CekiClient = class {
|
|
|
120
120
|
this._sendRaw({ type: "resume", session_id: sessionId });
|
|
121
121
|
return this._awaitResume(sessionId);
|
|
122
122
|
}
|
|
123
|
-
/** Close the WS connection — session stays alive in grace.
|
|
124
|
-
|
|
125
|
-
* before a new connection with the same renterId is established
|
|
126
|
-
* (avoids the close-handler race condition).
|
|
127
|
-
*/
|
|
128
|
-
async disconnect() {
|
|
123
|
+
/** Close the WS connection — session stays alive in grace. */
|
|
124
|
+
disconnect() {
|
|
129
125
|
this._closed = true;
|
|
130
126
|
this._activeSessions.clear();
|
|
131
127
|
this._pendingRents.clear();
|
|
132
128
|
this._pendingResumes.clear();
|
|
133
|
-
|
|
134
|
-
const ws = this._ws;
|
|
135
|
-
if (ws.readyState === WebSocket.CLOSED) {
|
|
136
|
-
this._ws = null;
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
if (ws.readyState === WebSocket.CLOSING) {
|
|
140
|
-
await new Promise((r) => {
|
|
141
|
-
ws.onclose = () => {
|
|
142
|
-
this._connected = false;
|
|
143
|
-
r();
|
|
144
|
-
};
|
|
145
|
-
});
|
|
146
|
-
this._ws = null;
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
await new Promise((r) => {
|
|
150
|
-
const t = setTimeout(() => {
|
|
151
|
-
r();
|
|
152
|
-
}, 5e3);
|
|
153
|
-
ws.onclose = () => {
|
|
154
|
-
this._connected = false;
|
|
155
|
-
clearTimeout(t);
|
|
156
|
-
r();
|
|
157
|
-
};
|
|
158
|
-
try {
|
|
159
|
-
ws.close();
|
|
160
|
-
} catch {
|
|
161
|
-
clearTimeout(t);
|
|
162
|
-
r();
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
this._ws = null;
|
|
129
|
+
this._closeWs();
|
|
166
130
|
}
|
|
167
131
|
/** Close everything. */
|
|
168
|
-
|
|
169
|
-
|
|
132
|
+
close() {
|
|
133
|
+
this.disconnect();
|
|
170
134
|
}
|
|
171
135
|
// ── private ────────────────────────────────────────────────
|
|
172
136
|
_awaitRent(key, scheduleId, timeoutMs) {
|
|
@@ -256,33 +220,13 @@ var CekiClient = class {
|
|
|
256
220
|
_onMatch(msg) {
|
|
257
221
|
const scheduleId = Number(msg.schedule_id ?? 0);
|
|
258
222
|
const eventId = msg.event_id ? String(msg.event_id) : null;
|
|
259
|
-
const sessionId = String(msg.session_id ?? "");
|
|
260
|
-
if (sessionId && this._ws?.readyState === WebSocket.OPEN) {
|
|
261
|
-
try {
|
|
262
|
-
this._ws.send(JSON.stringify({ type: "match_ack", session_id: sessionId }));
|
|
263
|
-
} catch {
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
223
|
let pending = this._pendingRents.get(`event:${eventId}`);
|
|
267
224
|
if (!pending) pending = this._pendingRents.get(`rent:${scheduleId}`);
|
|
268
225
|
if (pending) {
|
|
269
226
|
this._pendingRents.delete(`event:${eventId}`);
|
|
270
227
|
this._pendingRents.delete(`rent:${scheduleId}`);
|
|
271
228
|
pending.resolve({
|
|
272
|
-
session_id:
|
|
273
|
-
schedule_id: scheduleId,
|
|
274
|
-
event_id: eventId,
|
|
275
|
-
chat_topic_id: msg.chat_topic_id ? String(msg.chat_topic_id) : null,
|
|
276
|
-
provider_user_id: msg.provider_user_id != null ? Number(msg.provider_user_id) : null,
|
|
277
|
-
browser_info: msg.browser_info ?? {}
|
|
278
|
-
});
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
const resumePending = sessionId ? this._pendingResumes.get(sessionId) : null;
|
|
282
|
-
if (resumePending) {
|
|
283
|
-
this._pendingResumes.delete(sessionId);
|
|
284
|
-
resumePending.resolve({
|
|
285
|
-
session_id: sessionId,
|
|
229
|
+
session_id: String(msg.session_id ?? ""),
|
|
286
230
|
schedule_id: scheduleId,
|
|
287
231
|
event_id: eventId,
|
|
288
232
|
chat_topic_id: msg.chat_topic_id ? String(msg.chat_topic_id) : null,
|
|
@@ -325,9 +269,9 @@ var CekiClient = class {
|
|
|
325
269
|
const browser = this._activeSessions.get(sessionId);
|
|
326
270
|
if (!browser) return;
|
|
327
271
|
const id = Number(msg.id ?? 0);
|
|
328
|
-
const pending =
|
|
272
|
+
const pending = this._pendingCdp.get(id);
|
|
329
273
|
if (!pending) return;
|
|
330
|
-
|
|
274
|
+
this._pendingCdp.delete(id);
|
|
331
275
|
if (msg.error) {
|
|
332
276
|
pending.reject(new Error(String(msg.error.message ?? "CDP error")));
|
|
333
277
|
} else {
|
|
@@ -370,9 +314,9 @@ var CekiBrowser = class {
|
|
|
370
314
|
async navigate(url, timeoutMs) {
|
|
371
315
|
await this.send("Page.navigate", { url }, timeoutMs);
|
|
372
316
|
}
|
|
373
|
-
async click(
|
|
374
|
-
await this.send("Input.dispatchMouseEvent", { type: "mousePressed", x
|
|
375
|
-
await this.send("Input.dispatchMouseEvent", { type: "mouseReleased", x
|
|
317
|
+
async click(x, y) {
|
|
318
|
+
await this.send("Input.dispatchMouseEvent", { type: "mousePressed", x, y, button: "left", clickCount: 1 });
|
|
319
|
+
await this.send("Input.dispatchMouseEvent", { type: "mouseReleased", x, y, button: "left", clickCount: 1 });
|
|
376
320
|
}
|
|
377
321
|
async type(text) {
|
|
378
322
|
await this.send("Ceki.typeText", { text });
|
|
@@ -447,7 +391,7 @@ var BrowserCeki = class {
|
|
|
447
391
|
icon: "file:ceki.png",
|
|
448
392
|
group: ["transform"],
|
|
449
393
|
version: 1,
|
|
450
|
-
subtitle: '={{ "Ceki: " + $
|
|
394
|
+
subtitle: '={{ "Ceki: " + $operation }}',
|
|
451
395
|
description: "Rent a real human browser and control it: rent, navigate, click, type, screenshot, solve captchas, and more",
|
|
452
396
|
defaults: { name: "Browser Ceki" },
|
|
453
397
|
inputs: ["main"],
|
|
@@ -490,7 +434,7 @@ var BrowserCeki = class {
|
|
|
490
434
|
type: "string",
|
|
491
435
|
default: "",
|
|
492
436
|
placeholder: "RU, EE, US\u2026",
|
|
493
|
-
displayOptions: { show: { operation: ["search"] } }
|
|
437
|
+
displayOptions: { show: { operation: ["rent", "search"] } }
|
|
494
438
|
},
|
|
495
439
|
{
|
|
496
440
|
displayName: "Max $/min",
|
|
@@ -498,14 +442,14 @@ var BrowserCeki = class {
|
|
|
498
442
|
type: "number",
|
|
499
443
|
typeOptions: { numberPrecision: 4 },
|
|
500
444
|
default: 0.02,
|
|
501
|
-
displayOptions: { show: { operation: ["search"] } }
|
|
445
|
+
displayOptions: { show: { operation: ["rent", "search"] } }
|
|
502
446
|
},
|
|
503
447
|
{
|
|
504
448
|
displayName: "Min rating",
|
|
505
449
|
name: "minRating",
|
|
506
450
|
type: "number",
|
|
507
451
|
default: 0,
|
|
508
|
-
displayOptions: { show: { operation: ["
|
|
452
|
+
displayOptions: { show: { operation: ["rent"] } }
|
|
509
453
|
},
|
|
510
454
|
{
|
|
511
455
|
displayName: "Profile mode",
|
|
@@ -666,39 +610,28 @@ var BrowserCeki = class {
|
|
|
666
610
|
for (let i = 0; i < items.length; i++) {
|
|
667
611
|
const op = this.getNodeParameter("operation", i);
|
|
668
612
|
const client = new CekiClient(token);
|
|
613
|
+
await client.connect();
|
|
669
614
|
let browser;
|
|
670
|
-
let needFullClose = false;
|
|
671
615
|
try {
|
|
672
|
-
await client.connect();
|
|
673
616
|
if (op === "rent") {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
} catch (e) {
|
|
682
|
-
throw new Error(`Rent failed: ${e.message}`);
|
|
683
|
-
} finally {
|
|
684
|
-
await client.disconnect();
|
|
685
|
-
}
|
|
617
|
+
const sid2 = await resolveSid(i, client);
|
|
618
|
+
const mode = this.getNodeParameter("mode", i);
|
|
619
|
+
browser = await client.rent(sid2, { mode });
|
|
620
|
+
out.push({
|
|
621
|
+
json: { session_id: browser.sessionId, schedule_id: sid2, mode }
|
|
622
|
+
});
|
|
623
|
+
await client.disconnect();
|
|
686
624
|
continue;
|
|
687
625
|
}
|
|
688
626
|
if (op === "search") {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
} catch (e) {
|
|
698
|
-
throw new Error(`Search failed: ${e.message}`);
|
|
699
|
-
} finally {
|
|
700
|
-
await client.disconnect();
|
|
701
|
-
}
|
|
627
|
+
const geo = this.getNodeParameter("geo", i);
|
|
628
|
+
const maxPrice = this.getNodeParameter("maxPrice", i);
|
|
629
|
+
const list = await client.search({
|
|
630
|
+
geo: geo || void 0,
|
|
631
|
+
max_price_per_min: maxPrice
|
|
632
|
+
});
|
|
633
|
+
out.push({ json: { browsers: list, count: list.length } });
|
|
634
|
+
await client.disconnect();
|
|
702
635
|
continue;
|
|
703
636
|
}
|
|
704
637
|
if (op === "full") {
|
|
@@ -707,11 +640,7 @@ var BrowserCeki = class {
|
|
|
707
640
|
if (demoMode) {
|
|
708
641
|
sid2 = 99999;
|
|
709
642
|
} else {
|
|
710
|
-
|
|
711
|
-
sid2 = await resolveSid(i, client);
|
|
712
|
-
} catch (e) {
|
|
713
|
-
throw new Error(`Full: resolve schedule failed: ${e.message}`);
|
|
714
|
-
}
|
|
643
|
+
sid2 = await resolveSid(i, client);
|
|
715
644
|
}
|
|
716
645
|
const mode = this.getNodeParameter("mode", i);
|
|
717
646
|
const url = this.getNodeParameter("url", i);
|
|
@@ -724,18 +653,14 @@ var BrowserCeki = class {
|
|
|
724
653
|
const demoPng = Buffer.from("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", "base64");
|
|
725
654
|
binary = await this.helpers.prepareBinaryData(demoPng, "screenshot.png", "image/png");
|
|
726
655
|
} else {
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
await browser.close();
|
|
736
|
-
} catch (e) {
|
|
737
|
-
throw new Error(`Full op failed at step "${browser?.sessionId ? "navigate/screenshot" : "rent"}": ${e.message}`);
|
|
738
|
-
}
|
|
656
|
+
browser = await client.rent(sid2, { mode });
|
|
657
|
+
session_id = browser.sessionId;
|
|
658
|
+
await browser.navigate(url);
|
|
659
|
+
await sleep(ms);
|
|
660
|
+
const shot = await browser.screenshot({ format: "png", fullPage: true });
|
|
661
|
+
const data = shot.toString("base64");
|
|
662
|
+
binary = await this.helpers.prepareBinaryData(Buffer.from(data, "base64"), "screenshot.png", "image/png");
|
|
663
|
+
await browser.close();
|
|
739
664
|
}
|
|
740
665
|
out.push({
|
|
741
666
|
json: {
|
|
@@ -748,86 +673,57 @@ var BrowserCeki = class {
|
|
|
748
673
|
binary: { data: binary }
|
|
749
674
|
});
|
|
750
675
|
} finally {
|
|
751
|
-
await client.close()
|
|
752
|
-
});
|
|
676
|
+
await client.close();
|
|
753
677
|
}
|
|
754
678
|
continue;
|
|
755
679
|
}
|
|
756
680
|
const sessionId = this.getNodeParameter("sessionId", i);
|
|
757
|
-
|
|
758
|
-
browser = await client.resume(sessionId);
|
|
759
|
-
} catch (e) {
|
|
760
|
-
throw new Error(`Resume session "${sessionId}" failed: ${e.message}. Session may have expired or still be in grace.`);
|
|
761
|
-
}
|
|
681
|
+
browser = await client.resume(sessionId);
|
|
762
682
|
const sid = browser.sessionId;
|
|
763
683
|
switch (op) {
|
|
764
684
|
case "navigate": {
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
out.push({ json: { session_id: sid, url } });
|
|
769
|
-
} catch (e) {
|
|
770
|
-
throw new Error(`Navigate failed: ${e.message}`);
|
|
771
|
-
}
|
|
685
|
+
const url = this.getNodeParameter("url", i);
|
|
686
|
+
await browser.navigate(url);
|
|
687
|
+
out.push({ json: { session_id: sid, url } });
|
|
772
688
|
break;
|
|
773
689
|
}
|
|
774
690
|
case "click": {
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
out.push({ json: { session_id: sid, clicked: [x2, y2] } });
|
|
780
|
-
} catch (e) {
|
|
781
|
-
throw new Error(`Click at (${x},${y}) failed: ${e.message}`);
|
|
782
|
-
}
|
|
691
|
+
const x = this.getNodeParameter("x", i);
|
|
692
|
+
const y = this.getNodeParameter("y", i);
|
|
693
|
+
await browser.click(x, y);
|
|
694
|
+
out.push({ json: { session_id: sid, clicked: [x, y] } });
|
|
783
695
|
break;
|
|
784
696
|
}
|
|
785
697
|
case "type": {
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
out.push({ json: { session_id: sid, typed: text } });
|
|
790
|
-
} catch (e) {
|
|
791
|
-
throw new Error(`Type failed: ${e.message}`);
|
|
792
|
-
}
|
|
698
|
+
const text = this.getNodeParameter("text", i);
|
|
699
|
+
await browser.type(text);
|
|
700
|
+
out.push({ json: { session_id: sid, typed: text } });
|
|
793
701
|
break;
|
|
794
702
|
}
|
|
795
703
|
case "scroll": {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
out.push({ json: { session_id: sid, scrolled: deltaY } });
|
|
800
|
-
} catch (e) {
|
|
801
|
-
throw new Error(`Scroll failed: ${e.message}`);
|
|
802
|
-
}
|
|
704
|
+
const deltaY = this.getNodeParameter("deltaY", i);
|
|
705
|
+
await browser.scroll(deltaY);
|
|
706
|
+
out.push({ json: { session_id: sid, scrolled: deltaY } });
|
|
803
707
|
break;
|
|
804
708
|
}
|
|
805
709
|
case "screenshot": {
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
out.push({ json: { session_id: sid }, binary: { data: binary } });
|
|
817
|
-
} catch (e) {
|
|
818
|
-
throw new Error(`Screenshot failed: ${e.message}`);
|
|
819
|
-
}
|
|
710
|
+
const format = this.getNodeParameter("format", i);
|
|
711
|
+
const fullPage = this.getNodeParameter("fullPage", i);
|
|
712
|
+
const shot = await browser.screenshot({ format, fullPage });
|
|
713
|
+
const data = format === "base64" ? shot.data : shot.toString("base64");
|
|
714
|
+
const binary = await this.helpers.prepareBinaryData(
|
|
715
|
+
Buffer.from(data, "base64"),
|
|
716
|
+
"screenshot.png",
|
|
717
|
+
"image/png"
|
|
718
|
+
);
|
|
719
|
+
out.push({ json: { session_id: sid }, binary: { data: binary } });
|
|
820
720
|
break;
|
|
821
721
|
}
|
|
822
722
|
case "snapshot": {
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
});
|
|
828
|
-
} catch (e) {
|
|
829
|
-
throw new Error(`Snapshot failed: ${e.message}`);
|
|
830
|
-
}
|
|
723
|
+
const snap = await browser.snapshot();
|
|
724
|
+
out.push({
|
|
725
|
+
json: { session_id: sid, screenshot: snap.screenshot }
|
|
726
|
+
});
|
|
831
727
|
break;
|
|
832
728
|
}
|
|
833
729
|
case "wait": {
|
|
@@ -864,79 +760,30 @@ var BrowserCeki = class {
|
|
|
864
760
|
break;
|
|
865
761
|
}
|
|
866
762
|
case "upload": {
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
out.push({ json: { session_id: sid, uploaded: res } });
|
|
878
|
-
} catch (e) {
|
|
879
|
-
throw new Error(`Upload failed: ${e.message}`);
|
|
880
|
-
}
|
|
763
|
+
const selector = this.getNodeParameter("selector", i);
|
|
764
|
+
const bpn = this.getNodeParameter("binaryPropertyName", i);
|
|
765
|
+
const bin = items[i].binary?.[bpn];
|
|
766
|
+
if (!bin) throw new Error(`Binary property "${bpn}" not found on input`);
|
|
767
|
+
const stream = await this.helpers.getBinaryStream(bin.id);
|
|
768
|
+
const chunks = [];
|
|
769
|
+
for await (const c of stream) chunks.push(c);
|
|
770
|
+
const buf = Buffer.concat(chunks);
|
|
771
|
+
const res = await browser.upload(selector, buf);
|
|
772
|
+
out.push({ json: { session_id: sid, uploaded: res } });
|
|
881
773
|
break;
|
|
882
774
|
}
|
|
883
775
|
case "close": {
|
|
884
|
-
|
|
885
|
-
await browser.close().catch(() => {
|
|
886
|
-
});
|
|
887
|
-
} catch {
|
|
888
|
-
}
|
|
889
|
-
await new Promise((resolve) => {
|
|
890
|
-
const stopWs = new WebSocket("wss://browser.ceki.me/ws/agent", [`bearer.${token}`]);
|
|
891
|
-
const abortTimer = AbortSignal.timeout(1e4);
|
|
892
|
-
const onTimer = () => {
|
|
893
|
-
try {
|
|
894
|
-
stopWs.close();
|
|
895
|
-
} catch {
|
|
896
|
-
}
|
|
897
|
-
resolve();
|
|
898
|
-
};
|
|
899
|
-
abortTimer.addEventListener("abort", onTimer, { once: true });
|
|
900
|
-
stopWs.onopen = () => {
|
|
901
|
-
stopWs.send(JSON.stringify({ type: "stop", session_id: sessionId, reason: "n8n close" }));
|
|
902
|
-
};
|
|
903
|
-
stopWs.onmessage = (ev) => {
|
|
904
|
-
try {
|
|
905
|
-
const msg = JSON.parse(ev.data);
|
|
906
|
-
if (msg.type === "session_ended") {
|
|
907
|
-
abortTimer.removeEventListener("abort", onTimer);
|
|
908
|
-
try {
|
|
909
|
-
stopWs.close();
|
|
910
|
-
} catch {
|
|
911
|
-
}
|
|
912
|
-
resolve();
|
|
913
|
-
}
|
|
914
|
-
} catch {
|
|
915
|
-
}
|
|
916
|
-
};
|
|
917
|
-
stopWs.onerror = () => {
|
|
918
|
-
abortTimer.removeEventListener("abort", onTimer);
|
|
919
|
-
resolve();
|
|
920
|
-
};
|
|
921
|
-
stopWs.onclose = () => {
|
|
922
|
-
abortTimer.removeEventListener("abort", onTimer);
|
|
923
|
-
resolve();
|
|
924
|
-
};
|
|
925
|
-
});
|
|
776
|
+
await browser.close();
|
|
926
777
|
out.push({ json: { closed: true, session_id: sessionId } });
|
|
927
778
|
break;
|
|
928
779
|
}
|
|
929
780
|
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
await client.close();
|
|
935
|
-
} else {
|
|
936
|
-
await client.disconnect();
|
|
937
|
-
}
|
|
938
|
-
} catch {
|
|
781
|
+
if (op === "close") {
|
|
782
|
+
await client.close();
|
|
783
|
+
} else {
|
|
784
|
+
await client.disconnect();
|
|
939
785
|
}
|
|
786
|
+
} finally {
|
|
940
787
|
}
|
|
941
788
|
}
|
|
942
789
|
return [out];
|