-- | User endpoints
module Calamity.HTTP.User
    ( UserRequest(..)
    , ModifyUserData(..)
    , GetCurrentUserGuildsOptions(..) ) where

import           Calamity.HTTP.Internal.Request
import           Calamity.HTTP.Internal.Route
import           Calamity.Internal.AesonThings
import           Calamity.Types.Model.Channel
import           Calamity.Types.Model.Guild
import           Calamity.Types.Model.User
import           Calamity.Types.Snowflake

import           Control.Arrow
import           Control.Lens                   hiding ( (.=) )

import           Data.Aeson
import           Data.Default.Class
import           Data.Maybe
import           Data.Text                      ( Text )

import           GHC.Generics

import           Network.Wreq.Lens
import           Network.Wreq.Session

import           TextShow

data ModifyUserData = ModifyUserData
  { ModifyUserData -> Maybe Text
username :: Maybe Text
    -- | The avatar field should be in discord's image data format: https://discord.com/developers/docs/reference#image-data
  , ModifyUserData -> Maybe Text
avatar   :: Maybe Text
  }
  deriving ( Int -> ModifyUserData -> ShowS
[ModifyUserData] -> ShowS
ModifyUserData -> String
(Int -> ModifyUserData -> ShowS)
-> (ModifyUserData -> String)
-> ([ModifyUserData] -> ShowS)
-> Show ModifyUserData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ModifyUserData] -> ShowS
$cshowList :: [ModifyUserData] -> ShowS
show :: ModifyUserData -> String
$cshow :: ModifyUserData -> String
showsPrec :: Int -> ModifyUserData -> ShowS
$cshowsPrec :: Int -> ModifyUserData -> ShowS
Show, (forall x. ModifyUserData -> Rep ModifyUserData x)
-> (forall x. Rep ModifyUserData x -> ModifyUserData)
-> Generic ModifyUserData
forall x. Rep ModifyUserData x -> ModifyUserData
forall x. ModifyUserData -> Rep ModifyUserData x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ModifyUserData x -> ModifyUserData
$cfrom :: forall x. ModifyUserData -> Rep ModifyUserData x
Generic, ModifyUserData
ModifyUserData -> Default ModifyUserData
forall a. a -> Default a
def :: ModifyUserData
$cdef :: ModifyUserData
Default )
  deriving ( [ModifyUserData] -> Encoding
[ModifyUserData] -> Value
ModifyUserData -> Encoding
ModifyUserData -> Value
(ModifyUserData -> Value)
-> (ModifyUserData -> Encoding)
-> ([ModifyUserData] -> Value)
-> ([ModifyUserData] -> Encoding)
-> ToJSON ModifyUserData
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [ModifyUserData] -> Encoding
$ctoEncodingList :: [ModifyUserData] -> Encoding
toJSONList :: [ModifyUserData] -> Value
$ctoJSONList :: [ModifyUserData] -> Value
toEncoding :: ModifyUserData -> Encoding
$ctoEncoding :: ModifyUserData -> Encoding
toJSON :: ModifyUserData -> Value
$ctoJSON :: ModifyUserData -> Value
ToJSON ) via CalamityJSON ModifyUserData

