packages feed

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 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"