Deno में reCAPTCHA कैसे हल करें: Permissions और Timeouts

solve recaptcha in deno - How to Solve reCAPTCHA in Deno: Permissions and Timeouts

Deno में reCAPTCHA हल करने के लिए, CapSkip Node.js SDK को npm specifier के ज़रिए import करें और सॉल्वर का पता एनवायरनमेंट से खुद पढ़ें। फिर script को ऐसे permission flags के साथ चलाएँ जिनमें सिर्फ़ CapSkip और आपकी साइट का नाम हो। CapSkip आपके अपने Windows PC पर चलता है, इसलिए कोई प्रति-हल बिल नहीं बनता। कोड छोटा है। मुश्किल हिस्सा Deno का permission मॉडल है। SDK किसी रोकी गई कॉल को नेटवर्क error के रूप में बताता है। जो CapSkip चुप हो जाता है, वह script को बिना किसी error और बिना exit के अटका देता है। और timeout जोड़ने का आम तरीका प्रोसेस को पूरी समय-सीमा तक चालू रखता है। यह गाइड इन सभी को कवर करती है।

आपको क्या चाहिए

  • किसी Windows PC पर चल रहा CapSkip, जिसमें reCAPTCHA सॉल्वर चालू हो। पहली बार शुरू करने के चरण सेटअप गाइड में समझाए गए हैं।
  • Deno 2। नीचे सब कुछ Windows 11 पर Deno 2.9.6 के साथ चलाया गया, और फिर 2.9.7 पर भी, npm के capskip 1.3.0 के साथ।
  • एक PowerShell prompt। कमांड PowerShell syntax में लिखी गई हैं।
  • एक ऐसा पेज जिसके फॉर्म में reCAPTCHA v2 checkbox हो। उदाहरण Django जैसे एक फॉर्म में लॉग इन करता है जिसमें CSRF token होता है। फ़ील्ड के नाम अपनी साइट के हिसाब से बदलें।
  • सॉल्वर के लिए एक पता। Local मोड में CapSkip केवल उसी डिवाइस के लिए 127.0.0.1 पर जवाब देता है। Server मोड में वह आपके नेटवर्क पते या पब्लिक IP पर सुनता है, ताकि किसी दूसरी मशीन पर चल रही script API के ज़रिए उसे कॉल कर सके। दोनों यहाँ सेट किए जाते हैं: कनेक्शन सेटिंग्स.

नीचे की माप एक ही PC पर चल रहे mock CapSkip और mock लॉगिन पेज से ली गई हैं (यानी टेस्ट के लिए बनाए गए नकली CapSkip और नकली पेज), और इनके साथ असली Deno और असली SDK इस्तेमाल हुआ। permission errors, polling का शेड्यूल और अटकने का व्यवहार Deno और SDK के अपने हैं, इसलिए वे आपकी साइट पर भी वैसे ही रहते हैं। हल करने का समय और लॉगिन पेज के स्वीकार व अस्वीकार करने के नियम mock के अपने हैं।

स्टेप 1: Deno इंस्टॉल करें और प्रोजेक्ट बनाएँ

Deno को उसके आधिकारिक installer से या winget से इंस्टॉल करें। Deno के इंस्टॉलेशन पेज पर बाकी विकल्प दिए गए हैं, जैसे Scoop और Chocolatey।

# PowerShell: the official installer (or: winget install DenoLand.Deno)
irm https://deno.land/install.ps1 | iex
deno --version

फिर एक प्रोजेक्ट फ़ोल्डर बनाएँ और कुछ भी चलाने से पहले उसमें एक deno.json रखें। import map SDK का वर्ज़न पिन कर देता है और script को लंबे npm specifier की जगह बस "capskip" लिखने देता है।

{
  "imports": {
    "capskip": "npm:[email protected]"
  }
}

उस फ़ाइल के बनने से पहले deno add न चलाएँ। अगर आपके प्रोजेक्ट के ऊपर किसी फ़ोल्डर में package.json रखी है, जो यूज़र प्रोफ़ाइल में आम बात है, तो Deno प्रोजेक्ट को Node प्रोजेक्ट मान लेता है। तब npm:[email protected] का import Could not find "capskip" in a node_modules folder के साथ फेल हो जाता है। बिना वर्ज़न वाला import चुपचाप वही capskip लोड कर लेता है जो वहाँ ऊपर इंस्टॉल है। टेस्ट वाले PC पर वह पुराना 1.0.2 था। deno.json के बिना deno add चलाने से तो वह parent package.json भी बदल गई। आपके अपने फ़ोल्डर में deno.json होने पर Deno उसी फ़ोल्डर को प्रोजेक्ट का root मानता है।