data GetCurrentUserGuildsOptions = GetCurrentUserGuildsOptions
  { GetCurrentUserGuildsOptions -> Maybe (Snowflake Guild)
before :: Maybe (Snowflake Guild)
  , GetCurrentUserGuildsOptions -> Maybe (Snowflake Guild)
after  :: Maybe (Snowflake Guild)
  , GetCurrentUserGuildsOptions -> Maybe Integer
limit  :: Maybe Integer
  }
  deriving ( Int -> GetCurrentUserGuildsOptions -> ShowS
[GetCurrentUserGuildsOptions] -> ShowS
GetCurrentUserGuildsOptions -> String
(Int -> GetCurrentUserGuildsOptions -> ShowS)
-> (GetCurrentUserGuildsOptions -> String)
-> ([GetCurrentUserGuildsOptions] -> ShowS)
-> Show GetCurrentUserGuildsOptions
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [GetCurrentUserGuildsOptions] -> ShowS
$cshowList :: [GetCurrentUserGuildsOptions] -> ShowS
show :: GetCurrentUserGuildsOptions -> String
$cshow :: GetCurrentUserGuildsOptions -> String
showsPrec :: Int -> GetCurrentUserGuildsOptions -> ShowS
$cshowsPrec :: Int -> GetCurrentUserGuildsOptions -> ShowS
Show, (forall x.
 GetCurrentUserGuildsOptions -> Rep GetCurrentUserGuildsOptions x)
-> (forall x.
    Rep GetCurrentUserGuildsOptions x -> GetCurrentUserGuildsOptions)
-> Generic GetCurrentUserGuildsOptions
forall x.
Rep GetCurrentUserGuildsOptions x -> GetCurrentUserGuildsOptions
forall x.
GetCurrentUserGuildsOptions -> Rep GetCurrentUserGuildsOptions x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x.
Rep GetCurrentUserGuildsOptions x -> GetCurrentUserGuildsOptions
$cfrom :: forall x.
GetCurrentUserGuildsOptions -> Rep GetCurrentUserGuildsOptions x
Generic, GetCurrentUserGuildsOptions
GetCurrentUserGuildsOptions -> Default GetCurrentUserGuildsOptions
forall a. a -> Default a
def :: GetCurrentUserGuildsOptions
$cdef :: GetCurrentUserGuildsOptions
Default )

data UserRequest a where
  GetCurrentUser       ::                                UserRequest User
  GetUser              :: HasID User u => u ->           UserRequest User
  ModifyCurrentUser    :: ModifyUserData ->              UserRequest User
  GetCurrentUserGuilds :: GetCurrentUserGuildsOptions -> UserRequest [Partial Guild]
  LeaveGuild           :: HasID Guild g => g ->          UserRequest ()
  CreateDM             :: HasID User u => u ->           UserRequest DMChannel

baseRoute :: RouteBuilder _
baseRoute :: RouteBuilder '[]
baseRoute = RouteBuilder '[]
mkRouteBuilder RouteBuilder '[] -> S -> ConsRes S '[]
forall a (ids :: [(*, RouteRequirement)]).
RouteFragmentable a ids =>
RouteBuilder ids -> a -> ConsRes a ids
// Text -> S
S "users" RouteBuilder '[] -> S -> ConsRes S '[]
forall a (ids :: [(*, RouteRequirement)]).
RouteFragmentable a ids =>
RouteBuilder ids -> a -> ConsRes a ids
// Text -> S
S "@me"

instance Request (UserRequest a) where
  type Result (UserRequest a) = a

  route :: UserRequest a -> Route
route GetCurrentUser = RouteBuilder '[]
baseRoute
    RouteBuilder '[] -> (RouteBuilder '[] -> Route) -> Route
