deathbycaptcha 5.2.0 → 6.0.0
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.
- checksums.yaml +4 -4
- data/README.md +165 -193
- data/deathbycaptcha.gemspec +2 -2
- data/lib/deathbycaptcha/client/http.rb +22 -5
- data/lib/deathbycaptcha/client/socket.rb +5 -4
- data/lib/deathbycaptcha/client.rb +78 -8
- data/lib/deathbycaptcha/version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90fb9bdd5058aa906630d30ddeb9a7cba5300d5c68105928c12fcd5e89eeec63
|
4
|
+
data.tar.gz: df094417918661d023db5d2252a546d57dc8d2eb6ef9c9c627b2cde73de54463
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce58d74f000916cc9084c8f1509c62975eaef9ae5fe6c8193866b8fc2454168437004f83f4dd6f45ae553bca0b67950fc1ff6e378abe33424e91028bf4bf5983
|
7
|
+
data.tar.gz: 13b46d8da90a407874bc57dc7a61d4b651e0c98f4151748ec1d8f374b8de73e4707bb93ed3581e1a5fda15dcf46b787e14109007b31505bef69a633ca1049711
|
data/README.md
CHANGED
@@ -1,291 +1,263 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
We suggest you to also check [2Captcha.com](http://2captcha.com/?from=1025109)
|
5
|
-
for a cheaper service. You can find it's gem fully compatible with the
|
6
|
-
deathbycaptcha gem at https://github.com/infosimples/two_captcha.
|
7
|
-
|
8
|
-
[Contact us](https://infosimples.com/en) if you need enterprise services for
|
9
|
-
CAPTCHAs solving or Internet automation.
|
10
|
-
|
1
|
+
> DeathByCaptcha is recommended for solving the most popular CAPTCHA types,
|
2
|
+
> such as image to text, reCAPTCHA v2, reCAPTCHA v3, hCaptcha and FunCaptcha.
|
11
3
|
|
12
4
|
# DeathByCaptcha
|
13
5
|
|
14
|
-
DeathByCaptcha is a Ruby API for DeathByCaptcha - http://www.deathbycaptcha.com
|
15
|
-
|
6
|
+
DeathByCaptcha is a Ruby API for DeathByCaptcha - http://www.deathbycaptcha.com
|
16
7
|
|
17
8
|
## Installation
|
18
9
|
|
19
10
|
Add this line to your application's Gemfile:
|
20
11
|
|
21
12
|
```ruby
|
22
|
-
gem 'deathbycaptcha', '~>
|
13
|
+
gem 'deathbycaptcha', '~> 6.0.0'
|
23
14
|
```
|
24
|
-
|
25
15
|
And then execute:
|
26
16
|
|
27
|
-
|
17
|
+
```bash
|
18
|
+
$ bundle
|
19
|
+
````
|
28
20
|
|
29
21
|
Or install it yourself as:
|
30
22
|
|
31
|
-
|
23
|
+
```bash
|
24
|
+
$ gem install deathbycaptcha
|
25
|
+
````
|
32
26
|
|
33
27
|
## Usage
|
34
28
|
|
35
|
-
1.
|
29
|
+
### 1. Create a client
|
36
30
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
```
|
31
|
+
```ruby
|
32
|
+
client = DeathByCaptcha.new('myusername', 'mypassword')
|
33
|
+
```
|
41
34
|
|
42
|
-
2.
|
35
|
+
### 2. Solve a CAPTCHA
|
43
36
|
|
44
|
-
|
45
|
-
* **decode** doesn't raise exceptions.
|
46
|
-
* **decode!** may raise a *DeathByCaptcha::Error* if something goes wrong.
|
37
|
+
There are two types of methods available: `decode_*` and `decode_*!`:
|
47
38
|
|
48
|
-
|
39
|
+
- `decode_*` does not raise exceptions.
|
40
|
+
- `decode_*!` may raise a `DeathByCaptcha::Error` if something goes wrong.
|
49
41
|
|
50
|
-
|
51
|
-
captcha = client.decode!(url: 'http://bit.ly/1xXZcKo')
|
52
|
-
captcha.text # Solution of the captcha
|
53
|
-
captcha.id # Numeric ID of the captcha solved by DeathByCaptcha
|
54
|
-
captcha.is_correct # true if the solution is correct
|
55
|
-
```
|
42
|
+
If the solution is not available, an empty CAPTCHA object will be returned.
|
56
43
|
|
57
|
-
|
44
|
+
```ruby
|
45
|
+
captcha = client.decode_image!(url: 'http://bit.ly/1xXZcKo')
|
46
|
+
captcha.text # CAPTCHA solution
|
47
|
+
captcha.id # CAPTCHA numeric id
|
48
|
+
```
|
58
49
|
|
59
|
-
|
60
|
-
client.decode!(path: 'path/to/my/captcha/file')
|
50
|
+
#### Image CAPTCHA
|
61
51
|
|
62
|
-
|
52
|
+
You can specify `url`, `path`, `file`, `raw` and `raw64` when decoding an image.
|
63
53
|
|
64
|
-
|
54
|
+
```ruby
|
55
|
+
client.decode_image!(url: 'http://bit.ly/1xXZcKo')
|
56
|
+
client.decode_image!(path: 'path/to/my/captcha/file')
|
57
|
+
client.decode_image!(file: File.open('path/to/my/captcha/file', 'rb'))
|
58
|
+
client.decode_image!(raw: File.open('path/to/my/captcha/file', 'rb').read)
|
59
|
+
client.decode_image!(raw64: Base64.encode64(File.open('path/to/my/captcha/file', 'rb').read))
|
60
|
+
```
|
65
61
|
|
66
|
-
|
67
|
-
```
|
62
|
+
#### reCAPTCHA v2
|
68
63
|
|
69
|
-
|
70
|
-
|
64
|
+
```ruby
|
65
|
+
captcha = client.decode_recaptcha_v2!(
|
66
|
+
googlekey: "6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5",
|
67
|
+
pageurl: "https://patrickhlauke.github.io/recaptcha/",
|
68
|
+
# proxy: "http://user:password@127.0.0.1:3128", # OPTIONAL
|
69
|
+
# proxytype: "HTTP", # OPTIONAL
|
70
|
+
)
|
71
71
|
|
72
|
-
|
72
|
+
# The response will be a text (token), which you can access with `text` or `token` methods.
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
```
|
74
|
+
captcha.text
|
75
|
+
"03AOPBWq_RPO2vLzyk0h8gH0cA2X4v3tpYCPZR6Y4yxKy1s3Eo7CHZRQntxrd..."
|
77
76
|
|
78
|
-
|
77
|
+
captcha.token
|
78
|
+
"03AOPBWq_RPO2vLzyk0h8gH0cA2X4v3tpYCPZR6Y4yxKy1s3Eo7CHZRQntxrd..."
|
79
|
+
```
|
79
80
|
|
80
|
-
|
81
|
-
captcha = client.report!('130920620') # with 130920620 as the captcha id
|
82
|
-
```
|
81
|
+
*Parameters:*
|
83
82
|
|
84
|
-
|
83
|
+
- `googlekey`: The Google key for the reCAPTCHA.
|
84
|
+
- `pageurl`: The URL of the page with the reCAPTCHA challenge.
|
85
|
+
- `proxy`: optional parameter. Proxy URL and credentials (if any).
|
86
|
+
- `proxytype`: optional parameter. Proxy connection protocol.
|
85
87
|
|
86
|
-
|
88
|
+
#### reCAPTCHA v3
|
87
89
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
90
|
+
```ruby
|
91
|
+
captcha = client.decode_recaptcha_v3!(
|
92
|
+
googlekey: "6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696",
|
93
|
+
pageurl: "https://recaptcha-demo.appspot.com/recaptcha-v3-request-scores.php",
|
94
|
+
action: "examples/v3scores",
|
95
|
+
# min_score: 0.3, # OPTIONAL
|
96
|
+
# proxy: "http://user:password@127.0.0.1:3128", # OPTIONAL
|
97
|
+
# proxytype: "HTTP", # OPTIONAL
|
98
|
+
)
|
95
99
|
|
96
|
-
|
100
|
+
# The response will be a text (token), which you can access with `text` or `token` methods.
|
97
101
|
|
98
|
-
|
99
|
-
|
100
|
-
status.todays_accuracy # Current accuracy of DeathByCaptcha
|
101
|
-
status.solved_in # Estimated seconds to solve a captcha right now
|
102
|
-
status.is_service_overloaded # true if DeathByCaptcha is overloaded/unresponsive
|
103
|
-
```
|
102
|
+
captcha.text
|
103
|
+
"03AOPBWq_RPO2vLzyk0h8gH0cA2X4v3tpYCPZR6Y4yxKy1s3Eo7CHZRQntxrd..."
|
104
104
|
|
105
|
-
|
105
|
+
captcha.token
|
106
|
+
"03AOPBWq_RPO2vLzyk0h8gH0cA2X4v3tpYCPZR6Y4yxKy1s3Eo7CHZRQntxrd..."
|
107
|
+
```
|
106
108
|
|
107
|
-
|
109
|
+
*Parameters:*
|
108
110
|
|
109
|
-
|
110
|
-
|
111
|
-
|
111
|
+
- `googlekey`: The Google key for the reCAPTCHA.
|
112
|
+
- `pageurl`: The URL of the page with the reCAPTCHA challenge.
|
113
|
+
- `action`: The action name used by the CAPTCHA.
|
114
|
+
- `min_score`: optional parameter. The minimal score needed for the CAPTCHA resolution. Defaults to `0.3`.
|
115
|
+
- `proxy`: optional parameter. Proxy URL and credentials (if any).
|
116
|
+
- `proxytype`: optional parameter. Proxy connection protocol.
|
112
117
|
|
113
|
-
|
114
|
-
|
118
|
+
> About the `action` parameter: in order to find out what this is, you need to inspect the JavaScript
|
119
|
+
> code of the website looking for a call to the `grecaptcha.execute` function.
|
120
|
+
>
|
121
|
+
> ```javascript
|
122
|
+
> // Example
|
123
|
+
> grecaptcha.execute('6Lc2fhwTAAAAAGatXTzFYfvlQMI2T7B6ji8UVV_f', { action: "examples/v3scores" })
|
124
|
+
> ````
|
115
125
|
|
116
|
-
|
126
|
+
#### hCaptcha
|
117
127
|
|
118
128
|
```ruby
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
**Captcha (screenshot)**
|
129
|
+
captcha = client.decode_h_captcha!(
|
130
|
+
sitekey: "56489210-0c02-58c0-00e5-1763b63dc9d4",
|
131
|
+
pageurl: "https://www.site.with.hcaptcha/example",
|
132
|
+
# proxy: "http://user:password@127.0.0.1:3128", # OPTIONAL
|
133
|
+
# proxytype: "HTTP", # OPTIONAL
|
134
|
+
)
|
127
135
|
|
128
|
-
|
136
|
+
# The response will be a text (token), which you can access with `text` or `token` methods.
|
129
137
|
|
130
|
-
|
138
|
+
captcha.text
|
139
|
+
"P0_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNza2V5IjoiNnpWV..."
|
131
140
|
|
132
|
-
|
133
|
-
|
134
|
-
|
141
|
+
captcha.token
|
142
|
+
"P0_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNza2V5IjoiNnpWV..."
|
143
|
+
```
|
135
144
|
|
136
|
-
|
137
|
-
# captcha.text
|
138
|
-
"[[30,143],[241,325]]"
|
145
|
+
*Parameters:*
|
139
146
|
|
140
|
-
|
141
|
-
|
142
|
-
|
147
|
+
- `sitekey`: The site key for the hCatpcha.
|
148
|
+
- `pageurl`: The URL of the page with the hCaptcha challenge.
|
149
|
+
- `proxy`: optional parameter. Proxy URL and credentials (if any).
|
150
|
+
- `proxytype`: optional parameter. Proxy connection protocol.
|
143
151
|
|
144
|
-
|
152
|
+
#### FunCaptcha
|
145
153
|
|
146
154
|
```ruby
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
banner_text: 'Click all images with bananas' # the banner text
|
155
|
+
captcha = client.decode_fun_captcha!(
|
156
|
+
publickey: "12345678-0000-1111-2222-123456789012",
|
157
|
+
pageurl: "https://www.site.with.funcaptcha/example",
|
158
|
+
# proxy: "http://user:password@127.0.0.1:3128", # OPTIONAL
|
159
|
+
# proxytype: "HTTP", # OPTIONAL
|
153
160
|
)
|
154
|
-
```
|
155
|
-
|
156
|
-
You should specify arguments with *type = 3* and the decomposed captcha as seen in the
|
157
|
-
example below:
|
158
|
-
|
159
|
-
**Captcha: images grid**
|
160
|
-
|
161
|
-
> the argument is passed as *url*, *path*, *file*, *raw* or *raw64*
|
162
161
|
|
163
|
-
|
162
|
+
# The response will be a text (token), which you can access with `text` or `token` methods.
|
164
163
|
|
165
|
-
|
164
|
+
captcha.text
|
165
|
+
"380633616d817f2b8.2351188603|r=ap-southeast-2|met..."
|
166
166
|
|
167
|
-
|
167
|
+
captcha.token
|
168
|
+
"380633616d817f2b8.2351188603|r=ap-southeast-2|met..."
|
169
|
+
```
|
168
170
|
|
169
|
-
|
171
|
+
*Parameters:*
|
170
172
|
|
171
|
-
|
173
|
+
- `publickey`: The public key for the FunCaptcha.
|
174
|
+
- `pageurl`: The URL of the page with the hCaptcha challenge.
|
175
|
+
- `proxy`: optional parameter. Proxy URL and credentials (if any).
|
176
|
+
- `proxytype`: optional parameter. Proxy connection protocol.
|
172
177
|
|
173
|
-
|
174
|
-
be clicked counting from left to right. For the captcha above it should look
|
175
|
-
something like:
|
178
|
+
### 3. Retrieve a previously solved CAPTCHA
|
176
179
|
|
177
180
|
```ruby
|
178
|
-
#
|
179
|
-
"[1,9]"
|
180
|
-
|
181
|
-
# captcha.indexes
|
182
|
-
[1, 9]
|
181
|
+
captcha = client.captcha('28624378') # with 28624378 being the CAPTCHA id
|
183
182
|
```
|
184
183
|
|
185
|
-
|
186
|
-
|
187
|
-
> It's currently available only with the :http client.
|
184
|
+
### 4. Report an incorrectly solved CAPTCHA for a refund
|
188
185
|
|
189
|
-
|
190
|
-
|
191
|
-
|
186
|
+
```ruby
|
187
|
+
captcha = client.report!('28624378') # with 28624378 being the CAPTCHA id
|
188
|
+
```
|
192
189
|
|
193
|
-
|
194
|
-
http://deathbycaptcha.com/user/api/newtokenrecaptcha
|
190
|
+
> **Warning:** *abusing on this method may get you banned.*
|
195
191
|
|
196
|
-
###
|
192
|
+
### 5. Retrieve your user information and credit balance
|
197
193
|
|
198
194
|
```ruby
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
googlekey: "6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5",
|
205
|
-
pageurl: "https://patrickhlauke.github.io/recaptcha/"
|
206
|
-
})
|
195
|
+
user = client.user
|
196
|
+
user.is_banned # true if the user is banned
|
197
|
+
user.balance # Credit balance in USD cents
|
198
|
+
user.rate # CAPTCHA rate, i.e. charges for one solved CAPTCHA in USD cents
|
199
|
+
user.id # Numeric id of your account
|
207
200
|
```
|
208
201
|
|
209
|
-
|
210
|
-
|
211
|
-
The response will be a text (token), which you can access with **text** or **token** method.
|
202
|
+
### 6. Retrieve DeathByCaptcha server status
|
212
203
|
|
213
204
|
```ruby
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
L0IRFc3Cslu6UFV04CIfqXJBWCE5MY0Ag918r14b43ZdpwHSaVVrUqzCQMCyb
|
219
|
-
cGq0yxLQf9eSexFiAWmcWLI5nVNA81meTXhQlyCn5bbbI2IMSEErDqceZjf1m
|
220
|
-
X3M67BhIb4"
|
221
|
-
|
222
|
-
# captcha.token
|
223
|
-
"03AOPBWq_RPO2vLzyk0h8gH0cA2X4v3tpYCPZR6Y4yxKy1s3Eo7CHZRQntxrd
|
224
|
-
saD2H0e6S3547xi1FlqJB4rob46J0-wfZMj6YpyVa0WGCfpWzBWcLn7tO_EYs
|
225
|
-
vEC_3kfLNINWa5LnKrnJTDXTOz-JuCKvEXx0EQqzb0OU4z2np4uyu79lc_Ndv
|
226
|
-
L0IRFc3Cslu6UFV04CIfqXJBWCE5MY0Ag918r14b43ZdpwHSaVVrUqzCQMCyb
|
227
|
-
cGq0yxLQf9eSexFiAWmcWLI5nVNA81meTXhQlyCn5bbbI2IMSEErDqceZjf1m
|
228
|
-
X3M67BhIb4"
|
205
|
+
status = client.status
|
206
|
+
status.todays_accuracy # Current accuracy of DeathByCaptcha
|
207
|
+
status.solved_in # Estimated seconds to solve a CAPTCHA right now
|
208
|
+
status.is_service_overloaded # true if DeathByCaptcha is overloaded/unresponsive
|
229
209
|
```
|
230
210
|
|
231
|
-
> Those captchas sometimes took more than 60 seconds to solve
|
232
|
-
> So consider increasing the client's *timeout*
|
233
|
-
|
234
211
|
## Notes
|
235
212
|
|
236
|
-
|
213
|
+
### Thread-safety
|
237
214
|
|
238
215
|
The API is thread-safe, which means it is perfectly fine to share a client
|
239
216
|
instance between multiple threads.
|
240
217
|
|
241
|
-
|
218
|
+
### HTTP and Socket clients
|
219
|
+
|
220
|
+
The API supports HTTP (recommended) and socket-based connections.
|
242
221
|
|
243
|
-
|
244
|
-
|
245
|
-
|
222
|
+
```ruby
|
223
|
+
# HTTP-based connection.
|
224
|
+
client = DeathByCaptcha.new('myusername', 'mypassword')
|
225
|
+
# or
|
226
|
+
client = DeathByCaptcha.new('myusername', 'mypassword', :http)
|
227
|
+
|
228
|
+
# Socket-based connection.
|
229
|
+
client = DeathByCaptcha.new('myusername', 'mypassword', :socket)
|
230
|
+
```
|
246
231
|
|
247
232
|
When using the socket client, make sure that outgoing TCP traffic to
|
248
|
-
|
233
|
+
`api.dbcapi.me` to the ports in range `8123-8130` is not blocked by your
|
249
234
|
firewall.
|
250
235
|
|
251
|
-
> We
|
252
|
-
>
|
253
|
-
>
|
236
|
+
> We strongly recommend using the HTTP client (default) because only image
|
237
|
+
> CAPTCHAs (`decode_image!`) are supported by the socket client in this gem.
|
238
|
+
> Other CAPTCHA types, such as reCAPTCHA v2, reCAPTCHA v3, hCaptcha and FunCaptcha
|
239
|
+
> are supported by the HTTP client only.
|
254
240
|
|
255
|
-
|
241
|
+
### Ruby dependencies
|
256
242
|
|
257
|
-
DeathByCaptcha >= 5.0.0
|
243
|
+
DeathByCaptcha >= 5.0.0 does not require specific dependencies. That saves you
|
258
244
|
memory and avoid conflicts with other gems.
|
259
245
|
|
260
|
-
|
246
|
+
### Input image format
|
261
247
|
|
262
|
-
Any format you use in the
|
263
|
-
always be converted to a raw64
|
264
|
-
you already have this format
|
265
|
-
|
248
|
+
Any format you use in the `decode_image!` method (`url`, `file`, `path`, `raw` or `raw64`) will
|
249
|
+
always be converted to a `raw64`, which is a base64-encoded binary string. So, if
|
250
|
+
you already have this format on your end, there is no need for convertions before
|
251
|
+
calling the API.
|
266
252
|
|
267
253
|
> Our recomendation is to never convert your image format, unless needed. Let
|
268
254
|
> the gem convert internally. It may save you resources (CPU, memory and IO).
|
269
255
|
|
270
|
-
|
271
|
-
|
272
|
-
We no longer follow the versioninig system of the official clients of
|
273
|
-
DeathByCaptcha. We have bumped to version 5.0.0 and will use
|
274
|
-
[Semantic Versioning](http://semver.org/) from now on.
|
275
|
-
|
276
|
-
#### Upgrade from 4.x to 5.x
|
277
|
-
|
278
|
-
Any 5.x version is incompatible with any 4.x version. Please, review your code
|
279
|
-
before upgrading.
|
280
|
-
|
281
|
-
#### Ruby versions
|
282
|
-
|
283
|
-
This gem has been tested on the following versions of Ruby:
|
256
|
+
### Versioning
|
284
257
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
* MRI 1.9.3
|
258
|
+
We no longer follow the versioning system of the official clients of
|
259
|
+
DeathByCaptcha. From `5.0.0` onwards, we will use
|
260
|
+
[Semantic Versioning](http://semver.org/).
|
289
261
|
|
290
262
|
## Contributing
|
291
263
|
|
@@ -303,4 +275,4 @@ https://github.com/infosimples/deathbycaptcha/graphs/contributors
|
|
303
275
|
|
304
276
|
# License
|
305
277
|
|
306
|
-
MIT License. Copyright (C) 2011-
|
278
|
+
MIT License. Copyright (C) 2011-2022 Infosimples. https://infosimples.com/
|
data/deathbycaptcha.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
|
-
spec.add_development_dependency "bundler", "~>
|
26
|
-
spec.add_development_dependency "rake", "
|
25
|
+
spec.add_development_dependency "bundler", "~> 2.2.33"
|
26
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
27
27
|
spec.add_development_dependency "rspec", "~> 3.1"
|
28
28
|
end
|
@@ -55,20 +55,36 @@ module DeathByCaptcha
|
|
55
55
|
payload[:captchafile] = "base64:#{options[:raw64]}"
|
56
56
|
payload[:type] = options[:type] if options[:type].to_i > 0
|
57
57
|
|
58
|
-
|
58
|
+
case options[:type].to_i
|
59
|
+
when 3
|
59
60
|
banner64 = load_captcha(options[:banner])
|
60
61
|
raise DeathByCaptcha::InvalidCaptcha if banner64.to_s.empty?
|
61
62
|
|
62
|
-
payload
|
63
|
-
|
63
|
+
payload = {
|
64
|
+
banner: "base64:#{banner64}",
|
65
|
+
banner_text: options[:banner_text].to_s,
|
66
|
+
}
|
64
67
|
|
65
|
-
|
68
|
+
when 4, 5
|
66
69
|
payload = {
|
67
|
-
type:
|
70
|
+
type: options[:type].to_i,
|
68
71
|
token_params: options[:token_params].to_json,
|
69
72
|
}
|
73
|
+
|
74
|
+
when 6
|
75
|
+
payload = {
|
76
|
+
type: options[:type].to_i,
|
77
|
+
funcaptcha_params: options[:funcaptcha_params].to_json,
|
78
|
+
}
|
79
|
+
|
80
|
+
when 7
|
81
|
+
payload = {
|
82
|
+
type: options[:type].to_i,
|
83
|
+
hcaptcha_params: options[:hcaptcha_params].to_json,
|
84
|
+
}
|
70
85
|
end
|
71
86
|
|
87
|
+
payload.merge!(vendor_id: 5)
|
72
88
|
response = perform('captcha', :post_multipart, payload)
|
73
89
|
DeathByCaptcha::Captcha.new(response)
|
74
90
|
end
|
@@ -99,6 +115,7 @@ module DeathByCaptcha
|
|
99
115
|
boundary, body = prepare_multipart_data(payload)
|
100
116
|
req.content_type = "multipart/form-data; boundary=#{boundary}"
|
101
117
|
req.body = body
|
118
|
+
|
102
119
|
else
|
103
120
|
uri = URI("http://#{self.hostname}/api/#{action}?#{URI.encode_www_form(payload)}")
|
104
121
|
req = Net::HTTP::Get.new(uri.request_uri, headers)
|
@@ -73,10 +73,11 @@ module DeathByCaptcha
|
|
73
73
|
#
|
74
74
|
def perform(action, payload = {})
|
75
75
|
payload.merge!(
|
76
|
-
cmd:
|
77
|
-
version:
|
78
|
-
username:
|
79
|
-
password:
|
76
|
+
cmd: action,
|
77
|
+
version: DeathByCaptcha::API_VERSION,
|
78
|
+
username: self.username,
|
79
|
+
password: self.password,
|
80
|
+
vendor_id: 5,
|
80
81
|
)
|
81
82
|
|
82
83
|
socket = create_socket()
|
@@ -25,7 +25,7 @@ module DeathByCaptcha
|
|
25
25
|
#
|
26
26
|
# @return [DeathByCaptcha::Client] A Socket or HTTP Client instance.
|
27
27
|
#
|
28
|
-
def self.create(username, password, connection = :
|
28
|
+
def self.create(username, password, connection = :http, options = {})
|
29
29
|
case connection
|
30
30
|
when :socket
|
31
31
|
DeathByCaptcha::Client::Socket.new(username, password, options)
|
@@ -75,20 +75,22 @@ module DeathByCaptcha
|
|
75
75
|
# Decode the text from an image (i.e. solve a captcha).
|
76
76
|
#
|
77
77
|
# @param [Hash] options Options hash.
|
78
|
-
# @option options [String] :url
|
79
|
-
# @option options [String] :path
|
80
|
-
# @option options [File] :file
|
81
|
-
# @option options [String] :raw
|
82
|
-
# @option options [String] :raw64
|
78
|
+
# @option options [String] :url URL of the image to be decoded.
|
79
|
+
# @option options [String] :path File path of the image to be decoded.
|
80
|
+
# @option options [File] :file File instance with image to be decoded.
|
81
|
+
# @option options [String] :raw Binary content of the image to be decoded.
|
82
|
+
# @option options [String] :raw64 Binary content encoded in base64 of the image to be decoded.
|
83
|
+
# @option options [String] :type CAPTCHA type.
|
84
|
+
# @option options [String] :token_params Parameters for token APIs (reCAPTCHA / hCaptcha).
|
83
85
|
#
|
84
86
|
# @return [DeathByCaptcha::Captcha] The captcha (with solution if an error is not raised).
|
85
87
|
#
|
86
88
|
def decode!(options = {})
|
87
89
|
started_at = Time.now
|
88
90
|
|
89
|
-
#
|
91
|
+
# Do not load image data for CAPTCHA types other than "image".
|
90
92
|
raw64 = nil
|
91
|
-
|
93
|
+
if ![4, 5, 6, 7].include?(options[:type])
|
92
94
|
raw64 = load_captcha(options)
|
93
95
|
raise DeathByCaptcha::InvalidCaptcha if raw64.to_s.empty?
|
94
96
|
end
|
@@ -106,6 +108,74 @@ module DeathByCaptcha
|
|
106
108
|
decoded_captcha
|
107
109
|
end
|
108
110
|
|
111
|
+
def decode_image(options = {})
|
112
|
+
decode!(options)
|
113
|
+
rescue DeathByCaptcha::Error
|
114
|
+
DeathByCaptcha::Captcha.new
|
115
|
+
end
|
116
|
+
|
117
|
+
def decode_image!(options = {})
|
118
|
+
decode!(options.slice(:url, :path, :file, :raw, :raw64))
|
119
|
+
end
|
120
|
+
|
121
|
+
def decode_recaptcha_v2(options = {})
|
122
|
+
decode_recaptcha_v2!(options)
|
123
|
+
rescue DeathByCaptcha::Error
|
124
|
+
DeathByCaptcha::Captcha.new
|
125
|
+
end
|
126
|
+
|
127
|
+
def decode_recaptcha_v2!(options = {})
|
128
|
+
options = {
|
129
|
+
type: 4, # reCAPTCHA v2
|
130
|
+
token_params: options.slice(:googlekey, :pageurl, :proxy, :proxytype),
|
131
|
+
}
|
132
|
+
decode!(options)
|
133
|
+
end
|
134
|
+
|
135
|
+
def decode_recaptcha_v3(options = {})
|
136
|
+
decode_recaptcha_v3!(options)
|
137
|
+
rescue DeathByCaptcha::Error
|
138
|
+
DeathByCaptcha::Captcha.new
|
139
|
+
end
|
140
|
+
|
141
|
+
def decode_recaptcha_v3!(options = {})
|
142
|
+
options = {
|
143
|
+
type: 5, # reCAPTCHA v3
|
144
|
+
token_params: {
|
145
|
+
min_score: 0.3,
|
146
|
+
}.merge(options.slice(:googlekey, :pageurl, :action, :min_score, :proxy, :proxytype)),
|
147
|
+
}
|
148
|
+
decode!(options)
|
149
|
+
end
|
150
|
+
|
151
|
+
def decode_h_captcha(options = {})
|
152
|
+
decode_recaptcha_h_captcha!(options)
|
153
|
+
rescue DeathByCaptcha::Error
|
154
|
+
DeathByCaptcha::Captcha.new
|
155
|
+
end
|
156
|
+
|
157
|
+
def decode_h_captcha!(options = {})
|
158
|
+
options = {
|
159
|
+
type: 7, # hCaptcha
|
160
|
+
hcaptcha_params: options.slice(:sitekey, :pageurl, :proxy, :proxytype),
|
161
|
+
}
|
162
|
+
decode!(options)
|
163
|
+
end
|
164
|
+
|
165
|
+
def decode_fun_captcha(options = {})
|
166
|
+
decode_fun_captcha!(options)
|
167
|
+
rescue DeathByCaptcha::Error
|
168
|
+
DeathByCaptcha::Captcha.new
|
169
|
+
end
|
170
|
+
|
171
|
+
def decode_fun_captcha!(options = {})
|
172
|
+
options = {
|
173
|
+
type: 6, # FunCaptcha
|
174
|
+
funcaptcha_params: options.slice(:publickey, :pageurl, :proxy, :proxytype),
|
175
|
+
}
|
176
|
+
decode!(options)
|
177
|
+
end
|
178
|
+
|
109
179
|
# Retrieve information from an uploaded captcha.
|
110
180
|
#
|
111
181
|
# @param [Integer] captcha_id Numeric ID of the captcha.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deathbycaptcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rafael Barbolo, Rafael Ivan Garcia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.2.33
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.2.33
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 12.3.3
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 12.3.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|