स्टेप 2: SDK import करें और सेटिंग्स पढ़ें

स्टेप 2 से 5 का कोड solve.js नाम की एक फ़ाइल में, दिखाए गए क्रम में सेव करें। पूरी फ़ाइल इस गाइड के आख़िर के पास फिर से दी गई है। Deno इसे ES module के रूप में चलाता है, इसलिए SDK README की require कॉल यहाँ require is not defined के साथ फेल हो जाती है। named import इस्तेमाल करें। default import भी फेल होता है, क्योंकि वह आपको पूरा exports object थमा देता है: new CapSkip() कॉल करने पर CapSkip is not a constructor error आता है।

import { CapSkip } from "capskip";

// The SDK never reads the environment, so read it here and pass it in.
const host = Deno.env.get("CAPSKIP_HOST") ?? "127.0.0.1";
const port = Number(Deno.env.get("CAPSKIP_PORT") ?? 8080);
const apiKey = Deno.env.get("CAPSKIP_API_KEY") ?? "capskip";
const solver = new CapSkip({ host, port, apiKey });

// The login page to solve, passed on the command line.
const pageUrl = Deno.args[0] ?? "https://example.com/login";

SDK एनवायरनमेंट वेरिएबल खुद नहीं पढ़ता, इसलिए script उन्हें पढ़ती है और constructor को पास करती है। डिफ़ॉल्ट वैल्यू की वजह से फ़ाइल बिना किसी सेटअप के चल जाती है। CAPSKIP_API_KEY तभी मायने रखता है जब आपने CapSkip में API key validation चालू किया हो।

स्टेप 3: पेज fetch करें और उसकी cookies रखें

Deno के fetch में कोई cookie jar नहीं है, इसलिए script खुद एक रखती है। वह हर Set-Cookie लाइन को getSetCookie से पढ़ती है। इसकी जगह set-cookie पर headers.get कॉल करने से सारी लाइनें एक स्ट्रिंग में चिपक जाती हैं। cookie की Expires तारीख में कॉमा होता है, इसलिए कॉमा पर सीधा-सादा split cookies को गलत जगहों से काट देता है।

// Deno's fetch keeps no cookies, so collect every Set-Cookie line.
// (headers.get("set-cookie") would glue them into one string.)
const jar = new Map();

/** @param {Response} response */
function keepCookies(response) {
  for (const line of response.headers.getSetCookie()) {
    const [pair] = line.split(";");
    const eq = pair.indexOf("=");
    jar.set(pair.slice(0, eq).trim(), pair.slice(eq + 1).trim());
  }
}
const cookies = () => Array.from(jar, ([k, v]) => `${k}=${v}`).join("; ");

आगे script लॉगिन पेज लोड करती है और उसमें से sitekey और CSRF token पढ़ती है। दोनों patterns को अपने पेज के markup के हिसाब से बदलें।

const page = await fetch(pageUrl);
keepCookies(page);
const html = await page.text();

// Adjust these two patterns to your page's markup.
const sitekey = html.match(/data-sitekey="([^"]+)"/)?.[1];
const csrf = html.match(/name="csrfmiddlewaretoken" value="([^"]+)"/)?.[1];
if (!sitekey || !csrf) throw new Error("sitekey or CSRF token not found");

स्टेप 4: CapSkip से token माँगें

एक कॉल पूरा काम कर देती है। यह task सबमिट करती है, जवाब के लिए poll करती है और token लौटा देती है। SDK पहले तुरंत poll करता है, फिर एक चौथाई सेकंड इंतज़ार करता है और हर बार इंतज़ार को दोगुना करता जाता है, ज़्यादा से ज़्यादा 5 सेकंड तक। जो solve CapSkip ने एक सेकंड में पूरा किया, वह टेस्टिंग में करीब 1.8 सेकंड में लौटा, बिल्कुल Node जितना ही।

// code is typed "string or object" (Capy shares the field), so
// String() keeps deno check quiet.
const { code } = await solver.recaptcha(sitekey, pageUrl);
const token = String(code);

नतीजे में एक code फ़ील्ड होता है, और वही token है। SDK की type फ़ाइल उसे string या object घोषित करती है, क्योंकि कुछ कैप्चा टाइप उसी फ़ील्ड में एक object लौटाते हैं। String() उसे सादी string में बदल देता है। आगे का एक सेक्शन इस कॉल में timeout जोड़ता है।

