antigate 0.5 → 0.6
raw patch · 3 files changed
+100/−34 lines, 3 filesdep +deepseqPVP ok
version bump matches the API change (PVP)
Dependencies added: deepseq
API changes (from Hackage documentation)
+ Text.Recognition.Antigate: instance NFData ApiKey
+ Text.Recognition.Antigate: instance NFData CaptchaConf
+ Text.Recognition.Antigate: instance NFData Phase
+ Text.Recognition.Antigate: instance NFData SolveConf
+ Text.Recognition.Antigate: instance NFData SolveException
+ Text.Recognition.Antigate: instance NFData a => NFData (ApiResult a)
Files
- LICENSE +1/−1
- Text/Recognition/Antigate.hs +92/−29
- antigate.cabal +7/−4
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2012 kudah+Copyright © 2012 kudah Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
Text/Recognition/Antigate.hs view
@@ -85,7 +85,7 @@ import Data.ByteString.Lazy.Char8() import Network.HTTP.Conduit hiding (httpLbs)-import qualified Network.HTTP.Conduit+import qualified Network.HTTP.Conduit as HC import Network.HTTP.Conduit.MultipartFormData import Control.Concurrent (threadDelay)@@ -103,23 +103,29 @@ import Safe (readMay) import Text.Printf (printf) +import Control.DeepSeq (NFData(..), deepseq)++__RESPONSE_TIMEOUT :: Int+__RESPONSE_TIMEOUT = 15000000+ decodeUtf8 :: BL.ByteString -> TL.Text decodeUtf8 = TLE.decodeUtf8With TEE.lenientDecode httpLbs :: Request (ResourceT IO) -> Manager -> ResourceT IO (Response BL.ByteString)-httpLbs r m = Network.HTTP.Conduit.httpLbs r{responseTimeout=Nothing} m+httpLbs r =+ HC.httpLbs r{responseTimeout=Just __RESPONSE_TIMEOUT} httpGet :: MonadResource m => Manager -> String -> m BL.ByteString httpGet m u = liftResourceT $ do rq <- parseUrl u responseBody <$> httpLbs rq m -delimit :: Char -> String -> [String]-delimit _ [] = []-delimit a b =+charDelimit :: Char -> String -> [String]+charDelimit _ [] = []+charDelimit a b = case break (==a) b of (c, []) -> [c]- (c, (_:d)) -> c : delimit a d+ (c, (_:d)) -> c : charDelimit a d -- | Antigate API access key paired with service provider's host. -- At least these services claim to support Antigate API:@@ -142,6 +148,9 @@ {api_host = "antigate.com" ,api_key = str} +instance NFData ApiKey where+ rnf (ApiKey h k) = h `deepseq` k `deepseq` ()+ type CaptchaID = Int -- | Properties of the captcha to be solved. See <http://antigate.com/panel.php?action=api>@@ -201,6 +210,17 @@ ,max_bid = Nothing } +instance NFData CaptchaConf where+ rnf (CaptchaConf a b c d e f g h) =+ a `deepseq` b `deepseq`+ c `deepseq` d `deepseq`+ e `deepseq` f `deepseq`+ g `deepseq` h `deepseq` ()++instance NFData a => NFData (ApiResult a) where+ rnf (OK a) = a `deepseq` ()+ rnf x = x `seq` ()+ hostExt :: String -> String hostExt host | "pixodrom.com" `isInfixOf` host = "aspx"@@ -253,24 +273,38 @@ uploadReq :: MonadResource m => Manager -> ApiKey -> CaptchaConf -> Part m (ResourceT IO) -> m (ApiResult CaptchaID) uploadReq m ApiKey{..} conf part = do- url <- liftIO $ parseUrl $ "http://" ++ api_host ++ "/in." ++ hostExt api_host- req <- (`formDataBody` url) $- ([partBS "method" "post"- ,partBS "key" (fromString api_key)- ]) ++- (captchaConfFields conf- ) ++- [part]- liftResourceT $ parseUploadResponse . TL.unpack . decodeUtf8 . responseBody <$> httpLbs req m+ url <- liftIO $+ parseUrl $ "http://" ++ api_host ++ "/in." ++ hostExt api_host+ req <- flip formDataBody url $+ [partBS "method" "post"+ ,partBS "key" $ fromString api_key]+ ++ captchaConfFields conf+ ++ [part]+ liftResourceT $ do+ res <- httpLbs req m+ return $ parseUploadResponse $ TL.unpack $ decodeUtf8 $ responseBody res -- | upload captcha for recognition -- -- throws 'HttpException' on network errors.-uploadCaptcha :: MonadResource m => ApiKey -> CaptchaConf -> FilePath -> BL.ByteString -> Manager -> m (ApiResult CaptchaID)+uploadCaptcha+ :: MonadResource m+ => ApiKey+ -> CaptchaConf+ -> FilePath+ -> BL.ByteString+ -> Manager+ -> m (ApiResult CaptchaID) uploadCaptcha key sets filename image m = do uploadReq m key sets $ partFileRequestBody "file" filename $ RequestBodyLBS image -uploadCaptchaFromFile :: MonadResource m => ApiKey -> CaptchaConf -> FilePath -> Manager -> m (ApiResult CaptchaID)+uploadCaptchaFromFile+ :: MonadResource m+ => ApiKey+ -> CaptchaConf+ -> FilePath+ -> Manager+ -> m (ApiResult CaptchaID) uploadCaptchaFromFile key sets filename m = do uploadReq m key sets $ partFile "file" filename @@ -305,12 +339,17 @@ -- | Parse antigate's multi-check response parseMultiCheckResponses :: String -> [ApiResult String]-parseMultiCheckResponses = map parseMultiCheckResponse . delimit '|'+parseMultiCheckResponses = map parseMultiCheckResponse . charDelimit '|' -- | retrieve captcha status -- -- throws 'HttpException' on network errors.-checkCaptcha :: MonadResource m => ApiKey -> CaptchaID -> Manager -> m (ApiResult String)+checkCaptcha+ :: MonadResource m+ => ApiKey+ -> CaptchaID+ -> Manager+ -> m (ApiResult String) checkCaptcha ApiKey{..} captchaid m = fmap (parseCheckResponse . TL.unpack . decodeUtf8) $ httpGet m $ "http://" ++ api_host ++ "/res." ++ hostExt api_host ++ "?key=" ++@@ -319,7 +358,12 @@ -- | retrieve multiple captcha status -- -- throws 'HttpException' on network errors.-checkCaptchas :: MonadResource m => ApiKey -> [CaptchaID] -> Manager -> m [ApiResult String]+checkCaptchas+ :: MonadResource m+ => ApiKey+ -> [CaptchaID]+ -> Manager+ -> m [ApiResult String] checkCaptchas ApiKey{..} captchaids m = fmap (parseMultiCheckResponses . TL.unpack . decodeUtf8) $ httpGet m $ "http://" ++ api_host ++ "/res." ++ hostExt api_host ++ "?key=" ++@@ -332,9 +376,15 @@ instance Exception SolveException +instance NFData SolveException where+ rnf (SolveExceptionUpload a) = a `deepseq` ()+ rnf (SolveExceptionCheck a b) = a `deepseq` b `deepseq` ()+ data Phase = UploadPhase | CheckPhase deriving (Show, Read, Eq, Ord, Enum, Bounded) +instance NFData Phase+ data SolveConf = SolveConf { -- | how much to sleep while waiting for available slot; in microseconds.@@ -374,17 +424,23 @@ shows api_check_sleep . showString ", api_counter = <Phase -> Int -> IO ()>, api_upload_callback = <CaptchaID -> IO ()>}" +instance NFData SolveConf where+ rnf (SolveConf a b c d) =+ a `deepseq` b `deepseq`+ c `deepseq` d `deepseq` ()+ -- | High level function to solve captcha, blocks until answer is provided (about 2-10 seconds). -- -- throws 'SolveException' or 'HttpException' when something goes wrong.-solveCaptcha :: MonadResource m- => SolveConf- -> ApiKey- -> CaptchaConf- -> FilePath -- ^ image filename (antigate guesses filetype by file extension)- -> BL.ByteString -- ^ image contents- -> Manager -- ^ HTTP connection manager to use- -> m (CaptchaID, String)+solveCaptcha+ :: MonadResource m+ => SolveConf+ -> ApiKey+ -> CaptchaConf+ -> FilePath -- ^ image filename (antigate guesses filetype by file extension)+ -> BL.ByteString -- ^ image contents+ -> Manager -- ^ HTTP connection manager to use+ -> m (CaptchaID, String) solveCaptcha SolveConf{..} key conf filename image m = do liftIO $ api_counter UploadPhase 0 captchaid <- goupload 1 api_upload_sleep@@ -414,7 +470,14 @@ return (captchaid, answer) ex -> liftIO $ throwIO $ SolveExceptionCheck captchaid $ () <$ ex -solveCaptchaFromFile :: (MonadBaseControl IO m, MonadResource m) => SolveConf -> ApiKey -> CaptchaConf -> FilePath -> Manager -> m (CaptchaID, String)+solveCaptchaFromFile+ :: (MonadBaseControl IO m, MonadResource m)+ => SolveConf+ -> ApiKey+ -> CaptchaConf+ -> FilePath+ -> Manager+ -> m (CaptchaID, String) solveCaptchaFromFile a b c d m = do s <- liftIO (fromStrict' <$> BS.readFile d) solveCaptcha a b c d s m
antigate.cabal view
@@ -1,7 +1,9 @@ name: antigate-version: 0.5-synopsis: Haskell interface for antigate.com captcha recognition service and services supporting its API-description: Haskell interface for antigate.com captcha recognition service and other services (e.g. captchabot, decaptcher)+version: 0.6+synopsis: Interface for antigate.com captcha recognition API+description:+ Haskell interface for antigate.com captcha recognition service+ and other services supporting its API (e.g. captchabot, decaptcher) category: Network APIs, CAPTCHA, Text Recognition license: MIT license-file: LICENSE@@ -10,7 +12,7 @@ cabal-version: >= 1.8 stability: experimental build-type: Simple-tested-with: GHC == 7.4.1+tested-with: GHC == 7.4.1, GHC == 7.6.2 homepage: https://github.com/exbb2/antigate source-repository head@@ -26,6 +28,7 @@ ,safe ,resourcet ,transformers+ ,deepseq exposed-modules: Text.Recognition.Antigate