From 98433c97a017223abb5ef9690ad15a1ff0b9d089 Mon Sep 17 00:00:00 2001 From: GenixZero <70934040+median@users.noreply.github.com> Date: Wed, 8 Feb 2023 22:24:11 +1100 Subject: [PATCH] made kasada actually work --- acmethods.go | 163 +++++++++++++++++++++++++++++++-------------------- captchas.go | 5 +- proxy.go | 10 ++++ 3 files changed, 114 insertions(+), 64 deletions(-) diff --git a/acmethods.go b/acmethods.go index 1284759..7e31b8b 100644 --- a/acmethods.go +++ b/acmethods.go @@ -60,6 +60,67 @@ func antiCaptchaMethods(solver *Solver, preferredDomain string) *solveMethods { return int(taskId.(float64)), nil } + // parseResponse returns should continue, solution, error + parseResponse := func(body map[string]interface{}) (bool, *Solution, error) { + errMsg, hasError := body["errorDescription"] + if hasError && errMsg != nil { + return false, nil, errors.New(errMsg.(string)) + } + + status := body["status"] + + switch status { + case "processing": + return true, nil, nil + case "ready": + solution, hasSolution := body["solution"].(map[string]interface{}) + if !hasSolution { + return false, nil, errors.New("no solution") + } + + // response can either be gRecaptchaResponse or token + response := solution["gRecaptchaResponse"] + + if response == nil { + response = solution["token"] + } + + if response == nil { + response = solution["x-kpsdk-ct"] + } + + if response == nil { + if solver.Verbose { + fmt.Println(body) + } + + return false, nil, errors.New("no solution text") + } + + ip := "" + cost := "" + + rIP, hasIP := body["ip"] + if hasIP && rIP != nil { + ip = rIP.(string) + } + + rCost, hasCost := body["cost"] + if hasCost && rCost != nil { + cost = rCost.(string) + } + + return false, &Solution{ + Text: response.(string), + RawSolution: solution, + IP: ip, + Cost: cost, + }, nil + default: + return false, nil, errors.New("unknown status") + } + } + // keeps retrying until it has returned error or solved getResponse := func(taskId int) (*Solution, error) { for { @@ -84,64 +145,17 @@ func antiCaptchaMethods(solver *Solver, preferredDomain string) *solveMethods { continue } - errMsg, hasError := body["errorDescription"] - if hasError && errMsg != nil { - return nil, errors.New(errMsg.(string)) + shouldContinue, sol, err := parseResponse(body) + if err != nil { + return nil, err } - status := body["status"] - - switch status { - case "processing": + if shouldContinue { continue - case "ready": - solution, hasSolution := body["solution"].(map[string]interface{}) - if !hasSolution { - return nil, errors.New("no solution") - } - - // response can either be gRecaptchaResponse or token - response := solution["gRecaptchaResponse"] - - if response == nil { - response = solution["token"] - } - - if response == nil { - response = solution["x-kpsdk-ct"] - } - - if response == nil { - if solver.Verbose { - fmt.Println(body) - } - - return nil, errors.New("no solution text") - } - - ip := "" - cost := "" - - rIP, hasIP := body["ip"] - if hasIP && rIP != nil { - ip = rIP.(string) - } - - rCost, hasCost := body["cost"] - if hasCost && rCost != nil { - cost = rCost.(string) - } - - return &Solution{ - TaskId: taskId, - Text: response.(string), - RawSolution: solution, - IP: ip, - Cost: cost, - }, nil - default: - return nil, errors.New("unknown status") } + + sol.TaskId = taskId + return sol, nil } } @@ -328,24 +342,47 @@ func antiCaptchaMethods(solver *Solver, preferredDomain string) *solveMethods { // kasada method if solver.service == CapSolver { methods.Kasada = func(o KasadaOptions) (*KasadaSolution, error) { + if o.Proxy == nil { + return nil, errors.New("proxy is required") + } + taskData := map[string]interface{}{ - "type": "AntiKasadaTask", - "pageURL": o.PageURL, - "cd": o.DetailedCD, - "onlyCD": o.OnlyCD, - "version": o.Version, - "userAgent": o.UserAgent, + "pageURL": o.PageURL, + "cd": o.DetailedCD, + "onlyCD": o.OnlyCD, } - if o.Proxy != nil { - taskData["proxy"] = o.Proxy.String() + applyProxy(taskData, o.Proxy, "AntiKasadaTask") + + if o.Version != "" { + taskData["version"] = o.Version + } + + if o.UserAgent != "" { + taskData["userAgent"] = o.UserAgent } - sol, err := createResponse(taskData) + // send request to /kasada/invoke + payload := map[string]interface{}{ + "clientKey": solver.ApiKey, + "task": taskData, + "appId": "B7E57F27-0AD3-434D-A5B7-CF9EE7D093EF", + } + + body, err := postJSON(domain()+"/kasada/invoke", payload) if err != nil { return nil, err } + _, sol, err := parseResponse(body) + if err != nil { + return nil, err + } + + if sol == nil { + return nil, errors.New("no solution") + } + kpsdkCD := "" kpsdkCT := "" userAgent := "" diff --git a/captchas.go b/captchas.go index 669273c..513e675 100644 --- a/captchas.go +++ b/captchas.go @@ -88,9 +88,12 @@ type FunCaptchaOptions struct { Data string } +// KasadaOptions Make sure to set the proxy as its required type KasadaOptions struct { PageURL string - Proxy *Proxy + + // Proxy is required + Proxy *Proxy // DetailedCD Enable if you need more detailed x-kpsdk-cd, including params such as duration, st and rst DetailedCD bool diff --git a/proxy.go b/proxy.go index e103c1a..7573b2f 100644 --- a/proxy.go +++ b/proxy.go @@ -56,6 +56,7 @@ func NewProxy(t ProxyType, address string, port int, login *ProxyLogon) *Proxy { } } +// String only returns the proxy address and port func (p *Proxy) String() string { if p == nil { return "" @@ -64,6 +65,15 @@ func (p *Proxy) String() string { return p.login.String() + p.address + ":" + strconv.Itoa(p.port) } +// FullString returns the proxy address, port and type +func (p *Proxy) FullString() string { + if p == nil { + return "" + } + + return p.pType + "://" + p.login.String() + p.address + ":" + strconv.Itoa(p.port) +} + func (pl *ProxyLogon) String() string { if pl == nil { return ""