स्टेप 5: फॉर्म पोस्ट करें और नतीजा जाँचें

script token को g-recaptcha-response फ़ील्ड में, फॉर्म के बाकी फ़ील्ड के साथ पोस्ट करती है। दो बातें मायने रखती हैं। Deno का fetch कोई Referer नहीं भेजता, और HTTPS पर Django जैसी सख़्त साइट उसके बिना आई फॉर्म पोस्ट को ठुकरा देती है, इसलिए script उसे सेट करती है। और fetch कॉल redirect manual इस्तेमाल करती है, ताकि 302 वापस आए और उसकी नई session cookie पढ़ी जा सके। redirects को फ़ॉलो करने वाले डिफ़ॉल्ट पर 302 वाली cookie खो जाती है और लॉगिन 200 के साथ वापस फॉर्म पर ही पहुँच जाता है।

// fetch sends no Referer, and a strict site rejects the post without
// one. redirect "manual" keeps the 302 so we can read its new cookie.
const response = await fetch(pageUrl, {
  method: "POST",
  redirect: "manual",
  headers: { Cookie: cookies(), Referer: pageUrl },
  body: new URLSearchParams({
    csrfmiddlewaretoken: csrf,
    username: "YOUR_USERNAME",
    password: "YOUR_PASSWORD",
    "g-recaptcha-response": token,
  }),
});
keepCookies(response);

ठुकराया गया लॉगिन अक्सर 200 के साथ फिर वही फॉर्म दिखाता है। इसलिए script 302 के अलावा हर जवाब को नाकामी मानती है, फिर ऐसे marker को ढूँढती है जो सिर्फ़ लॉग इन किया हुआ पेज दिखाता है। Welcome back की जगह अपनी साइट का कोई टेक्स्ट रखें। जो script ठुकराए गए लॉगिन पर कामयाबी बताती है, वह फेल होने वाली script से भी बुरी है।

// A good login answers 302 and rotates the session cookie.
if (response.status !== 302) {
  const body = await response.text();
  throw new Error(`login rejected: ${response.status} ${body}`);
}
const next = new URL(response.headers.get("location") ?? "/", pageUrl);
const home = await fetch(next, { headers: { Cookie: cookies() } });

// Swap "Welcome back" for a marker your own site shows after login.
const ok = (await home.text()).includes("Welcome back");
console.log(ok ? "logged in" : "NOT logged in");
if (!ok) Deno.exit(2);

स्टेप 6: सबसे छोटे permission सेट के साथ चलाएँ

जब तक आप अनुमति न दें, Deno नेटवर्क, एनवायरनमेंट और फ़ाइल access को रोके रखता है। Deno में reCAPTCHA हल करने के लिए इस script को दो चीज़ें चाहिए, और नीचे की कमांड ठीक वही देती है।

