{-# LANGUAGE OverloadedStrings #-} module Network.Utilities where import Control.Lens import Data.Aeson import Data.Aeson.Lens import qualified Data.ByteString.Lazy.Char8 as BS import qualified Data.HashMap.Lazy as Hash import qualified Data.Map.Lazy as Map import Data.Maybe import Data.Scientific import qualified Data.Text as T import qualified Data.Vector as V import Data.Word import Network.Wreq type Resp = Response BS.ByteString type Obj = Map.Map String Value type HObj = Hash.HashMap T.Text Value type JSON = Response Obj type Errors = (Int, String) -- | Enum type for verifying FilePaths before sending to the API. data VerificationStatus = Good | Bad | Unknown deriving (Show) -- Process the results of a request into JSON -- Returns an IO Tuple of the status and response body. processRequest :: IO Resp -> IO (Status, Obj) processRequest response = do r <- asJSON =<< response :: IO JSON return (r ^. responseStatus, r ^. responseBody) -- Parses status code errors for api endpoints apiErr :: Int -> Obj -> String apiErr code body | code == 401 = getString "status_msg" body | code == 400 = ret $ Map.lookup "status_msg" body where ret val | isNothing val = getString "status_msg" body | otherwise = value2String $ fromJust val -- Gets a value that we know exists from a map definite :: String -> Obj -> Value definite k m = fromJust $ Map.lookup k m -- Gets a value that we know exists from a hash map definite' :: String -> HObj -> Value definite' k m = fromJust $ Hash.lookup (T.pack k) m -- Convert an Aeson value into a String value2String :: Value -> String value2String (String xs) = T.unpack xs value2String _ = "" -- Convert an Aeson value into an Integer value2Int :: Value -> Integer value2Int (Number x) = coefficient x value2Int _ = 0 -- Convert an Aeson value into a Double value2Double :: Value -> Double value2Double (Number x) = toRealFloat x :: Double value2Double _ = 0 -- Convert an Aeson value into a hash map value2Map :: Value -> HObj value2Map (Object o) = o value2Map _ = Hash.empty -- Convert an Aeson value into a Vector value2Vector :: Value -> V.Vector Value value2Vector (Array a) = a value2Vector _ = V.empty vecOfObjects :: V.Vector Value -> V.Vector HObj vecOfObjects = V.map value2Map -- Composes the definite and value2* functions into -- a single function that gets and converts from a map. -- Data.Map getInt key = value2Int . definite key getString key = value2String . definite key getMap key = value2Map . definite key getVec key = value2Vector . definite key -- Data.HashMap getInt' key = value2Int . definite' key getString' key = value2String . definite' key getMap' key = value2Map . definite' key getVec' key = value2Vector . definite' key -- custom postWith that overrides default checkStatus functionality. -- no longer returns an error on non-2** status codes. postWith' :: (String -> [FormParam] -> IO (Response BS.ByteString) ) postWith' = postWith defaults' defaults' = set checkStatus (Just $ \_ _ _ -> Nothing) defaults -- List of extensions for videos. If a file has one of these extensions -- we use the video Info from the API to verify the file. videoExtensions = [".mov", ".webm", ".ogv", ".ogg", ".wmv", ".mp4", ".m4p", ".qt", ".mpg", ".mp2", ".mpeg", ".mpe"] -- List of extensions for images. If a file has one of these extensions -- we use the image Info from the API to verify the file. imageExtensions = [".png", ".jpeg", ".jpg", ".gif", ".bmp"] -- Checks that a given file size is within the bounds specified by -- the (min, max) tuple. fileCheck :: Integer -> Word64 -> VerificationStatus fileCheck maxSize size = if conv <= maxSize then Good else Bad where conv = fromIntegral size :: Integer