{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}

module GoPro.Plus.Internal.HTTP where

import           Control.Lens
import           Control.Monad.IO.Class (MonadIO (..))
import           Data.Aeson             (FromJSON (..), Options (..), defaultOptions, fieldLabelModifier)
import qualified Data.ByteString.Char8  as BC
import qualified Data.ByteString.Lazy   as BL
import           Data.Text              (Text)
import qualified Data.Text.Encoding     as TE
import           Network.Wreq           (Options, asJSON, defaults, getWith, header, postWith, responseBody)
import           Network.Wreq.Types     (Postable)

userAgent :: BC.ByteString
userAgent :: ByteString
userAgent = ByteString
"github.com/dustin/gopro-plus 0.6.0.3"

defOpts :: Network.Wreq.Options
defOpts :: Options
defOpts = Options
defaults Options -> (Options -> Options) -> Options
forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"User-Agent" (([ByteString] -> Identity [ByteString])
 -> Options -> Identity Options)
-> [ByteString] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
userAgent]
          Options -> (Options -> Options) -> Options
forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"Referer" (([ByteString] -> Identity [ByteString])
 -> Options -> Identity Options)
-> [ByteString] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
"https://plus.gopro.com/"]
          Options -> (Options -> Options) -> Options
forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"Origin" (([ByteString] -> Identity [ByteString])
 -> Options -> Identity Options)
-> [ByteString] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
"https://plus.gopro.com"]
          Options -> (Options -> Options) -> Options
forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"Accept-Language" (([ByteString] -> Identity [ByteString])
 -> Options -> Identity Options)
-> [ByteString] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
"en-US,en;q=0.9"]

authOpts :: Text -> Network.Wreq.Options
authOpts :: Text -> Options
authOpts Text
tok = Options
defOpts Options -> (Options -> Options) -> Options
forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"Authorization" (([ByteString] -> Identity [ByteString])
 -> Options -> Identity Options)
-> [ByteString] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
"Bearer " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Text -> ByteString
TE.encodeUtf8 Text
tok]
               Options -> (Options -> Options) -> Options
forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"Accept" (([ByteString] -> Identity [ByteString])
 -> Options -> Identity Options)
-> [ByteString] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
"application/vnd.gopro.jk.media+json; version=2.0.0"]
               Options -> (Options -> Options) -> Options
forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"Content-Type" (([ByteString] -> Identity [ByteString])
 -> Options -> Identity Options)
-> [ByteString] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
"application/json"]

jsonOpts :: Data.Aeson.Options
jsonOpts :: Options
jsonOpts = Options
defaultOptions {
  fieldLabelModifier :: String -> String
fieldLabelModifier = (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_')
  }

-- | Proxy a request to GoPro with authentication.
proxy :: MonadIO m => Text -> String -> m BL.ByteString
proxy :: Text -> String -> m ByteString
proxy Text
tok String
u = do
  Response ByteString
r <- IO (Response ByteString) -> m (Response ByteString)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Response ByteString) -> m (Response ByteString))
-> IO (Response ByteString) -> m (Response ByteString)
forall a b. (a -> b) -> a -> b
$ Options -> String -> IO (Response ByteString)
getWith (Text -> Options
authOpts Text
tok) String
u
  ByteString -> m ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> m ByteString) -> ByteString -> m ByteString
forall a b. (a -> b) -> a -> b
$ Response ByteString
r Response ByteString
-> Getting ByteString (Response ByteString) ByteString
-> ByteString
forall s a. s -> Getting a s a -> a
^. Getting ByteString (Response ByteString) ByteString
forall body0 body1.
Lens (Response body0) (Response body1) body0 body1
responseBody

jget :: (MonadIO m, FromJSON a) => Text -> String -> m a
jget :: Text -> String -> m a
jget Text
tok = Options -> String -> m a
forall (m :: * -> *) a.
(MonadIO m, FromJSON a) =>
Options -> String -> m a
jgetWith (Text -> Options
authOpts Text
tok)

jgetWith :: (MonadIO m, FromJSON a) => Network.Wreq.Options -> String -> m a
jgetWith :: Options -> String -> m a
jgetWith Options
opts String
u = Getting a (Response a) a -> Response a -> a
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting a (Response a) a
forall body0 body1.
Lens (Response body0) (Response body1) body0 body1
responseBody (Response a -> a) -> m (Response a) -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Response a) -> m (Response a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Options -> String -> IO (Response ByteString)
getWith Options
opts String
u IO (Response ByteString)
-> (Response ByteString -> IO (Response a)) -> IO (Response a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Response ByteString -> IO (Response a)
forall (m :: * -> *) a.
(MonadThrow m, FromJSON a) =>
Response ByteString -> m (Response a)
asJSON)

jpostWith :: (MonadIO m, Postable a, FromJSON r) => Network.Wreq.Options -> String -> a -> m r
jpostWith :: Options -> String -> a -> m r
jpostWith Options
opts String
u a
v = Getting r (Response r) r -> Response r -> r
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting r (Response r) r
forall body0 body1.
Lens (Response body0) (Response body1) body0 body1
responseBody (Response r -> r) -> m (Response r) -> m r
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Response r) -> m (Response r)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Options -> String -> a -> IO (Response ByteString)
forall a.
Postable a =>
Options -> String -> a -> IO (Response ByteString)
postWith Options
opts String
u a
v IO (Response ByteString)
-> (Response ByteString -> IO (Response r)) -> IO (Response r)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Response ByteString -> IO (Response r)
forall (m :: * -> *) a.
(MonadThrow m, FromJSON a) =>
Response ByteString -> m (Response a)
asJSON)