deno run `
  --allow-env=CAPSKIP_HOST,CAPSKIP_PORT,CAPSKIP_API_KEY `
  --allow-net=127.0.0.1:8080,example.com `
  solve.js https://example.com/login

env list में तीनों CAPSKIP वेरिएबल के नाम हैं। net list में CapSkip का पता और पोर्ट है, और साइट भी। example.com और पेज का पता अपनी साइट से बदलें। कोई भी एक entry हटा दें तो रन फेल हो जाता है, और error में लिखा होता है कि क्या गायब है।

अनुमतियह क्या करने देता हैइसके बिना आपको क्या दिखता है
env, तीन नामCAPSKIP वेरिएबल पढ़नाNotCapable: Requires env access to "CAPSKIP_HOST", उसके बाद env flag के साथ दोबारा चलाने की सलाह। जो वेरिएबल सेट नहीं है, उसे भी मना कर दिया जाता है, इसलिए डिफ़ॉल्ट वैल्यू से मदद नहीं मिलती।
net, CapSkip का host और portCapSkip को SDK की कॉलएक NetworkException, जिसका संदेश है Requires net access to "127.0.0.1:8080", उसके बाद net flag के लिए वही सलाह।
net, साइटपेज और फॉर्म को आपकी fetch कॉलसाइट का नाम बताने वाला एक NotCapable error।

net list के कुछ नियम। बिना port वाला host हर port को अनुमति देता है, इसलिए example.com 80 और 443, दोनों को कवर करता है। port वाली entry सिर्फ़ उसी port को अनुमति देती है। 127.0.0.1 और 127.0.0.2 अलग-अलग host हैं। और किसी दूसरे host नाम पर redirect के लिए उस host का भी list में होना ज़रूरी है। जो पेज example.com से www.example.com पर भेजता है, वह redirect की दूसरी रिक्वेस्ट पर तब तक फेल होता है जब तक आप उसे जोड़ न दें। और कुछ नहीं चाहिए था: न read, न run, न sys, न import permission।

टर्मिनल में Deno फेल होने के बजाय पूछता है। वह हर वेरिएबल और हर host के लिए एक बार prompt करता है, और मना कर देने पर वही errors आते हैं। scheduled जॉब में कोई टर्मिनल नहीं होता, इसलिए वह तुरंत फेल हो जाता है। allow-all flag (-A) इन सारी जाँचों को हटा देता है, इसलिए इसे सिर्फ़ किसी जल्दी के प्रयोग के लिए रखें।

आप यही कमांड deno.json में task के रूप में रख सकते हैं, ताकि कम टाइप करना पड़े। नीचे का पहला ब्लॉक import map और एक solve task वाली deno.json है, और दूसरा PowerShell में एनवायरनमेंट सेट करके उसे चलाता है। task के नाम के बाद आप जो पेज का पता देते हैं, Deno उसे जोड़ देता है।

{
  "imports": {
    "capskip": "npm:[email protected]"
  },
  "tasks": {
    "solve": "deno run --allow-env=CAPSKIP_HOST,CAPSKIP_PORT,CAPSKIP_API_KEY --allow-net=127.0.0.1:8080,example.com solve.js"
  }
}
$env:CAPSKIP_HOST = "127.0.0.1"
$env:CAPSKIP_PORT = "8080"
deno task solve https://example.com/login

CAPSKIP_HOST के लिए IP पता इस्तेमाल करें। अगर आप localhost जैसा कोई नाम सेट करते हैं, तो वह नाम खुद net list में होना चाहिए, वरना SDK getaddrinfo EPERM localhost के साथ फेल हो जाता है। उसे list में डालना भी एक जाल है। CapSkip न चल रहा हो, तो localhost की वजह से Deno IPv6 पता [::1] आज़माता है, जो list में नहीं है। यह error SDK कॉल से नहीं, एक timer से throw होता है, इसलिए वह NetworkException नहीं है और try और catch उसे पकड़ नहीं सकते।

रोकी गई कॉल और न चल रहे CapSkip में फ़र्क़ पहचानें

दोनों NetworkException के रूप में आते हैं, इसलिए जो handler हमेशा "is CapSkip running?" कहता है, वह आपको गलत दिशा में भेज देता है। फ़र्क़ संदेश और cause में है। रोकी गई कॉल का संदेश Requires net access से शुरू होता है, और उसका cause Deno का NotCapable error होता है। अगर CAPSKIP_HOST कोई नाम है, तो संदेश getaddrinfo EPERM होता है और cause में इसके बजाय code EPERM होता है। जो CapSkip चल नहीं रहा, उसका संदेश connect ECONNREFUSED से शुरू होता है। Windows पर Deno में इसके फेल होने में करीब दो सेकंड लगते हैं, जबकि Node में कुछ मिलीसेकंड। जो script इसे बताने से पहले रुकी हुई लगे, वह अटकी नहीं है। नीचे का function दोनों तरह की रोक की जाँच करता है। आख़िर की पूरी script इसे पूरे फ़्लो के आसपास के catch block में कॉल करती है।

import { ApiException, NetworkException, TimeoutException } from "capskip";

// Deno's permission errors arrive wrapped in NetworkException. The
// cause is NotCapable for an IP host, and has the code EPERM for a
// host name. Tell them apart from a CapSkip that is not running.
/** @param {any} err */
function explain(err) {
  const cause = err?.cause;
  if (err instanceof NetworkException) {
    const denied = cause instanceof Deno.errors.NotCapable ||
      cause?.code === "EPERM";
    return denied
      ? `Deno blocked the call, add a flag: ${err.message}`
      : `CapSkip is not reachable: ${err.message || cause?.code}`;
  }
  if (err instanceof ApiException) return `CapSkip replied: ${err.message}`;
  if (err instanceof TimeoutException) return `Too slow: ${err.message}`;
  return String(err?.stack ?? err);
}

चुप पड़े CapSkip को script अटकाने से रोकें

SDK अपने कनेक्शन पर कोई timeout नहीं लगाता। अगर CapSkip कोई कॉल स्वीकार कर ले और फिर कभी जवाब न दे, तो script हमेशा इंतज़ार करती रहती है। Deno कुछ प्रिंट नहीं करता और बंद नहीं होता। SDK की recaptchaTimeout सेटिंग से मदद नहीं मिलती। वह सिर्फ़ polls के बीच जाँची जाती है, इसलिए जब submit कॉल या कोई poll जवाब का इंतज़ार कर रहा हो, तब वह चल नहीं सकती। Node में भी यही होता है। किसी wrapper के बिना बाहर निकलने का एकमात्र रास्ता Ctrl+C है।

कॉल पर समय-सीमा खुद लगाएँ। आम टूल AbortSignal.timeout है, और Deno में यहाँ वही गलत चुनाव है। abort listener वाला timeout signal प्रोसेस को तब तक चालू रखता है जब तक timer न चल जाए। जो solve 1.8 सेकंड में पूरा हुआ, उसके आसपास 30 सेकंड की समय-सीमा लगाने पर script 30 सेकंड बाद बंद हुई। सादा setTimeout, जिसे आप कॉल पूरी होते ही clear कर देते हैं, कामयाबी पर तुरंत बंद हो जाता है।

// The SDK sets no socket timeout, so a CapSkip that accepts the call
// and never answers would hang the script. Race it against a timer,
// and clear the timer so the process can exit on success.
/**
 * @param {Promise<any>} promise
 * @param {number} ms
 */
function withTimeout(promise, ms) {
  const { promise: limit, reject } = Promise.withResolvers();
  const timer = setTimeout(
    () => reject(new Error(`no answer in ${ms} ms`)),
    ms,
  );
  return Promise.race([promise, limit]).finally(() => clearTimeout(timer));
}

फिर स्टेप 4 के ब्लॉक को इससे बदल दें। यह उसी solve कॉल को लपेटता है। explain और withTimeout को उन लाइनों से ऊपर कहीं भी चिपका दें जो उन्हें इस्तेमाल करती हैं। SDK 300 सेकंड बाद खुद हार मान लेता है, इसलिए 330 सेकंड की समय-सीमा तभी चलती है जब CapSkip चुप हो जाए।

// The SDK gives up after 300 s by itself, so a 330 s budget only
// fires when CapSkip goes silent. code is typed "string or object"
// (Capy shares the field), so String() hands the form a plain string.
const solving = solver.recaptcha(sitekey, pageUrl);
const { code } = await withTimeout(solving, 330_000);
const token = String(code);

जब timer जीत जाता है, तब भी अधूरा कनेक्शन खुला रहता है, इसलिए पूरे उदाहरण का catch block Deno.exit पर खत्म होता है। इसके बिना प्रोसेस socket पर इंतज़ार करता रहता। टेस्टिंग में, जिस CapSkip ने submit का जवाब कभी नहीं दिया और जिसने नतीजे वाले polls का जवाब कभी नहीं दिया, दोनों समय-सीमा के बाद error के साथ खत्म हुए। exit code 1 था।

script को type-check करें

Deno JavaScript को SDK के साथ आए types के सामने जाँच सकता है, लेकिन सादी .js फ़ाइल के लिए आप कहें नहीं तो वह कुछ नहीं करता। सादी .js फ़ाइल पर deno check कुछ रिपोर्ट नहीं करता, भले ही कोड में type error हो। deno.json में checkJs चालू करने से जाँच असली बन जाती है।

{
  "imports": {
    "capskip": "npm:[email protected]"
  },
  "compilerOptions": {
    "checkJs": true
  }
}
deno check solve.js

जाँच चालू होने पर host की जगह hots जैसा गलत लिखा constructor ऑप्शन error बन जाता है। solve कॉल के अंदर गलत लिखा ऑप्शन error नहीं बनता, क्योंकि options type कोई भी key स्वीकार करता है, इसलिए वहाँ की typo compile हो जाती है और कुछ नहीं करती। जाँच को मदद समझें, गारंटी नहीं।

इसे एक अकेली exe में compile करें

permissions कमांड का हिस्सा हैं, इसलिए deno compile उन्हें exe के अंदर पक्का कर सकता है। तब Deno में reCAPTCHA हल करने वाली script एक solve.exe के रूप में दी जा सकती है, जो ऐसे PC पर भी चलती है जिसमें Deno इंस्टॉल नहीं है। यह उस Windows मशीन के लिए ठीक बैठता है जिस पर CapSkip और script साथ-साथ चलते हैं।

deno compile `
  --allow-env=CAPSKIP_HOST,CAPSKIP_PORT,CAPSKIP_API_KEY `
  --allow-net=127.0.0.1:8080,example.com `
  --output solve.exe solve.js
