2captcha (empty) → 0.1.0.0
raw patch · 21 files changed
+1615/−0 lines, 21 filesdep +aesondep +basedep +bytestringsetup-changed
Dependencies added: aeson, base, bytestring, clock, exceptions, http-client, lens, lens-aeson, parsec, text, wreq
Files
- 2captcha.cabal +69/−0
- CHANGELOG.md +4/−0
- LICENSE +21/−0
- README.md +233/−0
- Setup.hs +2/−0
- src/TwoCaptcha/Captcha.hs +41/−0
- src/TwoCaptcha/Internal/Client.hs +84/−0
- src/TwoCaptcha/Internal/Types/Captcha.hs +208/−0
- src/TwoCaptcha/Internal/Types/CapyCaptcha.hs +48/−0
- src/TwoCaptcha/Internal/Types/CoordinateCaptcha.hs +51/−0
- src/TwoCaptcha/Internal/Types/Exception.hs +242/−0
- src/TwoCaptcha/Internal/Types/FunCaptcha.hs +50/−0
- src/TwoCaptcha/Internal/Types/GeeTestCaptcha.hs +50/−0
- src/TwoCaptcha/Internal/Types/GridCaptcha.hs +79/−0
- src/TwoCaptcha/Internal/Types/HCaptcha.hs +55/−0
- src/TwoCaptcha/Internal/Types/KeyCaptcha.hs +50/−0
- src/TwoCaptcha/Internal/Types/NormalCaptcha.hs +88/−0
- src/TwoCaptcha/Internal/Types/ReCaptcha.hs +119/−0
- src/TwoCaptcha/Internal/Types/RotateCaptcha.hs +40/−0
- src/TwoCaptcha/Internal/Types/TextCaptcha.hs +36/−0
- src/TwoCaptcha/Internal/Types/TikTokCaptcha.hs +45/−0
+ 2captcha.cabal view
@@ -0,0 +1,69 @@+cabal-version: 1.12+name: 2captcha+version: 0.1.0.0+license: MIT+license-file: LICENSE+copyright: 2021 Edward Yang+maintainer: edwardyang0410@gmail.com+author: Edward Yang+homepage: https://github.com/qwbarch/2captcha-haskell#readme+bug-reports: https://github.com/qwbarch/2captcha-haskell/issues+synopsis: Haskell package for easy integration with the 2captcha API.+description:+ Haskell package for easy integration with the 2captcha API.+ .+ Feature list:+ .+ * Lens-based API+ * Uses Wreq for http calls++category: Network+build-type: Simple+extra-source-files:+ README.md+ CHANGELOG.md++source-repository head+ type: git+ location: https://github.com/qwbarch/2captcha-haskell++library+ exposed-modules:+ TwoCaptcha.Captcha+ TwoCaptcha.Internal.Client+ TwoCaptcha.Internal.Types.Captcha+ TwoCaptcha.Internal.Types.CapyCaptcha+ TwoCaptcha.Internal.Types.CoordinateCaptcha+ TwoCaptcha.Internal.Types.Exception+ TwoCaptcha.Internal.Types.FunCaptcha+ TwoCaptcha.Internal.Types.GeeTestCaptcha+ TwoCaptcha.Internal.Types.GridCaptcha+ TwoCaptcha.Internal.Types.HCaptcha+ TwoCaptcha.Internal.Types.KeyCaptcha+ TwoCaptcha.Internal.Types.NormalCaptcha+ TwoCaptcha.Internal.Types.ReCaptcha+ TwoCaptcha.Internal.Types.RotateCaptcha+ TwoCaptcha.Internal.Types.TextCaptcha+ TwoCaptcha.Internal.Types.TikTokCaptcha++ hs-source-dirs: src+ other-modules: Paths_2captcha+ default-language: Haskell2010+ default-extensions:+ OverloadedStrings FlexibleContexts FlexibleInstances+ UndecidableInstances RankNTypes ScopedTypeVariables LambdaCase+ MultiParamTypeClasses TemplateHaskell++ ghc-options: -Wall -Wno-name-shadowing+ build-depends:+ aeson >=1.5.6.0 && <1.6,+ base >=4.7 && <5,+ bytestring >=0.10.12.0 && <0.11,+ clock >=0.8.2 && <0.9,+ exceptions >=0.10.4 && <0.11,+ http-client >=0.6.4.1 && <0.7,+ lens >=4.19.2 && <4.20,+ lens-aeson >=1.1.1 && <1.2,+ parsec >=3.1.14.0 && <3.2,+ text >=1.2.4.1 && <1.3,+ wreq >=0.5.3.3 && <0.6
+ CHANGELOG.md view
@@ -0,0 +1,4 @@+# Changelog for 2captcha-haskell++## [0.1.0.0] - 2021-09-08+- Initial release
+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2021 Edward Yang++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ README.md view
@@ -0,0 +1,233 @@+# 2captcha-haskell++The easiest way to integrate 2captcha into your application to automate common types of captchas.++#### Table of Contents+- [Solving a captcha](#solving-a-captcha)+ - [Normal Captcha](#normal-captcha)+ - [Text Captcha](#text-captcha)+ - [ReCaptcha V2](#recaptcha-v2)+ - [ReCaptcha V3](#recaptcha-v3)+ - [FunCaptcha](#funcaptcha)+ - [GeeTest](#geetest)+ - [hCaptcha](#hcaptcha)+ - [KeyCaptcha](#keycaptcha)+ - [Capy](#capy)+ - [Grid](#grid)+ - [Coordinate](#coordinate)+ - [Rotate](#rotate)+ - [TikTok](#tiktok)++## Solving a captcha++Solving a captcha using 2captcha's api is through the ``in.php`` and ``res.php`` endpoints. +This package encapsulates the mentioned endpoints through [submit](https://github.com/qwbarch/2captcha-haskell/blob/e442950a79f1aef7fd2fb95aac9cd9bfe41a8df7/src/TwoCaptcha/Internal/Client.hs#L48) and [answer](https://github.com/qwbarch/2captcha-haskell/blob/e442950a79f1aef7fd2fb95aac9cd9bfe41a8df7/src/TwoCaptcha/Internal/Client.hs#L51). +If you'd like to poll for the answer, use [solve](https://github.com/qwbarch/2captcha-haskell/blob/e442950a79f1aef7fd2fb95aac9cd9bfe41a8df7/src/TwoCaptcha/Internal/Client.hs#L54).++[Default timeout](https://github.com/qwbarch/2captcha-haskell/blob/e442950a79f1aef7fd2fb95aac9cd9bfe41a8df7/src/TwoCaptcha/Internal/Types/Captcha.hs#L22): 120 seconds. +[ReCAPTCHA timeout](https://github.com/qwbarch/2captcha-haskell/blob/e442950a79f1aef7fd2fb95aac9cd9bfe41a8df7/src/TwoCaptcha/Internal/Types/ReCaptcha.hs#L118): 600 seconds. +[Polling interval](https://github.com/qwbarch/2captcha-haskell/blob/e442950a79f1aef7fd2fb95aac9cd9bfe41a8df7/src/TwoCaptcha/Internal/Types/Captcha.hs#L26): 10 seconds++Below are the minimal required parameters to solve each type of captcha.++### Normal Captcha++This function can be used to solve a local image captcha.++```haskell+let captcha =+ normalCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & method ?~ "post"+ & file ?~ "/path/to/file"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++This function can be used to solve a captcha encoded in base-64 form.++```haskell+let captcha =+ normalCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & method ?~ "base64"+ & body ?~ "BASE_64_ENCODED_IMAGE"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++### Text Captcha++This function can be used to solve captchas in text form.++```haskell+let captcha =+ textCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & textContent ?~ "If tomorrow is Saturday, what day is it today?"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++### ReCAPTCHA v2++ReCAPTCHA v2 requires a ``k`` or ``data-sitekey`` value found on the captcha page.++```haskell+let captcha =+ reCAPTCHAV2+ & apiKey ?~ "YOUR_API_KEY"+ & googleKey ?~ "GOOGLE_KEY_VALUE"+ & pageUrl ?~ "PAGE_URL"+session <- newAPISession+solve session captcha pollingInterval reCAPTCHATimeout+```++### ReCaptcha v3++ReCAPTCHA v3 requires a ``k`` or ``data-sitekey`` value found on the captcha page.++```haskell+let captcha =+ reCAPTCHAV3+ & apiKey ?~ "YOUR_API_KEY"+ & googleKey ?~ "GOOGLE_KEY_VALUE"+ & pageUrl ?~ "PAGE_URL"+session <- newAPISession+solve session captcha pollingInterval reCAPTCHATimeout+```++### FunCaptcha++FunCaptcha (ArkoseLabs) requires a ``pk`` or ``data-pkey`` value found on the captcha page.++```haskell+let captcha =+ funCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & publicKey ?~ "PUBLIC_KEY"+ & pageUrl ?~ "PAGE_URL"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++### GeeTest++GeeTest requires the ``gt``, ``challenge``, and ``api_server`` values on the captcha page.++```haskell+let captcha =+ geeTestCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & gt ?~ "GT_VALUE"+ & apiServer ?~ "API_SERVER"+ & challenge ?~ "CAPTCHA_CHALLENGE"+ & pageUrl ?~ "PAGE_URL"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++### hCaptcha++hCaptcha requires the ``data-sitekey`` value on the captcha page.++```haskell+let captcha =+ hCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & siteKey ?~ "SITE_KEY"+ & pageUrl ?~ "PAGE_URL"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++### KeyCaptcha++KeyCaptcha requires the ``s_s_c_user_id``, ``s_s_c_session_id``, ``s_s_c_web_server_sign``, and ``s_s_c_web_server_sign2`` values on the captcha page.++```haskell+let captcha =+ keyCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & userId ?~ "USER_ID_VALUE"+ & sessionId ?~ "SESSION_ID_VALUE"+ & webServerSign ?~ "WEB_SERVER_SIGN_VALUE"+ & webServerSign2 ?~ "WEB_SERVER_SIGN_2_VALUE"+ & pageUrl ?~ "PAGE_URL"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++### Capy++Capy requires the ``captchakey`` value on the captcha page.++```haskell+let captcha =+ capyCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & captchaKey ?~ "CAPTCHA_KEY"+ & pageUrl ?~ "PAGE_URL"+ & scriptDomain ?~ "SCRIPT_DOMAIN"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++### Grid++This function can be used to solve a local grid image captcha.++```haskell+let captcha =+ gridCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & method ?~ "post"+ & file ?~ "/path/to/file"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++### Coordinate++This function can be used to solve a local coordinate image captcha.++```haskell+let captcha =+ coordinateCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & method ?~ "post"+ & file ?~ "/path/to/file"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++### Rotate++This function can be used to solve a local rotate image captcha.++```haskell+let captcha =+ rotateCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & file ?~ "/path/to/file"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++### TikTok++TikTok requires the ``aid`` and ``host`` values on the captcha page.++```haskell+let captcha =+ tikTokCaptcha+ & apiKey ?~ "YOUR_API_KEY"+ & cookies ?~ "YOUR_COOKIES"+ & aid ?~ 0+ & host ?~ "HOST_VALUE"+ & pageUrl ?~ "PAGE_URL"+session <- newAPISession+solve session captcha pollingInterval captchaTimeout+```++
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/TwoCaptcha/Captcha.hs view
@@ -0,0 +1,41 @@+module TwoCaptcha.Captcha+ ( module TwoCaptcha.Internal.Types.Captcha,+ module TwoCaptcha.Internal.Types.CapyCaptcha,+ module TwoCaptcha.Internal.Types.CoordinateCaptcha,+ module TwoCaptcha.Internal.Types.Exception,+ module TwoCaptcha.Internal.Types.FunCaptcha,+ module TwoCaptcha.Internal.Types.GeeTestCaptcha,+ module TwoCaptcha.Internal.Types.GridCaptcha,+ module TwoCaptcha.Internal.Types.HCaptcha,+ module TwoCaptcha.Internal.Types.KeyCaptcha,+ module TwoCaptcha.Internal.Types.NormalCaptcha,+ module TwoCaptcha.Internal.Types.ReCaptcha,+ module TwoCaptcha.Internal.Types.RotateCaptcha,+ module TwoCaptcha.Internal.Types.TextCaptcha,+ module TwoCaptcha.Internal.Types.TikTokCaptcha,+ module TwoCaptcha.Internal.Client,+ )+where++import TwoCaptcha.Internal.Client hiding (handle)+import TwoCaptcha.Internal.Types.Captcha hiding+ ( defaultCaptcha,+ mkParamLens,+ mkParamLens',+ mkParamLensBool,+ mkPartLens,+ mkPartTextLens,+ )+import TwoCaptcha.Internal.Types.CapyCaptcha+import TwoCaptcha.Internal.Types.CoordinateCaptcha+import TwoCaptcha.Internal.Types.Exception+import TwoCaptcha.Internal.Types.FunCaptcha+import TwoCaptcha.Internal.Types.GeeTestCaptcha+import TwoCaptcha.Internal.Types.GridCaptcha+import TwoCaptcha.Internal.Types.HCaptcha+import TwoCaptcha.Internal.Types.KeyCaptcha+import TwoCaptcha.Internal.Types.NormalCaptcha+import TwoCaptcha.Internal.Types.ReCaptcha+import TwoCaptcha.Internal.Types.RotateCaptcha+import TwoCaptcha.Internal.Types.TextCaptcha+import TwoCaptcha.Internal.Types.TikTokCaptcha
+ src/TwoCaptcha/Internal/Client.hs view
@@ -0,0 +1,84 @@+module TwoCaptcha.Internal.Client where++import Control.Concurrent (threadDelay)+import Control.Lens ((&), (.~), (?~), (^.), (^?))+import Control.Monad.Catch (MonadCatch, MonadThrow (throwM), try)+import Control.Monad.IO.Class (MonadIO (liftIO))+import Data.Aeson.Lens (key, _Integer, _String)+import Data.ByteString.Lazy.Char8 (ByteString)+import Data.Text (Text, unpack)+import GHC.Base (Coercible, coerce)+import Network.Wreq (Response, responseBody)+import Network.Wreq.Session (Session, getWith, postWith)+import System.Clock (Clock (Monotonic), getTime, toNanoSecs)+import TwoCaptcha.Internal.Types.Captcha (Captcha, CaptchaId, CaptchaRes (CaptchaRes), HasCaptchaLenses, HasCommonCaptchaLenses (apiKey, headerACAO), PollingInterval, TimeoutDuration, captchaId, captchaRes, options, parts)+import TwoCaptcha.Internal.Types.Exception (TwoCaptchaErrorCode (CaptchaNotReady), TwoCaptchaException (NetworkException, SolvingTimeout, TwoCaptchaResponseException, UnknownError), readErrorCode)++-- | Runs the given http method and adapts errors to 'TwoCaptchaException'.+handle :: (MonadIO m, MonadCatch m) => IO (Response ByteString) -> m Text+handle method =+ try (liftIO method) >>= \case+ -- HttpException found due to non-200 status code. Rethrow as NetworkException.+ Left exception -> throwM $ NetworkException exception+ Right response -> do+ let statusRequest = do+ body <- response ^? responseBody+ status <- body ^? key "status" . _Integer+ request <- body ^? key "request" . _String+ return (status, request)+ case statusRequest of+ -- 'status' and 'request' fields are missing.+ Nothing -> do+ liftIO $ print response+ throwM $ UnknownError "The response is not the expected JSON. This is likely due to 2captcha changing their API."+ Just (status, request) -> do+ -- 'status' 0 means an error was returned.+ if status == 0+ then case readErrorCode (unpack request) of+ -- Parsing the error code failed even though an error was returned. This means the error code is not known yet.+ Left _ -> throwM $ UnknownError ("Invalid error: " <> request)+ -- Parsing the error code succeeded.+ Right errorCode -> throwM $ TwoCaptchaResponseException errorCode+ else -- No error was found.+ pure request++-- | Encapsulates the __in.php__ and __res.php__ endpoints for the 2captcha API.+class TwoCaptchaClient m where+ -- | Submit a captcha to be solved by the 2captcha API. Returns a captcha id used for 'answer'.+ submit :: (Coercible Captcha a, HasCaptchaLenses a, HasCommonCaptchaLenses a) => Session -> a -> m CaptchaId++ -- | Attempt to retrieve the answer of a captcha previously submitted.+ answer :: Session -> CaptchaRes -> m Text++ -- | Submits a captcha and polls for the answer.+ solve :: (Coercible Captcha a, HasCaptchaLenses a, HasCommonCaptchaLenses a) => PollingInterval -> TimeoutDuration -> Session -> a -> m Text++instance (MonadIO m, MonadCatch m) => TwoCaptchaClient m where+ submit session captcha' = handle $ postWith (captcha ^. options) session "https://2captcha.com/in.php" (captcha ^. parts)+ where+ captcha = coerce captcha'+ answer session (CaptchaRes captchaRes) = handle $ getWith (captchaRes ^. options) session "https://2captcha.com/res.php"+ solve pollingInterval timeoutDuration session captcha = do+ captchaId' <- submit session captcha+ let captchaRes' =+ captchaRes+ & apiKey .~ (captcha ^. apiKey)+ & headerACAO .~ (captcha ^. headerACAO)+ & captchaId ?~ captchaId'+ let time = liftIO $ (\t -> toNanoSecs t `div` 1000000) <$> getTime Monotonic+ startTime <- time+ let pollAnswer previousTime currentTime =+ -- Elapsed time is past the timeout duration+ if currentTime - previousTime >= timeoutDuration+ then throwM SolvingTimeout+ else do+ liftIO $ threadDelay (pollingInterval * 1000)+ -- Attempt to retrieve the answer. If it's not ready yet, retry.+ answerAttempt <- try $ answer session captchaRes'+ case answerAttempt of+ Left (TwoCaptchaResponseException CaptchaNotReady) -> do+ updatedTime <- time+ pollAnswer currentTime updatedTime+ Left exception -> throwM exception+ Right answer -> pure answer+ pollAnswer startTime startTime
+ src/TwoCaptcha/Internal/Types/Captcha.hs view
@@ -0,0 +1,208 @@+module TwoCaptcha.Internal.Types.Captcha where++import Control.Lens (Getter, Lens', iso, lens, to, (%~), (&), (.~), (^.))+import Control.Lens.TH (makeLenses)+import Data.String (IsString)+import Data.Text (Text, pack, unpack)+import GHC.Base (Coercible, coerce)+import Network.Wreq (Options, Part, defaults, param, partFile, partText)++-- import Prelude hiding (lookup)++-- | The id of a captcha being solved.+type CaptchaId = Text++-- | Time in milliseconds in how often to request the answer.+type PollingInterval = Int++-- | Time in milliseconds on when to timeout if the request takes too long.+type TimeoutDuration = Integer++-- | Default captcha timeout duration (120 seconds).+captchaTimeout :: TimeoutDuration+captchaTimeout = 120000++-- | Default polling interval (10 seconds).+pollingInterval :: PollingInterval+pollingInterval = 10000++-- | Represents the request information required to solve a captcha.+data Captcha = MkCaptcha+ { _options :: Options,+ _partTexts :: [(Text, Text)],+ _partFiles :: [(Text, FilePath)]+ }+ deriving (Show)++makeLenses ''Captcha++-- | Convert the captcha's multipart form parameters into a ['Part'].+parts :: Getter Captcha [Part]+parts = to (\captcha -> (uncurry partText <$> captcha ^. partTexts) ++ (uncurry partFile <$> captcha ^. partFiles))++instance HasCommonCaptchaLenses Captcha++instance HasCaptchaLenses Captcha++-- | Default parameters for solving a captcha. Internal use only.+defaultCaptcha :: Captcha+defaultCaptcha = MkCaptcha (defaults & param "json" .~ ["1"]) [] []++-- | Create a lens using the given field name for multipart forms.+mkPartLens :: (Coercible Captcha a, IsString s) => Lens' Captcha [(Text, s)] -> Text -> Lens' a (Maybe s)+mkPartLens partLens field = lens getter setter+ where+ getter a = lookup field (coerce a ^. partLens)+ setter a (Just value) = coerce $ coerce a & partLens %~ ((field, value) :)+ setter a Nothing = a++-- | Create a lens using the given field name for multipart form texts.+mkPartTextLens :: Coercible Captcha a => Text -> Lens' a (Maybe Text)+mkPartTextLens = mkPartLens partTexts++-- | Create a lens using the given field name for multipart form files.+mkPartFileLens :: Coercible Captcha a => Text -> Lens' a (Maybe FilePath)+mkPartFileLens = mkPartLens partFiles++-- | Creates a lens using the given field name for query parameters.+mkParamLens :: Coercible Captcha a => Text -> Lens' a (Maybe Text)+mkParamLens field = lens getter setter+ where+ getter a =+ let value = coerce a ^. options . param field+ in if null value then Nothing else Just $ head value+ setter a (Just value) = coerce $ coerce a & options %~ (& param field .~ [value])+ setter a Nothing = a++-- |+-- Create a lens using the given field name for type __b__ with a 'Show' and 'Read' instance.+--+-- GOTCHA: Bool values translate to 'True' or 'False'. Use 'mkLensBool' instead for bool lenses.+mkParamLens' :: (Coercible Captcha a, Show b, Read b) => Text -> Lens' a (Maybe b)+mkParamLens' field = mkParamLens field . iso (read . unpack <$>) (pack . show <$>)++-- |+-- Create a lens using the given field name for bools.+--+-- The boolean values become:+--+-- * 'True' - 1+-- * 'False' - 0+mkParamLensBool :: Coercible Captcha a => Text -> Lens' a (Maybe Bool)+mkParamLensBool field = mkParamLens field . iso (textToBool <$>) (boolToText <$>)+ where+ textToBool "0" = False+ textToBool "1" = True+ textToBool number = error $ unpack number <> " is not a valid bool value. This should never occur, please don't manipulate the options manually."+ boolToText False = "0"+ boolToText True = "1"++-- | Lenses for constructing options for 'TwoCaptcha.Internal.Client.submit'.+class Coercible Captcha a => HasCaptchaLenses a where+ -- | Software developer id. Developers who integrate their software with 2captcha earn 10% of the user's spendings.+ softId :: Lens' a (Maybe Int)+ softId = mkParamLens' "soft_id"++ -- | URL for <https://2captcha.com/2captcha-api#pingback pingback> (callback) response that will be sent the answer to when the captcha is solved.+ pingback :: Lens' a (Maybe Text)+ pingback = mkParamLens "pingback"++ -- | Type of captcha to solve.+ method :: Lens' a (Maybe Text)+ method = mkParamLens "method"++-- | Lenses for constructing options for 'TwoCaptcha.Internal.Client.submit' and 'TwoCaptcha.Internal.Client.answer'.+class Coercible Captcha a => HasCommonCaptchaLenses a where+ -- | Your 2captcha API <https://2captcha.com/2captcha-api#solving_captchas key>.+ apiKey :: Lens' a (Maybe Text)+ apiKey = mkParamLens "key"++ -- |+ -- If True, 'TwoCaptcha.Internal.Client.submit' will include the __Access-Control-Allow-Origin:*__ header in the response.+ -- Used for cross-domain AJAX requests in web applications.+ headerACAO :: Lens' a (Maybe Bool)+ headerACAO = mkParamLensBool "header_acao"++-- | Parameters used to retrieve the 'TwpCaptcha.Internal.Client.answer' of a solved captcha.+newtype CaptchaRes = CaptchaRes Captcha deriving (Show)++instance HasCommonCaptchaLenses CaptchaRes++-- |+-- Parameters for retrieving a captcha's answer.+--+-- Required parameters:+--+-- * 'apiKey'+-- * 'captchaId'+--+-- Optional parameters:+--+-- * 'headerACAO'+captchaRes :: CaptchaRes+captchaRes = CaptchaRes (defaultCaptcha & options %~ (& param "action" .~ ["get"]))++-- | The captcha id returned from 'TwoCaptcha.Internal.Client.submit'.+captchaId :: Lens' CaptchaRes (Maybe Text)+captchaId = mkParamLens "id"++class Coercible Captcha a => HasPageURL a where+ -- | Full URL of the page where the captcha is found.+ pageUrl :: Lens' a (Maybe Text)+ pageUrl = mkParamLens "pageurl"++class Coercible Captcha a => HasProxy a where+ -- |+ -- Proxy to be sent to the worker who solves the captcha. You can read more about proxies <https://2captcha.com/2captcha-api#proxies here>.+ --+ -- Format must be in __login:password@123.123.123.123:3128__ .+ proxy :: Lens' a (Maybe Text)+ proxy = mkParamLens "proxy"++ -- | Type of your proxy: __HTTP__, __HTTPS__, __SOCKS4__, __SOCKS5__.+ proxyType :: Lens' a (Maybe Text)+ proxyType = mkParamLens "proxytype"++class Coercible Captcha a => HasLocalImage a where+ -- | File path of a captcha image.+ file :: Lens' a (Maybe FilePath)+ file = mkPartFileLens "file"++ -- | Base-64 encoded image.+ body :: Lens' a (Maybe Text)+ body = mkPartTextLens "body"++ -- | Text which is shown to the worker to help solve a captcha.+ textInstructions :: Lens' a (Maybe Text)+ textInstructions = mkParamLens "textInstructions"++ -- | Image file path with instructions on solving a captcha.+ imgInstructions :: Lens' a (Maybe FilePath)+ imgInstructions = mkPartFileLens "imgInstructions"++class Coercible Captcha a => HasLanguage a where+ -- |+ -- The captcha's language:+ --+ -- 0. Not specified.+ -- 1. Cyrillic captcha.+ -- 2. Latin captcha.+ language :: Lens' a (Maybe Int)+ language = mkParamLens' "language"++ -- | The captcha's language code. Click <https://2captcha.com/2captcha-api#language here> for a list of supported languages.+ languageCode :: Lens' a (Maybe Text)+ languageCode = mkParamLens "lang"++class Coercible Captcha a => HasUserAgent a where+ -- | User agent that will be used by the worker when solving the captcha.+ userAgent :: Lens' a (Maybe Text)+ userAgent = mkParamLens "userAgent"++class Coercible Captcha a => HasCookies a where+ -- |+ -- Cookies that will be used by the worker solving the captcha. The used cookies will also be included in the response.+ --+ -- Format: __KEY1:Value1;KEY2:Value2;__+ cookies :: Lens' a (Maybe Text)+ cookies = mkParamLens "cookies"
+ src/TwoCaptcha/Internal/Types/CapyCaptcha.hs view
@@ -0,0 +1,48 @@+module TwoCaptcha.Internal.Types.CapyCaptcha where++import Control.Lens (Lens', (&), (?~))+import Data.Text (Text)+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses (method), HasCommonCaptchaLenses, HasPageURL, HasProxy, defaultCaptcha, mkParamLens)++-- | Parameters used to solve a capy puzzle captcha.+newtype CapyCaptcha = MkCapyCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses CapyCaptcha++instance HasCaptchaLenses CapyCaptcha++instance HasPageURL CapyCaptcha++instance HasProxy CapyCaptcha++-- |+-- Parameters used to solve a capy puzzle captcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'captchaKey'+-- * 'scriptDomain'+-- * 'TwoCaptcha.Internal.Types.Captcha.pageUrl'+--+-- Optional parameters:+--+-- * 'scriptDomain'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxy'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxyType'+capyCaptcha :: CapyCaptcha+capyCaptcha = MkCapyCaptcha (defaultCaptcha & method ?~ "capy")++-- | Value of __captchakey__ parameter you found on page.+captchaKey :: Lens' CapyCaptcha (Maybe Text)+captchaKey = mkParamLens "captchakey"++-- |+-- The domain part of the script URL found on page.+--+-- If not specified, defaults to: https://jp.api.capy.me/+scriptDomain :: Lens' CapyCaptcha (Maybe Text)+scriptDomain = mkParamLens "api_server"
+ src/TwoCaptcha/Internal/Types/CoordinateCaptcha.hs view
@@ -0,0 +1,51 @@+module TwoCaptcha.Internal.Types.CoordinateCaptcha where++import Control.Lens (Lens')+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses, HasCommonCaptchaLenses, HasLanguage, HasLocalImage, defaultCaptcha, mkParamLensBool)++-- | Parameters used to solve a coordinate captcha.+newtype CoordinateCaptcha = MkCoordinateCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses CoordinateCaptcha++instance HasCaptchaLenses CoordinateCaptcha++instance HasLocalImage CoordinateCaptcha++instance HasLanguage CoordinateCaptcha++-- | Parameters used to solve a coordinate captcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'TwoCaptcha.Internal.Types.Captcha.method'+-- * 'coordinateReCAPTCHAImage'+-- * 'TwoCaptcha.Internal.Types.Captcha.file'*+-- * 'TwoCaptcha.Internal.Types.Captcha.body'*+--+-- Optional parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.textInstructions'+-- * 'TwoCaptcha.Internal.Types.Captcha.imgInstructions'+-- * 'TwoCaptcha.Internal.Types.Captcha.language'+-- * 'TwoCaptcha.Internal.Types.Captcha.languageCode'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+--+-- Possible 'TwoCaptcha.Internal.Types.Captcha.method' values:+--+-- * __post__ - defines that you're sending an image with multipart form+-- * __base64__ - defines that you're sending a base64 encoded image+--+-- Starred required parameter rules:+--+-- * __file__ is only required if __captcha = "post"__+-- * __body__ is only required if __captcha = "base64"__+coordinateCaptcha :: CoordinateCaptcha+coordinateCaptcha = MkCoordinateCaptcha defaultCaptcha++-- | Defines that you're sending a reCAPTCHA as an image.+coordinateReCAPTCHAImage :: Lens' CoordinateCaptcha (Maybe Bool)+coordinateReCAPTCHAImage = mkParamLensBool "coordinatescaptcha"
+ src/TwoCaptcha/Internal/Types/Exception.hs view
@@ -0,0 +1,242 @@+module TwoCaptcha.Internal.Types.Exception where++import Control.Exception (Exception)+import Data.Functor (($>))+import Data.Text (Text)+import Network.HTTP.Client (HttpException)+import Text.Parsec (ParseError, parse, try, (<|>))+import Text.Parsec.Char (string)+import Text.Parsec.String (Parser)++-- | Represents a possible exception when interacting with the 2captcha API.+data TwoCaptchaException+ = -- | An error documented on 2captcha's website.+ TwoCaptchaResponseException TwoCaptchaErrorCode+ | -- | A non-200 status code was thrown. This should only appear in rare cases.+ NetworkException HttpException+ | -- | An unknown error occured, likely due to a change in the 2captcha API.+ UnknownError Text+ | -- | Solving the captcha took too long. Try setting a higher timeout duration?+ SolvingTimeout+ deriving (Show)++instance Exception TwoCaptchaException++-- | Possible errors when using the 2captcha API.+data TwoCaptchaErrorCode+ = -- | The api key you provided is invalid. Please ensure it is 32 characters long.+ WrongUserKey+ | -- | The key you've provided does not exist.+ KeyDoesNotExist+ | -- | You don't have funds in your account.+ ZeroBalance+ | -- | The __pageurl__ parameter is missing in your request.+ PageUrlMissing+ | -- |+ -- You can receive this error in two cases:+ --+ -- 1. __If you solve token-based captchas (reCAPTCHA, hCaptcha, ArkoseLabs FunCaptcha, GeeTest, etc):__+ -- the queue of your captchas that are not distributed to workers is too long.+ -- Queue limit changes dynamically and depends on total amount of captchas awaiting solution and usually it’s between 50 and 100 captchas.+ --+ -- 2. __If you solve Normal Captcha:__ your maximum rate for normal captchas is lower than current rate on the server.+ -- You can change your maximum rate in <https://2captcha.com/setting your account's settings.>+ NoSlotAvailable+ | -- | Image size is less than 100 bytes.+ ZeroCaptchaFileSize+ | -- | Image size is more than 100 kB.+ TooBigCaptchaFileSize+ | -- | Image file has unsupported extension. Accepted extensions: jpg, jpeg, gif, png.+ WrongFileExtension+ | -- | Server can't recognize image file type.+ ImageTypeNotSupported+ | -- |+ -- Server can't get file data from your POST-request.+ -- That happens if your POST-request is malformed or base64 data is not a valid base64 image.+ UploadFailure+ | -- | The request is sent from the IP that is not on the list of your allowed IPs.+ IpNotAllowed+ | -- | Your IP address is banned due to many frequent attempts to access the server using wrong authorization keys.+ IpBanned+ | -- |+ -- You can get this error code when sending reCAPTCHA V2. This happens if your request contains invalid pair of googlekey and pageurl.+ -- The common reason for that is that reCAPTCHA is loaded inside an iframe hosted on another domain/subdomain.+ BadTokenOrPageUrl+ | -- | 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.+ GoogleKeyInvalid+ | -- | The __googlekey__ parameter is missing in your request.+ GoogleKeyMissing+ | -- |+ -- You've sent an image that is marked in 2captcha's database as unrecognizable.+ -- Usually that happens if the website where you found the captcha stopped sending you captchas and started to send a "deny access" image.+ CaptchaImageBlocked+ | -- | You are sending too many unrecognizable images.+ TooManyBadImages+ | -- |+ -- You made more than 60 requests to in.php within 3 seconds.+ -- Your account is banned for 10 seconds. Ban will be lifted automatically.+ RateLimited+ | -- |+ -- You received the error 'NoSlotAvailable' 120 times in one minute because your current bid is lower than current bid on the server.+ --+ -- Blocking time: 10 minutes.+ Error1001+ | -- |+ -- You received the error 'ZeroBalance' 120 times in one minute because your balance is zero.+ --+ -- Blocking time: 5 minutes.+ Error1002+ | -- |+ -- 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.+ -- 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.+ --+ -- Blocking time: 30 seconds.+ Error1003+ | -- | Your IP address is blocked because there were 5 requests with incorrect API key from your IP.+ Error1004+ | -- |+ -- You are making too many requests to res.php to get answers.+ --+ --+ -- 2captcha uses the following rule to block your account: R > C * 20 + 1200+ --+ -- Where:+ --+ -- * R - the amount of your requests+ --+ -- * C - the amount of captchas you've uploaded+ --+ -- That means that you don't have to make more than 20 requests to res.php per each captcha.+ -- Please remember that balance request sent to res.php also counts!+ --+ -- 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.+ --+ -- Blocking time: 10 minutes.+ Error1005+ | -- |+ -- The error code is returned if some required parameters are missing in your request or the values have incorrect format.+ -- For example if you submit <https://2captcha.com/2captcha-api#grid Grid images> but your request is missing an instruction for workers.+ --+ -- Blocking time: 5 minutes.+ BadParameters+ | -- | You can get this error code when sending a captcha via proxy server which is marked as BAD by the 2captcha API.+ BadProxy+ | -- | Your captcha is not solved yet.+ CaptchaNotReady+ | -- |+ -- 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).+ --+ -- You will not be charged for that request.+ CaptchaUnsolvable+ | -- | You've provided captcha ID in wrong format. The ID can contain numbers only.+ WrongIdFormat+ | -- | You provided an invalid captcha id.+ WrongCaptchaId+ | -- | 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.+ BadDuplicates+ | -- |+ -- 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%).+ -- Or if more than 15 minutes passed after you submitted the captcha.+ ReportNotRecorded+ | -- | 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.+ DuplicateReport+ | -- |+ -- You can receive this error code when registering a <https://2captcha.com/2captcha-api#pingback pingback (callback)> IP or domain.+ --+ -- This happens if your request is coming from an IP address that doesn't match the IP address of your pingback IP or domain.+ InvalidPingbackIp+ | -- |+ -- You can receive this error code when sending <https://2captcha.com/2captcha-api#solving_geetest GeeTest>.+ -- This error means the __challenge__ value you provided is expired.+ TokenExpired+ | -- | Action parameter is missing or no value is provided for __action__ parameter.+ EmptyAction+ | -- |+ -- You can get this error code if we were unable to load a captcha through your proxy server.+ -- The proxy will be marked as BAD by our API and we will not accept requests with the proxy during 10 minutes.+ -- You will recieve ERROR_BAD_PROXY code from in.php API endpoint in such case.+ ProxyConnectionFailed+ deriving (Show, Eq)++-- | The raw error code provided by 2captcha.+errorCode :: TwoCaptchaErrorCode -> String+errorCode WrongUserKey = "ERROR_WRONG_USER_KEY"+errorCode KeyDoesNotExist = "ERROR_KEY_DOES_NOT_EXIST"+errorCode ZeroBalance = "ERROR_ZERO_BALANCE"+errorCode PageUrlMissing = "ERROR_PAGEURL"+errorCode NoSlotAvailable = "ERROR_NO_SLOT_AVAILABLE"+errorCode ZeroCaptchaFileSize = "ERROR_ZERO_CAPTCHA_FILESIZE"+errorCode TooBigCaptchaFileSize = "ERROR_TOO_BIG_CAPTCHA_FILESIZE"+errorCode WrongFileExtension = "ERROR_WRONG_FILE_EXTENSION"+errorCode ImageTypeNotSupported = "ERROR_IMAGE_TYPE_NOT_SUPPORTED"+errorCode UploadFailure = "ERROR_UPLOAD"+errorCode IpNotAllowed = "ERROR_IP_NOT_ALLOWED"+errorCode IpBanned = "IP_BANNED"+errorCode BadTokenOrPageUrl = "ERROR_BAD_TOKEN_OR_PAGEURL"+errorCode GoogleKeyInvalid = "ERROR_GOOGLEKEY"+errorCode GoogleKeyMissing = "ERROR_WRONG_GOOGLEKEY"+errorCode CaptchaImageBlocked = "ERROR_CAPTCHAIMAGE_BLOCKED"+errorCode TooManyBadImages = "TOO_MANY_BAD_IMAGES"+errorCode RateLimited = "MAX_USER_TURN"+errorCode Error1001 = "ERROR: 1001"+errorCode Error1002 = "ERROR: 1002"+errorCode Error1003 = "ERROR: 1003"+errorCode Error1004 = "ERROR: 1004"+errorCode Error1005 = "ERROR: 1005"+errorCode BadParameters = "ERROR_BAD_PARAMETERS"+errorCode BadProxy = "ERROR_BAD_PROXY"+errorCode CaptchaNotReady = "CAPCHA_NOT_READY"+errorCode CaptchaUnsolvable = "ERROR_CAPTCHA_UNSOLVABLE"+errorCode WrongIdFormat = "ERROR_WRONG_ID_FORMAT"+errorCode WrongCaptchaId = "ERROR_WRONG_CAPTCHA_ID"+errorCode BadDuplicates = "ERROR_BAD_DUPLICATES"+errorCode ReportNotRecorded = "ERROR_REPORT_NOT_RECORDED"+errorCode DuplicateReport = "ERROR_DUPLICATE_REPORT"+errorCode InvalidPingbackIp = "ERROR_IP_ADDRES"+errorCode TokenExpired = "ERROR_TOKEN_EXPIRED"+errorCode EmptyAction = "ERROR_EMPTY_ACTION"+errorCode ProxyConnectionFailed = "ERROR_PROXY_CONNECTION_FAILED"++-- | Parser instance for parsing an error code to a 'TwoCaptchaErrorCode'.+errorParser :: Parser TwoCaptchaErrorCode+errorParser =+ try (string (errorCode WrongUserKey) $> WrongUserKey)+ <|> try (string (errorCode KeyDoesNotExist) $> KeyDoesNotExist)+ <|> try (string (errorCode ZeroBalance) $> ZeroBalance)+ <|> try (string (errorCode PageUrlMissing) $> PageUrlMissing)+ <|> try (string (errorCode NoSlotAvailable) $> NoSlotAvailable)+ <|> try (string (errorCode ZeroCaptchaFileSize) $> ZeroCaptchaFileSize)+ <|> try (string (errorCode TooBigCaptchaFileSize) $> TooBigCaptchaFileSize)+ <|> try (string (errorCode WrongFileExtension) $> WrongFileExtension)+ <|> try (string (errorCode ImageTypeNotSupported) $> ImageTypeNotSupported)+ <|> try (string (errorCode UploadFailure) $> UploadFailure)+ <|> try (string (errorCode IpNotAllowed) $> IpNotAllowed)+ <|> try (string (errorCode IpBanned) $> IpBanned)+ <|> try (string (errorCode BadTokenOrPageUrl) $> BadTokenOrPageUrl)+ <|> try (string (errorCode GoogleKeyInvalid) $> GoogleKeyInvalid)+ <|> try (string (errorCode GoogleKeyMissing) $> GoogleKeyMissing)+ <|> try (string (errorCode CaptchaImageBlocked) $> CaptchaImageBlocked)+ <|> try (string (errorCode TooManyBadImages) $> TooManyBadImages)+ <|> try (string (errorCode RateLimited) $> RateLimited)+ <|> try (string (errorCode Error1001) $> Error1001)+ <|> try (string (errorCode Error1002) $> Error1002)+ <|> try (string (errorCode Error1003) $> Error1003)+ <|> try (string (errorCode Error1004) $> Error1004)+ <|> try (string (errorCode Error1005) $> Error1005)+ <|> try (string (errorCode BadParameters) $> BadParameters)+ <|> try (string (errorCode BadProxy) $> BadProxy)+ <|> try (string (errorCode CaptchaNotReady) $> CaptchaNotReady)+ <|> try (string (errorCode CaptchaUnsolvable) $> CaptchaUnsolvable)+ <|> try (string (errorCode WrongIdFormat) $> WrongIdFormat)+ <|> try (string (errorCode WrongCaptchaId) $> WrongCaptchaId)+ <|> try (string (errorCode BadDuplicates) $> BadDuplicates)+ <|> try (string (errorCode ReportNotRecorded) $> ReportNotRecorded)+ <|> try (string (errorCode DuplicateReport) $> DuplicateReport)+ <|> try (string (errorCode InvalidPingbackIp) $> InvalidPingbackIp)+ <|> try (string (errorCode TokenExpired) $> TokenExpired $> TokenExpired $> TokenExpired $> TokenExpired)+ <|> try (string (errorCode EmptyAction) $> EmptyAction)+ <|> string (errorCode ProxyConnectionFailed) $> ProxyConnectionFailed++-- | Read an error code as its corresponding 'TwoCaptchaErrorCode'.+readErrorCode :: String -> Either ParseError TwoCaptchaErrorCode+readErrorCode = parse errorParser ""
+ src/TwoCaptcha/Internal/Types/FunCaptcha.hs view
@@ -0,0 +1,50 @@+module TwoCaptcha.Internal.Types.FunCaptcha where++import Control.Lens (Lens', (&), (?~))+import Data.Text (Text)+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses (method), HasCommonCaptchaLenses, HasPageURL, HasProxy, defaultCaptcha, mkParamLens)++-- | Parameters used to solve FunCaptcha.+newtype FunCaptcha = MkFunCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses FunCaptcha++instance HasCaptchaLenses FunCaptcha++instance HasPageURL FunCaptcha++instance HasProxy FunCaptcha++-- |+-- Parameters used to solve FunCaptcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'publicKey'+-- * 'TwoCaptcha.Internal.Types.Captcha.pageUrl'+--+-- Optional parameters:+--+-- * 'surl'+-- * 'customDataField'+-- * 'TwoCaptcha.Internal.Types.Captcha.userAgent'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxy'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxyType'+funCaptcha :: FunCaptcha+funCaptcha = MkFunCaptcha (defaultCaptcha & method ?~ "funcaptcha")++-- | Value of __pk__ or __data-pkey__ found on the FunCaptcha page.+publicKey :: Lens' FunCaptcha (Maybe Text)+publicKey = mkParamLens "publickey"++-- | Value of __surl__ found on the FunCaptcha page.+surl :: Lens' FunCaptcha (Maybe Text)+surl = mkParamLens "surl"++-- | Custom data to pass to FunCaptcha.+customDataField :: Text -> Lens' FunCaptcha (Maybe Text)+customDataField field = mkParamLens ("data[" <> field <> "]")
+ src/TwoCaptcha/Internal/Types/GeeTestCaptcha.hs view
@@ -0,0 +1,50 @@+module TwoCaptcha.Internal.Types.GeeTestCaptcha where++import Control.Lens (Lens', (&), (?~))+import Data.Text (Text)+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses (method), HasCommonCaptchaLenses, HasPageURL, HasProxy, defaultCaptcha, mkParamLens)++-- | Parameters used to solve a GeeTest captcha.+newtype GeeTestCaptcha = MkGeeTestCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses GeeTestCaptcha++instance HasCaptchaLenses GeeTestCaptcha++instance HasPageURL GeeTestCaptcha++instance HasProxy GeeTestCaptcha++-- |+-- Parameters used to solve a GeeTest captcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'gt'+-- * 'challenge'+-- * 'TwoCaptcha.Internal.Types.Captcha.pageUrl'+--+-- Optional parameters:+--+-- * 'apiServer'+-- * 'TwoCaptcha.Internal.Types.Captcha.userAgent'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxy'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxyType'+geeTestCaptcha :: GeeTestCaptcha+geeTestCaptcha = MkGeeTestCaptcha (defaultCaptcha & method ?~ "geetest")++-- | Value of __gt__ parameter you found on target website.+gt :: Lens' GeeTestCaptcha (Maybe Text)+gt = mkParamLens "gt"++-- | Value of __challenge__ parameter you found on target website.+challenge :: Lens' GeeTestCaptcha (Maybe Text)+challenge = mkParamLens "challenge"++-- | Value of __api_server__ parameter you found on target website.+apiServer :: Lens' GeeTestCaptcha (Maybe Text)+apiServer = mkParamLens "api_server"
+ src/TwoCaptcha/Internal/Types/GridCaptcha.hs view
@@ -0,0 +1,79 @@+module TwoCaptcha.Internal.Types.GridCaptcha where++import Control.Lens (Lens')+import Data.Text (Text)+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses, HasCommonCaptchaLenses, HasLanguage, HasLocalImage, defaultCaptcha, mkParamLens, mkParamLens', mkParamLensBool)++-- | Parameters used to solve a grid captcha.+newtype GridCaptcha = MkGridCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses GridCaptcha++instance HasCaptchaLenses GridCaptcha++instance HasLocalImage GridCaptcha++instance HasLanguage GridCaptcha++-- |+-- Parameters for solving a grid captcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'TwoCaptcha.Internal.Types.Captcha.method'+-- * 'reCAPTCHAImage'+-- * 'TwoCaptcha.Internal.Types.Captcha.file'*+-- * 'TwoCaptcha.Internal.Types.Captcha.body'*+--+-- Optional parameters:+--+-- * 'canvas'+-- * 'TwoCaptcha.Internal.Types.Captcha.textInstructions'+-- * 'TwoCaptcha.Internal.Types.Captcha.imgInstructions'+-- * 'reCAPTCHAImage'+-- * 'rows'+-- * 'columns'+-- * 'previousId'+-- * 'cannotAnswer'+-- * 'TwoCaptcha.Internal.Types.Captcha.language'+-- * 'TwoCaptcha.Internal.Types.Captcha.languageCode'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+--+-- Possible 'TwoCaptcha.Internal.Types.Captcha.method' values:+--+-- * __post__ - defines that you're sending an image with multipart form+-- * __base64__ - defines that you're sending a base64 encoded image+--+-- Starred required parameter rules:+--+-- * __file__ is only required if __captcha = "post"__+-- * __body__ is only required if __captcha = "base64"__+gridCaptcha :: GridCaptcha+gridCaptcha = MkGridCaptcha defaultCaptcha++-- | Defines that you're sending a reCAPTCHA as an image.+reCAPTCHAImage :: Lens' GridCaptcha (Maybe Bool)+reCAPTCHAImage = mkParamLensBool "recaptcha"++-- | Defines that you want to use a <https://2captcha.com/2captcha-api#canvas canvas> method.+canvas :: Lens' GridCaptcha (Maybe Bool)+canvas = mkParamLensBool "canvas"++-- | Number of rows in reCAPTCHA grid.+rows :: Lens' GridCaptcha (Maybe Int)+rows = mkParamLens' "recaptcharows"++-- | Number of columns in reCAPTCHA grid.+columns :: Lens' GridCaptcha (Maybe Int)+columns = mkParamLens' "recaptchacols"++-- | Id of your previous request with the same captcha challenge.+previousId :: Lens' GridCaptcha (Maybe Text)+previousId = mkParamLens "previousID"++-- | Defines if the captcha can potentially have no images, or possibly cannot be answered.+cannotAnswer :: Lens' GridCaptcha (Maybe Bool)+cannotAnswer = mkParamLensBool "can_no_answer"
+ src/TwoCaptcha/Internal/Types/HCaptcha.hs view
@@ -0,0 +1,55 @@+module TwoCaptcha.Internal.Types.HCaptcha where++import Control.Lens (Lens', (&), (?~))+import Data.Text (Text)+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses (method), HasCommonCaptchaLenses, HasPageURL, HasProxy, defaultCaptcha, mkParamLens, mkParamLensBool)++-- | Parameters used to solve hCaptcha.+newtype HCaptcha = MkHCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses HCaptcha++instance HasCaptchaLenses HCaptcha++instance HasPageURL HCaptcha++instance HasProxy HCaptcha++-- |+-- Parameters used to solve hCaptcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'sitekey'+-- * 'TwoCaptcha.Internal.Types.Captcha.pageUrl'+--+-- Optional parameters:+--+-- * 'hInvisible'+-- * 'customData'+-- * 'TwoCaptcha.Internal.Types.Captcha.userAgent'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxy'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxyType'+hCaptcha :: HCaptcha+hCaptcha = MkHCaptcha (defaultCaptcha & method ?~ "hcaptcha")++-- | Value of __data-sitekey__ parameter on target website.+siteKey :: Lens' HCaptcha (Maybe Text)+siteKey = mkParamLens "sitekey"++-- | Defines if the captcha is invisible. Invisible hCaptchas are currently a rare case.+hInvisible :: Lens' HCaptcha (Maybe Bool)+hInvisible = mkParamLensBool "invisible"++-- |+-- Custom data that is used in some implementations of hCaptcha, mostly with invisible captchas.+-- In most cases, you see it as __rqdata__ inside network requests.+--+-- __IMPORTANT__: you MUST provide 'userAgent' if you submit with 'customData'.+-- The value should match the User-Agent you use when interacting with target website.+customData :: Lens' HCaptcha (Maybe Text)+customData = mkParamLens "data"
+ src/TwoCaptcha/Internal/Types/KeyCaptcha.hs view
@@ -0,0 +1,50 @@+module TwoCaptcha.Internal.Types.KeyCaptcha where++import Control.Lens (Lens', (&), (?~))+import Data.Text (Text)+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses (method), HasCommonCaptchaLenses, HasPageURL, defaultCaptcha, mkParamLens)++-- | Parameters used to solve KeyCaptcha.+newtype KeyCaptcha = MkKeyCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses KeyCaptcha++instance HasCaptchaLenses KeyCaptcha++instance HasPageURL KeyCaptcha++-- |+-- Parameters used to solve a KeyCaptcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'userId'+-- * 'sessionId'+-- * 'webServerSign'+-- * 'webServerSign2'+-- * 'TwoCaptchal.Internal.Types.Captcha.pageUrl'+--+-- Optional parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+keyCaptcha :: KeyCaptcha+keyCaptcha = MkKeyCaptcha (defaultCaptcha & method ?~ "keycaptcha")++-- | Value of __s_s_c_user_id__ parameter you found on page.+userId :: Lens' KeyCaptcha (Maybe Text)+userId = mkParamLens "s_s_c_user_id"++-- | Value of __s_s_c_session_id__ parameter you found on page.+sessionId :: Lens' KeyCaptcha (Maybe Text)+sessionId = mkParamLens "s_s_c_session_id"++-- | Value of __s_s_c_web_server_sign__ parameter you found on page.+webServerSign :: Lens' KeyCaptcha (Maybe Text)+webServerSign = mkParamLens "s_s_c_web_server_sign"++-- | Value of __s_s_c_web_server_sign2__ parameter you found on page.+webServerSign2 :: Lens' KeyCaptcha (Maybe Text)+webServerSign2 = mkParamLens "s_s_c_web_server_sign2"
+ src/TwoCaptcha/Internal/Types/NormalCaptcha.hs view
@@ -0,0 +1,88 @@+module TwoCaptcha.Internal.Types.NormalCaptcha where++import Control.Lens (Lens')+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses, HasCommonCaptchaLenses, HasLanguage, HasLocalImage, defaultCaptcha, mkParamLens', mkParamLensBool)++-- | Parameters used to solve a normal captcha.+newtype NormalCaptcha = MkNormalCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses NormalCaptcha++instance HasCaptchaLenses NormalCaptcha++instance HasLocalImage NormalCaptcha++instance HasLanguage NormalCaptcha++-- |+-- Parameters for solving a normal captcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'TwoCaptcha.Internal.Types.Captcha.method'+-- * 'TwoCaptcha.Internal.Types.Captcha.file'*+-- * 'TwoCaptcha.Internal.Types.Captcha.body'*+--+-- Optional parameters:+--+-- * 'phrase'+-- * 'caseSensitive'+-- * 'format'+-- * 'calc'+-- * 'minLength'+-- * 'maxLength'+-- * 'TwoCaptcha.Internal.Types.Captcha.language'+-- * 'TwoCaptcha.Internal.Types.Captcha.languageCode'+-- * 'TwoCaptcha.Internal.Types.Captcha.textInstructions'+-- * 'TwoCaptcha.Internal.Types.Captcha.imgInstructions'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+--+-- Possible 'TwoCaptcha.Internal.Types.Captcha.method' values:+--+-- * __post__ - defines that you're sending an image with multipart form+-- * __base64__ - defines that you're sending a base64 encoded image+--+-- Starred required parameter rules:+--+-- * __file__ is only required if __captcha = "post"__+-- * __body__ is only required if __captcha = "base64"__+normalCaptcha :: NormalCaptcha+normalCaptcha = MkNormalCaptcha defaultCaptcha++-- |+-- Defines if the captcha is a phrase.+--+-- * True - Captcha contains two or more words.+-- * False - Captcha contains one word.+phrase :: Lens' NormalCaptcha (Maybe Bool)+phrase = mkParamLensBool "phrase"++-- | Defines if the captcha is case sensitive.+caseSensitive :: Lens' NormalCaptcha (Maybe Bool)+caseSensitive = mkParamLensBool "regsense"++-- |+-- The captcha's format:+--+-- 0. Not specified.+-- 1. Captcha contains only numbers.+-- 2. Captcha contains only letters.+-- 3. Captcha contains only numbers OR only letters.+-- 4. Captcha contains both numbers AND letters.+format :: Lens' NormalCaptcha (Maybe Int)+format = mkParamLens' "numeric"++-- | Define if the captcha requires calculation (e.g. 1 + 1 = ?).+calc :: Lens' NormalCaptcha (Maybe Bool)+calc = mkParamLensBool "calc"++-- | The minimum number of symbols in the captcha (up to 20).+minLength :: Lens' NormalCaptcha (Maybe Int)+minLength = mkParamLens' "min_len"++-- | The maximum numbers of symbols in the captcha (up to 20).+maxLength :: Lens' NormalCaptcha (Maybe Int)+maxLength = mkParamLens' "max_len"
+ src/TwoCaptcha/Internal/Types/ReCaptcha.hs view
@@ -0,0 +1,119 @@+module TwoCaptcha.Internal.Types.ReCaptcha where++import Control.Lens (Lens', (%~), (&), (.~), (?~))+import Data.Text (Text)+import GHC.Base (Coercible)+import Network.Wreq.Lens (param)+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses (method), HasCommonCaptchaLenses, HasCookies, HasPageURL, HasProxy, HasUserAgent, TimeoutDuration, defaultCaptcha, mkParamLens, mkParamLens', mkParamLensBool, options)++-- | Default parameters for solving a recaptcha. Internal use only.+defaultReCAPTCHA :: Captcha+defaultReCAPTCHA = defaultCaptcha & method ?~ "userrecaptcha"++-- | Lenses for constructing ReCaptcha options.+class Coercible Captcha a => HasReCaptchaLenses a where+ -- | Defines if your ReCaptcha is enterprise.+ enterprise :: Lens' a (Maybe Bool)+ enterprise = mkParamLensBool "enterprise"++ -- |+ -- If using 'ReCaptchaV2', this is the value of __k__ or __data-sitekey__ found on the captcha page.+ --+ -- If using 'ReCaptchaV3', this is the value of __sitekey__ found on the captcha page.+ googleKey :: Lens' a (Maybe Text)+ googleKey = mkParamLens "googlekey"++ -- | Domain used to load the captcha: __google.com__ or __recaptcha.net__.+ domain :: Lens' a (Maybe Text)+ domain = mkParamLens "domain"++-- | Parameters used to solve reCAPTCHA V2.+newtype ReCaptchaV2 = MkReCaptchaV2 Captcha deriving (Show)++instance HasCommonCaptchaLenses ReCaptchaV2++instance HasCaptchaLenses ReCaptchaV2++instance HasReCaptchaLenses ReCaptchaV2++instance HasPageURL ReCaptchaV2++instance HasProxy ReCaptchaV2++instance HasUserAgent ReCaptchaV2++instance HasCookies ReCaptchaV2++-- |+-- Parameters used to solve reCAPTCHA V2.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'googleKey'+-- * 'TwoCaptcha.Internal.Types.Captcha.pageUrl'+--+-- Optional parameters:+--+-- * 'enterprise'+-- * 'domain'+-- * 'invisible'+-- * 'dataS'+-- * 'TwoCaptcha.Internal.Types.Captcha.cookies'+-- * 'TwoCaptcha.Internal.Types.Captcha.userAgent'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxy'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxyType'+reCAPTCHAV2 :: ReCaptchaV2+reCAPTCHAV2 = MkReCaptchaV2 defaultReCAPTCHA++-- | Defines if the reCAPTCHA v2 is invisible.+invisible :: Lens' ReCaptchaV2 (Maybe Bool)+invisible = mkParamLensBool "invisible"++-- | Value of the __data-s__ parameter found on the reCAPTCHA page. Currently applicable for google services.+dataS :: Lens' ReCaptchaV2 (Maybe Text)+dataS = mkParamLens "data-s"++-- | Parameters used to solve reCAPTCHA V3.+newtype ReCaptchaV3 = MkReCaptchaV3 Captcha deriving (Show)++instance HasCommonCaptchaLenses ReCaptchaV3++instance HasCaptchaLenses ReCaptchaV3++instance HasReCaptchaLenses ReCaptchaV3++instance HasPageURL ReCaptchaV3++-- |+-- Parameters used to solve reCAPTCHA V3.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'googleKey'+-- * 'TwoCaptcha.Internal.Types.Captcha.pageUrl'+--+-- Optional parameters:+--+-- * 'enterprise'+-- * 'domain'+-- * 'minScore'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxy'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxyType'+reCAPTCHAV3 :: ReCaptchaV3+reCAPTCHAV3 = MkReCaptchaV3 (defaultReCAPTCHA & options %~ (& param "version" .~ ["v3"]))++-- | The score needed for resolution. Currently it's almost impossible to get a token with a score higher than 0.3+minScore :: Lens' ReCaptchaV3 (Maybe Double)+minScore = mkParamLens' "min_score"++-- | Default reCAPTCHA timeout duration (600 seconds).+reCAPTCHATimeout :: TimeoutDuration+reCAPTCHATimeout = 600000
+ src/TwoCaptcha/Internal/Types/RotateCaptcha.hs view
@@ -0,0 +1,40 @@+module TwoCaptcha.Internal.Types.RotateCaptcha where++import Control.Lens (Lens', (&), (?~))+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses (method), HasCommonCaptchaLenses, HasLocalImage, defaultCaptcha, mkParamLens')++-- | Parameters used to solve a rotate captcha.+newtype RotateCaptcha = MkRotateCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses RotateCaptcha++instance HasCaptchaLenses RotateCaptcha++instance HasLocalImage RotateCaptcha++-- |+-- Parameters used to solve a rotate captcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'TwoCaptcha.Internal.Types.Captcha.file'*+-- * 'TwoCaptcha.Internal.Types.Captcha.body'*+--+-- Optional parameters:+--+-- * 'angle'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+--+-- Starred required parameter rules:+--+-- * __file__ is only required if your captcha is sent as a file.+-- * __body__ is only required if your captcha is sent in base64 format.+rotateCaptcha :: RotateCaptcha+rotateCaptcha = MkRotateCaptcha (defaultCaptcha & method ?~ "rotatecaptcha")++-- | Angle for one rotation step in degrees. Defaults to 40 degrees if not specified.+angle :: Lens' RotateCaptcha (Maybe Int)+angle = mkParamLens' "angle"
+ src/TwoCaptcha/Internal/Types/TextCaptcha.hs view
@@ -0,0 +1,36 @@+module TwoCaptcha.Internal.Types.TextCaptcha where++import Control.Lens (Lens')+import Data.Text (Text)+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses, HasCommonCaptchaLenses, HasLanguage, defaultCaptcha, mkParamLens)++-- | Parameters used to solve a text captcha.+newtype TextCaptcha = MkTextCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses TextCaptcha++instance HasCaptchaLenses TextCaptcha++instance HasLanguage TextCaptcha++-- |+-- Parameters for solving a text captcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'textContent'+--+-- Optional parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.language'+-- * 'TwoCaptcha.Internal.Types.Captcha.languageCode'+-- * 'TwoCaptcha.Internal.Types.Captcha.headerACAO'+-- * 'TwoCaptcha.Internal.Types.Captcha.pingback'+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+textCaptcha :: TextCaptcha+textCaptcha = MkTextCaptcha defaultCaptcha++-- | The text captcha's content.+textContent :: Lens' TextCaptcha (Maybe Text)+textContent = mkParamLens "textcaptcha"
+ src/TwoCaptcha/Internal/Types/TikTokCaptcha.hs view
@@ -0,0 +1,45 @@+module TwoCaptcha.Internal.Types.TikTokCaptcha where++import Control.Lens (Lens', (&), (?~))+import Data.Text (Text)+import TwoCaptcha.Internal.Types.Captcha (Captcha, HasCaptchaLenses (method), HasCommonCaptchaLenses, HasCookies, HasPageURL, HasProxy, defaultCaptcha, mkParamLens, mkParamLens')++-- | Parameters used to solve a TikTok captcha.+newtype TikTokCaptcha = MkTikTokCaptcha Captcha deriving (Show)++instance HasCommonCaptchaLenses TikTokCaptcha++instance HasCaptchaLenses TikTokCaptcha++instance HasPageURL TikTokCaptcha++instance HasProxy TikTokCaptcha++instance HasCookies TikTokCaptcha++-- |+-- Parameters used to solve a TikTok captcha.+--+-- Required parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.apiKey'+-- * 'TwoCaptcha.Internal.Types.Captcha.cookies'+-- * 'aid'+-- * 'host'+-- * 'TwoCaptcha.Internal.Types.Captcha.pageUrl'+--+-- Optional parameters:+--+-- * 'TwoCaptcha.Internal.Types.Captcha.softId'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxy'+-- * 'TwoCaptcha.Internal.Types.Captcha.proxyType'+tikTokCaptcha :: TikTokCaptcha+tikTokCaptcha = MkTikTokCaptcha (defaultCaptcha & method ?~ "tiktok")++-- | The __aid__ parameter value found on the page.+aid :: Lens' TikTokCaptcha (Maybe Int)+aid = mkParamLens' "aid"++-- | The __host__ parameter value found on the page.+host :: Lens' TikTokCaptcha (Maybe Text)+host = mkParamLens "host"