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