.\solve.exe https://example.com/login

चार बातें जान लें। पहला compile dl.deno.land से करीब 33 MB का runtime डाउनलोड करता है, और exe करीब 80 MB की होती है। एनवायरनमेंट वेरिएबल अब भी काम करते हैं, इसलिए CAPSKIP_PORT माना जाता है। permissions compile के समय तय हो जाती हैं, और exe में उन्हें बढ़ाने का कोई flag नहीं है: allow-all flag देने पर वह प्रोग्राम का पहला argument बन जाता है। और exe में, मना की गई कॉल का संदेश कहता है कि permission compile करते समय बताएँ।

Task Scheduler जैसी दिखने वाली एक launch ने टेस्टिंग में exe चलाई, और वह code 0 के साथ बंद हो गई। उसमें working folder System32 था, कोई console नहीं था और PATH में Deno नहीं था। असली scheduled task रजिस्टर नहीं किया गया, इसलिए Windows Task Scheduler जॉब में कैप्चा हल करने की गाइड में वहाँ मायने रखने वाली समय-सीमा और restart सेटिंग्स देखें।

CapSkip को किसी दूसरी मशीन पर चलाना

script और सॉल्वर का एक ही PC पर होना ज़रूरी नहीं। कनेक्शन सेटिंग्स में CapSkip को Server मोड पर कर दें, तो वह आपके नेटवर्क पते या पब्लिक IP पर सुनता है। फिर दो चीज़ें बदलें: CAPSKIP_HOST और net list। अगर आप net list में नया पता जोड़ना भूल जाएँ, तो error में वही पता लिखा आता है।

