Skip to content

Commit 98433c9

Browse files
committed
made kasada actually work
1 parent d9b027c commit 98433c9

File tree

3 files changed

+114
-64
lines changed

3 files changed

+114
-64
lines changed

acmethods.go

Lines changed: 100 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,67 @@ func antiCaptchaMethods(solver *Solver, preferredDomain string) *solveMethods {
6060
return int(taskId.(float64)), nil
6161
}
6262

63+
// parseResponse returns should continue, solution, error
64+
parseResponse := func(body map[string]interface{}) (bool, *Solution, error) {
65+
errMsg, hasError := body["errorDescription"]
66+
if hasError && errMsg != nil {
67+
return false, nil, errors.New(errMsg.(string))
68+
}
69+
70+
status := body["status"]
71+
72+
switch status {
73+
case "processing":
74+
return true, nil, nil
75+
case "ready":
76+
solution, hasSolution := body["solution"].(map[string]interface{})
77+
if !hasSolution {
78+
return false, nil, errors.New("no solution")
79+
}
80+
81+
// response can either be gRecaptchaResponse or token
82+
response := solution["gRecaptchaResponse"]
83+
84+
if response == nil {
85+
response = solution["token"]
86+
}
87+
88+
if response == nil {
89+
response = solution["x-kpsdk-ct"]
90+
}
91+
92+
if response == nil {
93+
if solver.Verbose {
94+
fmt.Println(body)
95+
}
96+
97+
return false, nil, errors.New("no solution text")
98+
}
99+
100+
ip := ""
101+
cost := ""
102+
103+
rIP, hasIP := body["ip"]
104+
if hasIP && rIP != nil {
105+
ip = rIP.(string)
106+
}
107+
108+
rCost, hasCost := body["cost"]
109+
if hasCost && rCost != nil {
110+
cost = rCost.(string)
111+
}
112+
113+
return false, &Solution{
114+
Text: response.(string),
115+
RawSolution: solution,
116+
IP: ip,
117+
Cost: cost,
118+
}, nil
119+
default:
120+
return false, nil, errors.New("unknown status")
121+
}
122+
}
123+
63124
// keeps retrying until it has returned error or solved
64125
getResponse := func(taskId int) (*Solution, error) {
65126
for {
@@ -84,64 +145,17 @@ func antiCaptchaMethods(solver *Solver, preferredDomain string) *solveMethods {
84145
continue
85146
}
86147

87-
errMsg, hasError := body["errorDescription"]
88-
if hasError && errMsg != nil {
89-
return nil, errors.New(errMsg.(string))
148+
shouldContinue, sol, err := parseResponse(body)
149+
if err != nil {
150+
return nil, err
90151
}
91152

92-
status := body["status"]
93-
94-
switch status {
95-
case "processing":
153+
if shouldContinue {
96154
continue
97-
case "ready":
98-
solution, hasSolution := body["solution"].(map[string]interface{})
99-
if !hasSolution {
100-
return nil, errors.New("no solution")
101-
}
102-
103-
// response can either be gRecaptchaResponse or token
104-
response := solution["gRecaptchaResponse"]
105-
106-
if response == nil {
107-
response = solution["token"]
108-
}
109-
110-
if response == nil {
111-
response = solution["x-kpsdk-ct"]
112-
}
113-
114-
if response == nil {
115-
if solver.Verbose {
116-
fmt.Println(body)
117-
}
118-
119-
return nil, errors.New("no solution text")
120-
}
121-
122-
ip := ""
123-
cost := ""
124-
125-
rIP, hasIP := body["ip"]
126-
if hasIP && rIP != nil {
127-
ip = rIP.(string)
128-
}
129-
130-
rCost, hasCost := body["cost"]
131-
if hasCost && rCost != nil {
132-
cost = rCost.(string)
133-
}
134-
135-
return &Solution{
136-
TaskId: taskId,
137-
Text: response.(string),
138-
RawSolution: solution,
139-
IP: ip,
140-
Cost: cost,
141-
}, nil
142-
default:
143-
return nil, errors.New("unknown status")
144155
}
156+
157+
sol.TaskId = taskId
158+
return sol, nil
145159
}
146160
}
147161

@@ -328,24 +342,47 @@ func antiCaptchaMethods(solver *Solver, preferredDomain string) *solveMethods {
328342
// kasada method
329343
if solver.service == CapSolver {
330344
methods.Kasada = func(o KasadaOptions) (*KasadaSolution, error) {
345+
if o.Proxy == nil {
346+
return nil, errors.New("proxy is required")
347+
}
348+
331349
taskData := map[string]interface{}{
332-
"type": "AntiKasadaTask",
333-
"pageURL": o.PageURL,
334-
"cd": o.DetailedCD,
335-
"onlyCD": o.OnlyCD,
336-
"version": o.Version,
337-
"userAgent": o.UserAgent,
350+
"pageURL": o.PageURL,
351+
"cd": o.DetailedCD,
352+
"onlyCD": o.OnlyCD,
338353
}
339354

340-
if o.Proxy != nil {
341-
taskData["proxy"] = o.Proxy.String()
355+
applyProxy(taskData, o.Proxy, "AntiKasadaTask")
356+
357+
if o.Version != "" {
358+
taskData["version"] = o.Version
359+
}
360+
361+
if o.UserAgent != "" {
362+
taskData["userAgent"] = o.UserAgent
342363
}
343364

344-
sol, err := createResponse(taskData)
365+
// send request to /kasada/invoke
366+
payload := map[string]interface{}{
367+
"clientKey": solver.ApiKey,
368+
"task": taskData,
369+
"appId": "B7E57F27-0AD3-434D-A5B7-CF9EE7D093EF",
370+
}
371+
372+
body, err := postJSON(domain()+"/kasada/invoke", payload)
345373
if err != nil {
346374
return nil, err
347375
}
348376

377+
_, sol, err := parseResponse(body)
378+
if err != nil {
379+
return nil, err
380+
}
381+
382+
if sol == nil {
383+
return nil, errors.New("no solution")
384+
}
385+
349386
kpsdkCD := ""
350387
kpsdkCT := ""
351388
userAgent := ""

captchas.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,12 @@ type FunCaptchaOptions struct {
8888
Data string
8989
}
9090

91+
// KasadaOptions Make sure to set the proxy as its required
9192
type KasadaOptions struct {
9293
PageURL string
93-
Proxy *Proxy
94+
95+
// Proxy is required
96+
Proxy *Proxy
9497

9598
// DetailedCD Enable if you need more detailed x-kpsdk-cd, including params such as duration, st and rst
9699
DetailedCD bool

proxy.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ func NewProxy(t ProxyType, address string, port int, login *ProxyLogon) *Proxy {
5656
}
5757
}
5858

59+
// String only returns the proxy address and port
5960
func (p *Proxy) String() string {
6061
if p == nil {
6162
return ""
@@ -64,6 +65,15 @@ func (p *Proxy) String() string {
6465
return p.login.String() + p.address + ":" + strconv.Itoa(p.port)
6566
}
6667

68+
// FullString returns the proxy address, port and type
69+
func (p *Proxy) FullString() string {
70+
if p == nil {
71+
return ""
72+
}
73+
74+
return p.pType + "://" + p.login.String() + p.address + ":" + strconv.Itoa(p.port)
75+
}
76+
6777
func (pl *ProxyLogon) String() string {
6878
if pl == nil {
6979
return ""

0 commit comments

Comments
 (0)