forall a b. a -> (a -> b) -> b
& RouteBuilder '[] -> Route
forall (ids :: [(*, RouteRequirement)]).
EnsureFulfilled ids =>
RouteBuilder ids -> Route
buildRoute
  route (GetUser (forall a. HasID User a => a -> Snowflake User
forall b a. HasID b a => a -> Snowflake b
getID @User -> Snowflake User
uid)) = RouteBuilder '[]
mkRouteBuilder RouteBuilder '[] -> S -> ConsRes S '[]
forall a (ids :: [(*, RouteRequirement)]).
RouteFragmentable a ids =>
RouteBuilder ids -> a -> ConsRes a ids
// Text -> S
S "users" RouteBuilder '[] -> ID User -> ConsRes (ID User) '[]
forall a (ids :: [(*, RouteRequirement)]).
RouteFragmentable a ids =>
RouteBuilder ids -> a -> ConsRes a ids
// ID User
forall k (a :: k). ID a
ID @User
    RouteBuilder '[ '(User, 'Required)]
-> (RouteBuilder '[ '(User, 'Required)]
    -> RouteBuilder '[ '(User, 'Satisfied), '(User, 'Required)])
-> RouteBuilder '[ '(User, 'Satisfied), '(User, 'Required)]
forall a b. a -> (a -> b) -> b
& Snowflake User
-> RouteBuilder '[ '(User, 'Required)]
-> RouteBuilder '[ '(User, 'Satisfied), '(User, 'Required)]
forall k (ids :: [(*, RouteRequirement)]).
Typeable k =>
Snowflake k
-> RouteBuilder ids -> RouteBuilder ('(k, 'Satisfied) : ids)
giveID Snowflake User
uid
    RouteBuilder '[ '(User, 'Satisfied), '(User, 'Required)]
-> (RouteBuilder '[ '(User, 'Satisfied), '(User, 'Required)]
    -> Route)
-> Route
forall a b. a -> (a -> b) -> b
& RouteBuilder '[ '(User, 'Satisfied), '(User, 'Required)] -> Route
forall (ids :: [(*, RouteRequirement)]).
EnsureFulfilled ids =>
RouteBuilder ids -> Route
buildRoute
  route (ModifyCurrentUser _) = RouteBuilder '[]
baseRoute
    RouteBuilder '[] -> (RouteBuilder '[] -> Route) -> Route
forall a b. a -> (a -> b) -> b
& RouteBuilder '[] -> Route
forall (ids :: [(*, RouteRequirement)]).
EnsureFulfilled ids =>
RouteBuilder ids -> Route
buildRoute
  route (GetCurrentUserGuilds _) = RouteBuilder '[]
baseRoute RouteBuilder '[] -> S -> ConsRes S '[]
forall a (ids :: [(*, RouteRequirement)]).
RouteFragmentable a ids =>
RouteBuilder ids -> a -> ConsRes a ids
// Text -> S
S "guilds"
    RouteBuilder '[] -> (RouteBuilder '[] -> Route) -> Route
forall a b. a -> (a -> b) -> b
& RouteBuilder '[] -> Route
forall (ids :: [(*, RouteRequirement)]).
EnsureFulfilled ids =>
RouteBuilder ids -> Route
buildRoute
  route (LeaveGuild (forall a. HasID Guild a => a -> Snowflake Guild
forall b a. HasID b a => a -> Snowflake b
getID @Guild -> Snowflake Guild
gid)) = RouteBuilder '[]
baseRoute RouteBuilder '[] -> S -> ConsRes S '[]
forall a (ids :: [(*, RouteRequirement)]).
RouteFragmentable a ids =>
RouteBuilder ids -> a -> ConsRes a ids
// Text -> S
S "guilds" RouteBuilder '[] -> ID Guild -> ConsRes (ID Guild) '[]
forall a (ids :: [(*, RouteRequirement)]).
RouteFragmentable a ids =>
RouteBuilder ids -> a -> ConsRes a ids
// ID Guild
forall k (a :: k). ID a
ID @Guild
    RouteBuilder '[ '(Guild, 'Required)]
-> (RouteBuilder '[ '(Guild, 'Required)]
    -> RouteBuilder '[ '(Guild, 'Satisfied), '(Guild, 'Required)])
-> RouteBuilder '[ '(Guild, 'Satisfied), '(Guild, 'Required)]
forall a b. a -> (a -> b) -> b
& Snowflake Guild
-> RouteBuilder '[ '(Guild, 'Required)]
-> RouteBuilder '[ '(Guild, 'Satisfied), '(Guild, 'Required)]
forall k (ids :: [(*, RouteRequirement)]).
Typeable k =>
Snowflake k
-> RouteBuilder ids -> RouteBuilder ('(k, 'Satisfied) : ids)
giveID Snowflake Guild
gid
    RouteBuilder '[ '(Guild, 'Satisfied), '(Guild, 'Required)]
-> (RouteBuilder '[ '(Guild, 'Satisfied), '(Guild, 'Required)]
    -> Route)
-> Route
forall a b. a -> (a -> b) -> b
& RouteBuilder '[ '(Guild, 'Satisfied), '(Guild, 'Required)] -> Route
forall (ids :: [(*, RouteRequirement)]).
EnsureFulfilled ids =>
RouteBuilder ids -> Route
buildRoute
  route (CreateDM _) = RouteBuilder '[]
baseRoute RouteBuilder '[] -> S -> ConsRes S '[]
forall a (ids :: [(*, RouteRequirement)]).
RouteFragmentable a ids =>
RouteBuilder ids -> a -> ConsRes a ids
// Text -> S
S "channels"
    RouteBuilder '[] -> (RouteBuilder '[] -> Route) -> Route
forall a b. a -> (a -> b) -> b
& RouteBuilder '[] -> Route
forall (ids :: [(*, RouteRequirement)]).
EnsureFulfilled ids =>
RouteBuilder ids -> Route
buildRoute

  action :: UserRequest a
-> Options -> Session -> String -> IO (Response ByteString)
action GetCurrentUser = Options -> Session -> String -> IO (Response ByteString)
getWith
  action (GetUser _) = Options -> Session -> String -> IO (Response ByteString)
getWith
  action (ModifyCurrentUser o :: ModifyUserData
o) = Value -> Options -> Session -> String -> IO (Response ByteString)
forall a.
Postable a =>
a -> Options -> Session -> String -> IO (Response ByteString)
patchWith' (ModifyUserData -> Value
forall a. ToJSON a => a -> Value
toJSON ModifyUserData
o)
  action (GetCurrentUserGuilds GetCurrentUserGuildsOptions { Maybe (Snowflake Guild)
before :: Maybe (Snowflake Guild)
$sel:before:GetCurrentUserGuildsOptions :: GetCurrentUserGuildsOptions -> Maybe (Snowflake Guild)
before, Maybe (Snowflake Guild)
after :: Maybe (Snowflake Guild)
$sel:after:GetCurrentUserGuildsOptions :: GetCurrentUserGuildsOptions -> Maybe (Snowflake Guild)
after, Maybe Integer
limit :: Maybe Integer
$sel:limit:GetCurrentUserGuildsOptions :: GetCurrentUserGuildsOptions -> Maybe Integer
limit }) = (Options -> Options)
-> Options -> Session -> String -> IO (Response ByteString)
getWithP
    (Text -> Lens' Options [Text]
param "before" (([Text] -> Identity [Text]) -> Options -> Identity Options)
-> [Text] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Maybe Text -> [Text]
forall a. Maybe a -> [a]
maybeToList (Snowflake Guild -> Text
forall a. TextShow a => a -> Text
showt (Snowflake Guild -> Text) -> Maybe (Snowflake Guild) -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (Snowflake Guild)
before) (Options -> Options) -> (Options -> Options) -> Options -> Options
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Text -> Lens' Options [Text]
param "after" (([Text] -> Identity [Text]) -> Options -> Identity Options)
-> [Text] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Maybe Text -> [Text]
forall a. Maybe a -> [a]
maybeToList (Snowflake Guild -> Text
forall a. TextShow a => a -> Text
showt (Snowflake Guild -> Text) -> Maybe (Snowflake Guild) -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (Snowflake Guild)
after) (Options -> Options) -> (Options -> Options) -> Options -> Options
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Text -> Lens' Options [Text]
param
     "limit" (([Text] -> Identity [Text]) -> Options -> Identity Options)
-> [Text] -> Options -> Options
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Maybe Text -> [Text]
forall a. Maybe a -> [a]
maybeToList (Integer -> Text
forall a. TextShow a => a -> Text
showt (Integer -> Text) -> Maybe Integer -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Integer
limit))
  action (LeaveGuild _) = Options -> Session -> String -> IO (Response ByteString)
deleteWith
  action (CreateDM (forall a. HasID User a => a -> Snowflake User
forall b a. HasID b a => a -> Snowflake b
getID @User -> Snowflake User
uid)) = Value -> Options -> Session -> String -> IO (Response ByteString)
forall a.
Postable a =>
a -> Options -> Session -> String -> IO (Response ByteString)
postWith' ([Pair] -> Value
object ["recipient_id" Text -> Snowflake User -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Snowflake User
uid])