$env:CAPSKIP_HOST = "192.168.1.50"
$env:CAPSKIP_PORT = "8080"
$env:CAPSKIP_API_KEY = "YOUR_API_KEY"
deno run `
  --allow-env=CAPSKIP_HOST,CAPSKIP_PORT,CAPSKIP_API_KEY `
  --allow-net=192.168.1.50:8080,example.com `
  solve.js https://example.com/login

जब रास्ता इंटरनेट से होकर जाए तो स्टैटिक पब्लिक IP इस्तेमाल करें। API key validation चालू करें, और CAPSKIP_API_KEY में वही key रखें जो ऊपर का ब्लॉक सेट करता है। Server मोड शुरू होते ही CapSkip अपना पोर्ट हर पते के लिए खोल देता है। पहुँच को सिर्फ़ अपेक्षित मशीनों तक सीमित रखने के लिए, बाकी पतों के लिए Windows Firewall में एक block नियम जोड़ें। सॉल्वर अब भी आपकी अपनी Windows मशीन है, और solve अब भी बिना मीटर वाले हैं।

पूरी script

यह रही solve.js एक ही टुकड़े में, timeout wrapper और error handler के साथ। इसे deno.json के बगल में सेव करें और स्टेप 6 की कमांड से चलाएँ।

import {
  ApiException,
  CapSkip,
  NetworkException,
  TimeoutException,
} from "capskip";

// The SDK never reads the environment, so read it here and pass it in.
const host = Deno.env.get("CAPSKIP_HOST") ?? "127.0.0.1";
const port = Number(Deno.env.get("CAPSKIP_PORT") ?? 8080);
const apiKey = Deno.env.get("CAPSKIP_API_KEY") ?? "capskip";
const solver = new CapSkip({ host, port, apiKey });

// The login page to solve, passed on the command line.
const pageUrl = Deno.args[0] ?? "https://example.com/login";

// Deno's fetch keeps no cookies, so collect every Set-Cookie line.
// (headers.get("set-cookie") would glue them into one string.)
const jar = new Map();

/** @param {Response} response */
function keepCookies(response) {
  for (const line of response.headers.getSetCookie()) {
    const [pair] = line.split(";");
    const eq = pair.indexOf("=");
    jar.set(pair.slice(0, eq).trim(), pair.slice(eq + 1).trim());
  }
}
const cookies = () => Array.from(jar, ([k, v]) => `${k}=${v}`).join("; ");

// Deno's permission errors arrive wrapped in NetworkException. The
// cause is NotCapable for an IP host, and has the code EPERM for a
// host name. Tell them apart from a CapSkip that is not running.
/** @param {any} err */
function explain(err) {
  const cause = err?.cause;
  if (err instanceof NetworkException) {
    const denied = cause instanceof Deno.errors.NotCapable ||
      cause?.code === "EPERM";
    return denied
      ? `Deno blocked the call, add a flag: ${err.message}`
      : `CapSkip is not reachable: ${err.message || cause?.code}`;
  }
  if (err instanceof ApiException) return `CapSkip replied: ${err.message}`;
  if (err instanceof TimeoutException) return `Too slow: ${err.message}`;
  return String(err?.stack ?? err);
}

// The SDK sets no socket timeout, so a CapSkip that accepts the call
// and never answers would hang the script. Race it against a timer,
// and clear the timer so the process can exit on success.
/**
 * @param {Promise<any>} promise
 * @param {number} ms
 */
function withTimeout(promise, ms) {
  const { promise: limit, reject } = Promise.withResolvers();
  const timer = setTimeout(
    () => reject(new Error(`no answer in ${ms} ms`)),
    ms,
  );
  return Promise.race([promise, limit]).finally(() => clearTimeout(timer));
}

try {
  const page = await fetch(pageUrl);
  keepCookies(page);
  const html = await page.text();

  // Adjust these two patterns to your page's markup.
  const sitekey = html.match(/data-sitekey="([^"]+)"/)?.[1];
  const csrf = html.match(/name="csrfmiddlewaretoken" value="([^"]+)"/)?.[1];
  if (!sitekey || !csrf) throw new Error("sitekey or CSRF token not found");

  // The SDK gives up after 300 s by itself, so a 330 s budget only
  // fires when CapSkip goes silent. code is typed "string or object"
  // (Capy shares the field), so String() hands the form a plain string.
  const solving = solver.recaptcha(sitekey, pageUrl);
  const { code } = await withTimeout(solving, 330_000);
  const token = String(code);

  // fetch sends no Referer, and a strict site rejects the post without
  // one. redirect "manual" keeps the 302 so we can read its new cookie.
  const response = await fetch(pageUrl, {
    method: "POST",
    redirect: "manual",
    headers: { Cookie: cookies(), Referer: pageUrl },
    body: new URLSearchParams({
      csrfmiddlewaretoken: csrf,
      username: "YOUR_USERNAME",
      password: "YOUR_PASSWORD",
      "g-recaptcha-response": token,
    }),
  });
  keepCookies(response);

  // A good login answers 302 and rotates the session cookie.
  if (response.status !== 302) {
    const body = await response.text();
    throw new Error(`login rejected: ${response.status} ${body}`);
  }
  const next = new URL(response.headers.get("location") ?? "/", pageUrl);
  const home = await fetch(next, { headers: { Cookie: cookies() } });

  // Swap "Welcome back" for a marker your own site shows after login.
  const ok = (await home.text()).includes("Welcome back");
  console.log(ok ? "logged in" : "NOT logged in");
  if (!ok) Deno.exit(2);
} catch (err) {
  console.error(explain(err));
  Deno.exit(1);
}

Deno में reCAPTCHA हल करते समय आम errors

try block के बिना Deno सबसे पहले class का नाम प्रिंट करता है, जैसा पहले कॉलम में है। पूरी script वही संदेश अपने prefix के बाद प्रिंट करती है।

आप जो देखते हैंकारणफिक्स
Requires env access to "CAPSKIP_HOST"env permission में एक नाम छूट गया हैतीनों CAPSKIP नाम list में रखें
NetworkException: Requires net access to "127.0.0.1:8080"CapSkip का host और port net list में नहीं हैंउन्हें जोड़ें, और साइट भी जोड़ें
NetworkException: connect ECONNREFUSED, करीब 2 सेकंड बादCapSkip चल नहीं रहा, या port गलत हैCapSkip शुरू करें और कनेक्शन सेटिंग्स में port जाँचें
NetworkException: getaddrinfo EPERM localhosthost नाम इस्तेमाल हो रहा है, पर net list में सिर्फ़ IP हैCAPSKIP_HOST में 127.0.0.1 इस्तेमाल करें
ReferenceError: require is not definedES module में CommonJS कॉलnamed import इस्तेमाल करें
TypeError: CapSkip is not a constructordefault import पूरा exports object दे देता है{ CapSkip } को नाम से import करें
Could not find "capskip" in a node_modules folderप्रोजेक्ट के ऊपर की package.json imports को अपने हिसाब से resolve करने लगती हैप्रोजेक्ट फ़ोल्डर में एक deno.json रखें
कोई output नहीं, कोई exit नहींCapSkip ने कॉल स्वीकार की और कभी जवाब नहीं दियाकॉल को withTimeout में लपेटें और Deno.exit कॉल करें
ApiException: ERROR_CAPTCHA_UNSOLVABLECapSkip ने कोशिश की और असफल रहानया task सबमिट करें, नोट्स के लिए देखें: ERROR_CAPTCHA_UNSOLVABLE

FAQ

क्या मैं flags छोड़कर allow-all इस्तेमाल कर सकता हूँ?

यह चलता है, पर Deno में चलाने का मकसद ही खत्म कर देता है। तब script के पास नेटवर्क, फ़ाइल और एनवायरनमेंट की हर चीज़ तक पहुँच होती है, उन packages समेत जिन्हें वह import करती है। तीन नामों की एक list और दो hosts की एक list इतनी छोटी हैं कि उन्हें रखना मुश्किल नहीं।

क्या यह Deno Deploy या किसी दूसरे होस्टेड runtime पर काम करता है?

Deno Deploy और दूसरे होस्टेड runtimes को यहाँ टेस्ट नहीं किया गया। किसी और के डेटा सेंटर का सर्वर आपके PC के 127.0.0.1 तक नहीं पहुँच सकता। इसलिए CapSkip को अपने नियंत्रण वाली किसी Windows मशीन पर, स्टैटिक पब्लिक IP के साथ, Server मोड में चलाएँ, और CAPSKIP_HOST को उसी पर लगाएँ। प्लेटफ़ॉर्म को उस पते और port पर आउटबाउंड कनेक्शन की अनुमति भी देनी होगी, इसलिए उसके नेटवर्क नियम जाँचें। होस्टेड function से वही Server मोड सेटअप कैसे करना है, यह Netlify Functions में कैप्चा हल करने की गाइड में बताया गया है।

fetch से CapSkip को कॉल करने के बजाय SDK क्यों इस्तेमाल करें?

CapSkip 2captcha API के साथ compatible है, इसलिए in.php और res.php पर fetch भी काम करता है। फिर polling लूप, back-off और error mapping आपको खुद लिखनी पड़ती है। SDK पहले से ऐसे शेड्यूल पर poll करता है जो एक चौथाई सेकंड से शुरू होता है, token लौटाता है, और ApiException, NetworkException और TimeoutException उठाता है। इसकी कीमत दो बातें हैं: permission errors लपेटे हुए आते हैं, और SDK कोई socket timeout नहीं लगाता।

क्या Deno में बाकी कैप्चा टाइप भी इसी तरह काम करते हैं?

इस गाइड के लिए Deno में सिर्फ़ reCAPTCHA v2 चलाया गया। Turnstile और GeeTest जैसे token टाइप वही endpoints कॉल करते हैं, इसलिए वही दो flags लागू होने चाहिए, पर यह टेस्ट नहीं किया गया। फ़ाइल पाथ के रूप में दिए गए इमेज कैप्चा को read permission भी चाहिए, और URL के रूप में दिए गए इमेज कैप्चा के लिए उस साइट का net list में होना ज़रूरी है। हर टाइप के ऑप्शन Node.js कैप्चा सॉल्वर पेज पर पढ़ लें, इससे पहले कि आप कोई कॉल कॉपी करें।

संक्षेप में

Deno में reCAPTCHA हल करने के लिए, SDK import वाली deno.json को अपने फ़ोल्डर में रखें और named export import करें। CapSkip की सेटिंग्स खुद पढ़ें। env list और ऐसी net list के साथ चलाएँ जिसमें CapSkip का पता और आपकी साइट हो, इससे ज़्यादा कुछ नहीं। मना की गई कॉल और बंद पड़े CapSkip में फ़र्क़ उसके cause से पहचानें। solve पर सादे timer से समय-सीमा लगाएँ, क्योंकि AbortSignal.timeout प्रोसेस को खुला रखता है और चुप CapSkip उसे वरना हमेशा के लिए अटका देता है।

एक बार compile करके schedule की गई script महीने में हज़ारों हल कर सकती है। अपनी खुद की Windows मशीन पर चल रहे असीमित कैप्चा सॉल्वर से इन्हें चलाने का मतलब है कि यह संख्या कभी बिल में नहीं बदलती।