1 | module TwoCaptcha.Internal.Types.Exception where |
2 | |
3 | import Control.Exception (Exception) |
4 | import Data.Functor (($>)) |
5 | import Data.Text (Text) |
6 | import Network.HTTP.Client (HttpException) |
7 | import Text.Parsec (ParseError, parse, try, (<|>)) |
8 | import Text.Parsec.Char (string) |
9 | import Text.Parsec.String (Parser) |
10 | |
11 | -- | Represents a possible exception when interacting with the 2captcha API. |
12 | data TwoCaptchaException |
13 | = -- | An error documented on 2captcha's website. |
14 | TwoCaptchaResponseException TwoCaptchaErrorCode |
15 | | -- | A non-200 status code was thrown. This should only appear in rare cases. |
16 | NetworkException HttpException |
17 | | -- | An unknown error occured, likely due to a change in the 2captcha API. |
18 | UnknownError Text |
19 | | -- | Solving the captcha took too long. Try setting a higher timeout duration? |
20 | SolvingTimeout |
21 | deriving (Show) |
22 | |
23 | instance Exception TwoCaptchaException |
24 | |
25 | -- | Possible errors when using the 2captcha API. |
26 | data TwoCaptchaErrorCode |
27 | = -- | The api key you provided is invalid. Please ensure it is 32 characters long. |
28 | WrongUserKey |
29 | | -- | The key you've provided does not exist. |
30 | KeyDoesNotExist |
31 | | -- | You don't have funds in your account. |
32 | ZeroBalance |
33 | | -- | The __pageurl__ parameter is missing in your request. |
34 | PageUrlMissing |
35 | | -- | |
36 | -- You can receive this error in two cases: |
37 | -- |
38 | -- 1. __If you solve token-based captchas (reCAPTCHA, hCaptcha, ArkoseLabs FunCaptcha, GeeTest, etc):__ |
39 | -- the queue of your captchas that are not distributed to workers is too long. |
40 | -- Queue limit changes dynamically and depends on total amount of captchas awaiting solution and usually it’s between 50 and 100 captchas. |
41 | -- |
42 | -- 2. __If you solve Normal Captcha:__ your maximum rate for normal captchas is lower than current rate on the server. |
43 | -- You can change your maximum rate in <https://2captcha.com/setting your account's settings.> |
44 | NoSlotAvailable |
45 | | -- | Image size is less than 100 bytes. |
46 | ZeroCaptchaFileSize |
47 | | -- | Image size is more than 100 kB. |
48 | TooBigCaptchaFileSize |
49 | | -- | Image file has unsupported extension. Accepted extensions: jpg, jpeg, gif, png. |
50 | WrongFileExtension |
51 | | -- | Server can't recognize image file type. |
52 | ImageTypeNotSupported |
53 | | -- | |
54 | -- Server can't get file data from your POST-request. |
55 | -- That happens if your POST-request is malformed or base64 data is not a valid base64 image. |
56 | UploadFailure |
57 | | -- | The request is sent from the IP that is not on the list of your allowed IPs. |
58 | IpNotAllowed |
59 | | -- | Your IP address is banned due to many frequent attempts to access the server using wrong authorization keys. |
60 | IpBanned |
61 | | -- | |
62 | -- You can get this error code when sending reCAPTCHA V2. This happens if your request contains invalid pair of googlekey and pageurl. |
63 | -- The common reason for that is that reCAPTCHA is loaded inside an iframe hosted on another domain/subdomain. |
64 | BadTokenOrPageUrl |
65 | | -- | You can get this error code when sending reCAPTCHA V2. That means that sitekey value provided in your request is incorrect: it's blank or malformed. |
66 | GoogleKeyInvalid |
67 | | -- | The __googlekey__ parameter is missing in your request. |
68 | GoogleKeyMissing |
69 | | -- | |
70 | -- You've sent an image that is marked in 2captcha's database as unrecognizable. |
71 | -- Usually that happens if the website where you found the captcha stopped sending you captchas and started to send a "deny access" image. |
72 | CaptchaImageBlocked |
73 | | -- | You are sending too many unrecognizable images. |
74 | TooManyBadImages |
75 | | -- | |
76 | -- You made more than 60 requests to in.php within 3 seconds. |
77 | -- Your account is banned for 10 seconds. Ban will be lifted automatically. |
78 | RateLimited |
79 | | -- | |
80 | -- You received the error 'NoSlotAvailable' 120 times in one minute because your current bid is lower than current bid on the server. |
81 | -- |
82 | -- Blocking time: 10 minutes. |
83 | Error1001 |
84 | | -- | |
85 | -- You received the error 'ZeroBalance' 120 times in one minute because your balance is zero. |
86 | -- |
87 | -- Blocking time: 5 minutes. |
88 | Error1002 |
89 | | -- | |
90 | -- You received the error 'NoSlotAvailable' because you are uploading many captchas and server has a long queue of your captchas that are not distributed to workers. |
91 | -- You received three times more errors than amount of captchas you sent (but not less than 120 errors). Increase the timeout if you see this error. |
92 | -- |
93 | -- Blocking time: 30 seconds. |
94 | Error1003 |
95 | | -- | Your IP address is blocked because there were 5 requests with incorrect API key from your IP. |
96 | Error1004 |
97 | | -- | |
98 | -- You are making too many requests to res.php to get answers. |
99 | -- |
100 | -- |
101 | -- 2captcha uses the following rule to block your account: R > C * 20 + 1200 |
102 | -- |
103 | -- Where: |
104 | -- |
105 | -- * R - the amount of your requests |
106 | -- |
107 | -- * C - the amount of captchas you've uploaded |
108 | -- |
109 | -- That means that you don't have to make more than 20 requests to res.php per each captcha. |
110 | -- Please remember that balance request sent to res.php also counts! |
111 | -- |
112 | -- To get your answer faster without a risk to be blocked you can use <https://2captcha.com/2captcha-api#pingback pingback> feature and 2captcha will send you the answer when your captcha is solved. |
113 | -- |
114 | -- Blocking time: 10 minutes. |
115 | Error1005 |
116 | | -- | |
117 | -- The error code is returned if some required parameters are missing in your request or the values have incorrect format. |
118 | -- For example if you submit <https://2captcha.com/2captcha-api#grid Grid images> but your request is missing an instruction for workers. |
119 | -- |
120 | -- Blocking time: 5 minutes. |
121 | BadParameters |
122 | | -- | You can get this error code when sending a captcha via proxy server which is marked as BAD by the 2captcha API. |
123 | BadProxy |
124 | | -- | Your captcha is not solved yet. |
125 | CaptchaNotReady |
126 | | -- | |
127 | -- 2captcha was unable to solve your captcha - three of their workers were unable solve it or they didn't get an answer within 90 seconds (300 seconds for reCAPTCHA V2). |
128 | -- |
129 | -- You will not be charged for that request. |
130 | CaptchaUnsolvable |
131 | | -- | You've provided captcha ID in wrong format. The ID can contain numbers only. |
132 | WrongIdFormat |
133 | | -- | You provided an invalid captcha id. |
134 | WrongCaptchaId |
135 | | -- | Error is returned when 100% accuracy feature is enabled. The error means that max numbers of tries is reached but min number of matches not found. |
136 | BadDuplicates |
137 | | -- | |
138 | -- Error is returned to your <https://2captcha.com/2captcha-api#complain report> request if you already complained lots of correctly solved captchas (more than 40%). |
139 | -- Or if more than 15 minutes passed after you submitted the captcha. |
140 | ReportNotRecorded |
141 | | -- | Error is returned to your <https://2captcha.com/2captcha-api#complain report request> if you are trying to report the same captcha more than once. |
142 | DuplicateReport |
143 | | -- | |
144 | -- You can receive this error code when registering a <https://2captcha.com/2captcha-api#pingback pingback (callback)> IP or domain. |
145 | -- |
146 | -- This happens if your request is coming from an IP address that doesn't match the IP address of your pingback IP or domain. |
147 | InvalidPingbackIp |
148 | | -- | |
149 | -- You can receive this error code when sending <https://2captcha.com/2captcha-api#solving_geetest GeeTest>. |
150 | -- This error means the __challenge__ value you provided is expired. |
151 | TokenExpired |
152 | | -- | Action parameter is missing or no value is provided for __action__ parameter. |
153 | EmptyAction |
154 | | -- | |
155 | -- You can get this error code if we were unable to load a captcha through your proxy server. |
156 | -- The proxy will be marked as BAD by our API and we will not accept requests with the proxy during 10 minutes. |
157 | -- You will recieve ERROR_BAD_PROXY code from in.php API endpoint in such case. |
158 | ProxyConnectionFailed |
159 | deriving (Show, Eq) |
160 | |
161 | -- | The raw error code provided by 2captcha. |
162 | errorCode :: TwoCaptchaErrorCode -> String |
163 | errorCode WrongUserKey = "ERROR_WRONG_USER_KEY" |
164 | errorCode KeyDoesNotExist = "ERROR_KEY_DOES_NOT_EXIST" |
165 | errorCode ZeroBalance = "ERROR_ZERO_BALANCE" |
166 | errorCode PageUrlMissing = "ERROR_PAGEURL" |
167 | errorCode NoSlotAvailable = "ERROR_NO_SLOT_AVAILABLE" |
168 | errorCode ZeroCaptchaFileSize = "ERROR_ZERO_CAPTCHA_FILESIZE" |
169 | errorCode TooBigCaptchaFileSize = "ERROR_TOO_BIG_CAPTCHA_FILESIZE" |
170 | errorCode WrongFileExtension = "ERROR_WRONG_FILE_EXTENSION" |
171 | errorCode ImageTypeNotSupported = "ERROR_IMAGE_TYPE_NOT_SUPPORTED" |
172 | errorCode UploadFailure = "ERROR_UPLOAD" |
173 | errorCode IpNotAllowed = "ERROR_IP_NOT_ALLOWED" |
174 | errorCode IpBanned = "IP_BANNED" |
175 | errorCode BadTokenOrPageUrl = "ERROR_BAD_TOKEN_OR_PAGEURL" |
176 | errorCode GoogleKeyInvalid = "ERROR_GOOGLEKEY" |
177 | errorCode GoogleKeyMissing = "ERROR_WRONG_GOOGLEKEY" |
178 | errorCode CaptchaImageBlocked = "ERROR_CAPTCHAIMAGE_BLOCKED" |
179 | errorCode TooManyBadImages = "TOO_MANY_BAD_IMAGES" |
180 | errorCode RateLimited = "MAX_USER_TURN" |
181 | errorCode Error1001 = "ERROR: 1001" |
182 | errorCode Error1002 = "ERROR: 1002" |
183 | errorCode Error1003 = "ERROR: 1003" |
184 | errorCode Error1004 = "ERROR: 1004" |
185 | errorCode Error1005 = "ERROR: 1005" |
186 | errorCode BadParameters = "ERROR_BAD_PARAMETERS" |
187 | errorCode BadProxy = "ERROR_BAD_PROXY" |
188 | errorCode CaptchaNotReady = "CAPCHA_NOT_READY" |
189 | errorCode CaptchaUnsolvable = "ERROR_CAPTCHA_UNSOLVABLE" |
190 | errorCode WrongIdFormat = "ERROR_WRONG_ID_FORMAT" |
191 | errorCode WrongCaptchaId = "ERROR_WRONG_CAPTCHA_ID" |
192 | errorCode BadDuplicates = "ERROR_BAD_DUPLICATES" |
193 | errorCode ReportNotRecorded = "ERROR_REPORT_NOT_RECORDED" |
194 | errorCode DuplicateReport = "ERROR_DUPLICATE_REPORT" |
195 | errorCode InvalidPingbackIp = "ERROR_IP_ADDRES" |
196 | errorCode TokenExpired = "ERROR_TOKEN_EXPIRED" |
197 | errorCode EmptyAction = "ERROR_EMPTY_ACTION" |
198 | errorCode ProxyConnectionFailed = "ERROR_PROXY_CONNECTION_FAILED" |
199 | |
200 | -- | Parser instance for parsing an error code to a 'TwoCaptchaErrorCode'. |
201 | errorParser :: Parser TwoCaptchaErrorCode |
202 | errorParser = |
203 | try (string (errorCode WrongUserKey) $> WrongUserKey) |
204 | <|> try (string (errorCode KeyDoesNotExist) $> KeyDoesNotExist) |
205 | <|> try (string (errorCode ZeroBalance) $> ZeroBalance) |
206 | <|> try (string (errorCode PageUrlMissing) $> PageUrlMissing) |
207 | <|> try (string (errorCode NoSlotAvailable) $> NoSlotAvailable) |
208 | <|> try (string (errorCode ZeroCaptchaFileSize) $> ZeroCaptchaFileSize) |
209 | <|> try (string (errorCode TooBigCaptchaFileSize) $> TooBigCaptchaFileSize) |
210 | <|> try (string (errorCode WrongFileExtension) $> WrongFileExtension) |
211 | <|> try (string (errorCode ImageTypeNotSupported) $> ImageTypeNotSupported) |
212 | <|> try (string (errorCode UploadFailure) $> UploadFailure) |
213 | <|> try (string (errorCode IpNotAllowed) $> IpNotAllowed) |
214 | <|> try (string (errorCode IpBanned) $> IpBanned) |
215 | <|> try (string (errorCode BadTokenOrPageUrl) $> BadTokenOrPageUrl) |
216 | <|> try (string (errorCode GoogleKeyInvalid) $> GoogleKeyInvalid) |
217 | <|> try (string (errorCode GoogleKeyMissing) $> GoogleKeyMissing) |
218 | <|> try (string (errorCode CaptchaImageBlocked) $> CaptchaImageBlocked) |
219 | <|> try (string (errorCode TooManyBadImages) $> TooManyBadImages) |
220 | <|> try (string (errorCode RateLimited) $> RateLimited) |
221 | <|> try (string (errorCode Error1001) $> Error1001) |
222 | <|> try (string (errorCode Error1002) $> Error1002) |
223 | <|> try (string (errorCode Error1003) $> Error1003) |
224 | <|> try (string (errorCode Error1004) $> Error1004) |
225 | <|> try (string (errorCode Error1005) $> Error1005) |
226 | <|> try (string (errorCode BadParameters) $> BadParameters) |
227 | <|> try (string (errorCode BadProxy) $> BadProxy) |
228 | <|> try (string (errorCode CaptchaNotReady) $> CaptchaNotReady) |
229 | <|> try (string (errorCode CaptchaUnsolvable) $> CaptchaUnsolvable) |
230 | <|> try (string (errorCode WrongIdFormat) $> WrongIdFormat) |
231 | <|> try (string (errorCode WrongCaptchaId) $> WrongCaptchaId) |
232 | <|> try (string (errorCode BadDuplicates) $> BadDuplicates) |
233 | <|> try (string (errorCode ReportNotRecorded) $> ReportNotRecorded) |
234 | <|> try (string (errorCode DuplicateReport) $> DuplicateReport) |
235 | <|> try (string (errorCode InvalidPingbackIp) $> InvalidPingbackIp) |
236 | <|> try (string (errorCode TokenExpired) $> TokenExpired $> TokenExpired $> TokenExpired $> TokenExpired) |
237 | <|> try (string (errorCode EmptyAction) $> EmptyAction) |
238 | <|> string (errorCode ProxyConnectionFailed) $> ProxyConnectionFailed |
239 | |
240 | -- | Read an error code as its corresponding 'TwoCaptchaErrorCode'. |
241 | readErrorCode :: String -> Either ParseError TwoCaptchaErrorCode |
242 | readErrorCode = parse errorParser "" |