-
Notifications
You must be signed in to change notification settings - Fork 9
/
twocaptcha.go
152 lines (133 loc) · 3.49 KB
/
twocaptcha.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package twocaptcha
// package twocaptcha provides a Golang client for https://2captcha.com/
import (
"encoding/base64"
"errors"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
)
// ApiURL is the url of the 2captcha API endpoint
var ApiURL = "https://2captcha.com/in.php"
// ResultURL is the url of the 2captcha result API endpoint
var ResultURL = "https://2captcha.com/res.php"
// TwoCaptchaClient is an interface to https://2captcha.com/ API.
type TwoCaptchaClient struct {
// ApiKey is the API key for the 2captcha.com API.
// Valid key is required by all the functions of this library
// See more details on https://2captcha.com/2captcha-api#solving_captchas
ApiKey string
// Client is a HTTP client for the api calls to 2captcha
Client *http.Client
}
// New creates a TwoCaptchaClient instance
func New(apiKey string) *TwoCaptchaClient {
return &TwoCaptchaClient{
ApiKey: apiKey,
Client: http.DefaultClient,
}
}
// SolveCaptcha performs a normal captcha solving request to 2captcha.com
// and returns with the solved captcha if the request was successful.
// Valid ApiKey is required.
// See more details on https://2captcha.com/2captcha-api#solving_normal_captcha
func (c *TwoCaptchaClient) SolveCaptcha(url string) (string, error) {
resp, err := http.Get(url)
if err != nil || resp.StatusCode != 200 {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
strBase64 := base64.StdEncoding.EncodeToString(body)
captchaId, err := c.apiRequest(
ApiURL,
map[string]string{
"method": "base64",
"body": strBase64,
"phrase": "1",
"regsense": "1",
},
0,
3,
)
if err != nil {
return "", err
}
return c.apiRequest(
ResultURL,
map[string]string{
"id": captchaId,
"action": "get",
},
5,
20,
)
}
// SolveRecaptchaV2 performs a recaptcha v2 solving request to 2captcha.com
// and returns with the solved captcha if the request was successful.
// Valid ApiKey is required.
// See more details on https://2captcha.com/2captcha-api#solving_recaptchav2_new
func (c *TwoCaptchaClient) SolveRecaptchaV2(siteURL, recaptchaKey string) (string, error) {
captchaId, err := c.apiRequest(
ApiURL,
map[string]string{
"googlekey": recaptchaKey,
"pageurl": siteURL,
"method": "userrecaptcha",
},
0,
3,
)
if err != nil {
return "", err
}
return c.apiRequest(
ResultURL,
map[string]string{
"googlekey": recaptchaKey,
"pageurl": siteURL,
"method": "userrecaptcha",
"id": captchaId,
"action": "get",
},
5,
20,
)
}
func (c *TwoCaptchaClient) apiRequest(URL string, params map[string]string, delay time.Duration, retries int) (string, error) {
if retries <= 0 {
return "", errors.New("Maximum retries exceeded")
}
time.Sleep(delay * time.Second)
form := url.Values{}
form.Add("key", c.ApiKey)
for k, v := range params {
form.Add(k, v)
}
req, err := http.NewRequest("POST", URL, strings.NewReader(form.Encode()))
if err != nil {
return "", err
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := c.Client.Do(req)
if err != nil {
return "", err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
resp.Body.Close()
if strings.Contains(string(body), "CAPCHA_NOT_READY") {
return c.apiRequest(URL, params, delay, retries-1)
}
if !strings.Contains(string(body), "OK|") {
return "", errors.New("Invalid respponse from 2captcha: " + string(body))
}
return string(body[3:]), nil
}