{-# LANGUAGE OverloadedStrings #-} module HTTP.ThirdParty.ProxyList(getProxyList, randomProxy) where import qualified Data.Text as T import qualified Data.Text.Encoding as TE import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy.Char8 as LBS import Control.Lens import Network.Wreq import Text.Regex.Posix import Text.Regex.Base import qualified Codec.Binary.Base64.String as B64 import System.Random url :: String url = "https://proxy-list.org/english/search.php" myOptions = defaults & (param "country" .~ ["any"]) & (param "type" .~ ["any"]) & (param "port" .~ ["any"]) sslOptions :: Bool -> Options sslOptions False = myOptions & (param "search" .~ ["ssl-no"]) & (param "ssl" .~ ["no"]) sslOptions True = myOptions & (param "search" .~ ["ssl-yes"]) & (param "ssl" .~ ["yes"]) getProxyList :: Bool -> IO [(String, Int)] getProxyList ssl = do let opts = sslOptions ssl resp <- getWith opts url let body = resp ^. responseBody let bodyString = T.unpack (TE.decodeUtf8 (toStrictString body)) let base64Strings = getAllTextMatches (bodyString =~ base64Pat :: AllTextMatches [] String) let ipStrings = [decodeBase64 str | str <- base64Strings] return [transform str | str <- ipStrings] where base64Pat = "Proxy\\('([^']+)'\\)" :: String decodeBase64 :: String -> String decodeBase64 base64 = let _:str:_ = getAllTextSubmatches (base64 =~ base64Pat :: AllTextSubmatches [] String) in B64.decode str ipPortPat = "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}):([0-9]+)" :: String transform :: String -> (String, Int) transform str = let _:ip:port:_ = getAllTextSubmatches (str =~ ipPortPat :: AllTextSubmatches [] String) in (ip, (read port :: Int)) randomProxy :: [(String, Int)] -> IO (String, Int) randomProxy list = do let len = (length list) gOld <- getStdGen let (x, gNew) = next gOld setStdGen gNew let f:_ = drop (x `mod` len) list return f toStrictString = BS.concat . LBS.toChunks