{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
module Web.Slack.Experimental.Views (
SlackView (..),
HomeTabView (..),
ModalView (..),
Expected (..),
PublishReq (..),
PublishResp (..),
Api,
viewsPublish,
) where
import Data.Aeson qualified as A
import Data.Aeson.KeyMap qualified as KM
import Servant.API (AuthProtect, FormUrlEncoded, JSON, Post, ReqBody, (:>))
import Servant.Client (ClientM, client)
import Servant.Client.Core (AuthenticatedRequest)
import Web.FormUrlEncoded (ToForm (..))
import Web.HttpApiData (ToHttpApiData (..))
import Web.Slack.AesonUtils (Expected (..), snakeCaseOptions, snakeCaseOptionsEatTrailingUnderscore, (.=!), (.=?))
import Web.Slack.Experimental.Blocks qualified as B
import Web.Slack.Experimental.Blocks.Types (SlackPlainTextOnly)
import Web.Slack.Internal (ResponseJSON (..), SlackConfig (..), mkSlackAuthenticateReq, run)
import Web.Slack.Pager (Response)
import Web.Slack.Prelude
import Web.Slack.Types (UserId)
data SlackView inner = SlackView
{ forall inner. SlackView inner -> Vector SlackBlock
blocks :: Vector B.SlackBlock
, forall inner. SlackView inner -> Maybe Text
privateMetadata :: Maybe Text
, forall inner. SlackView inner -> Maybe Text
callbackId :: Maybe Text
, forall inner. SlackView inner -> Maybe Text
externalId :: Maybe Text
, forall inner. SlackView inner -> inner
inner :: inner
}
deriving stock (Int -> SlackView inner -> ShowS
[SlackView inner] -> ShowS
SlackView inner -> String
(Int -> SlackView inner -> ShowS)
-> (SlackView inner -> String)
-> ([SlackView inner] -> ShowS)
-> Show (SlackView inner)
forall inner. Show inner => Int -> SlackView inner -> ShowS
forall inner. Show inner => [SlackView inner] -> ShowS
forall inner. Show inner => SlackView inner -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall inner. Show inner => Int -> SlackView inner -> ShowS
showsPrec :: Int -> SlackView inner -> ShowS
$cshow :: forall inner. Show inner => SlackView inner -> String
show :: SlackView inner -> String
$cshowList :: forall inner. Show inner => [SlackView inner] -> ShowS
showList :: [SlackView inner] -> ShowS
Show, SlackView inner -> SlackView inner -> Bool
(SlackView inner -> SlackView inner -> Bool)
-> (SlackView inner -> SlackView inner -> Bool)
-> Eq (SlackView inner)
forall inner.
Eq inner =>
SlackView inner -> SlackView inner -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall inner.
Eq inner =>
SlackView inner -> SlackView inner -> Bool
== :: SlackView inner -> SlackView inner -> Bool
$c/= :: forall inner.
Eq inner =>
SlackView inner -> SlackView inner -> Bool
/= :: SlackView inner -> SlackView inner -> Bool
Eq, (forall x. SlackView inner -> Rep (SlackView inner) x)
-> (forall x. Rep (SlackView inner) x -> SlackView inner)
-> Generic (SlackView inner)
forall x. Rep (SlackView inner) x -> SlackView inner
forall x. SlackView inner -> Rep (SlackView inner) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall inner x. Rep (SlackView inner) x -> SlackView inner
forall inner x. SlackView inner -> Rep (SlackView inner) x
$cfrom :: forall inner x. SlackView inner -> Rep (SlackView inner) x
from :: forall x. SlackView inner -> Rep (SlackView inner) x
$cto :: forall inner x. Rep (SlackView inner) x -> SlackView inner
to :: forall x. Rep (SlackView inner) x -> SlackView inner
Generic)
type role SlackView representational
instance (FromJSON inner) => FromJSON (SlackView inner) where
parseJSON :: Value -> Parser (SlackView inner)
parseJSON = String
-> (Object -> Parser (SlackView inner))
-> Value
-> Parser (SlackView inner)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlackView" \Object
o -> do
Vector SlackBlock
blocks <- Object
o Object -> Key -> Parser (Vector SlackBlock)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"blocks"
Maybe Text
privateMetadata <- Object
o Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"private_metadata"
Maybe Text
callbackId <- Object
o Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"callback_id"
Maybe Text
externalId <- Object
o Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"external_id"
inner
inner <- forall a. FromJSON a => Value -> Parser a
parseJSON @inner (Object -> Value
A.Object Object
o)
SlackView inner -> Parser (SlackView inner)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SlackView {inner
Maybe Text
Vector SlackBlock
$sel:blocks:SlackView :: Vector SlackBlock
$sel:privateMetadata:SlackView :: Maybe Text
$sel:callbackId:SlackView :: Maybe Text
$sel:externalId:SlackView :: Maybe Text
$sel:inner:SlackView :: inner
blocks :: Vector SlackBlock
privateMetadata :: Maybe Text
callbackId :: Maybe Text
externalId :: Maybe Text
inner :: inner
..}
instance (ToJSON inner) => ToJSON (SlackView inner) where
toJSON :: SlackView inner -> Value
toJSON SlackView {inner
Maybe Text
Vector SlackBlock
$sel:blocks:SlackView :: forall inner. SlackView inner -> Vector SlackBlock
$sel:privateMetadata:SlackView :: forall inner. SlackView inner -> Maybe Text
$sel:callbackId:SlackView :: forall inner. SlackView inner -> Maybe Text
$sel:externalId:SlackView :: forall inner. SlackView inner -> Maybe Text
$sel:inner:SlackView :: forall inner. SlackView inner -> inner
blocks :: Vector SlackBlock
privateMetadata :: Maybe Text
callbackId :: Maybe Text
externalId :: Maybe Text
inner :: inner
..} = case inner -> Value
forall a. ToJSON a => a -> Value
toJSON inner
inner of
A.Object Object
innerObj ->
Object -> Value
A.Object
( [(Key, Value)] -> Object
forall v. [(Key, v)] -> KeyMap v
KM.fromList
( [Maybe (Key, Value)] -> [(Key, Value)]
forall (f :: * -> *) t.
(IsSequence (f (Maybe t)), Functor f,
Element (f (Maybe t)) ~ Maybe t) =>
f (Maybe t) -> f t
catMaybes
[ Key
"blocks" Key -> Vector SlackBlock -> Maybe (Key, Value)
forall v. ToJSON v => Key -> v -> Maybe (Key, Value)
.=! Vector SlackBlock
blocks
, Key
"private_metadata" Key -> Maybe Text -> Maybe (Key, Value)
forall v. ToJSON v => Key -> Maybe v -> Maybe (Key, Value)
.=? Maybe Text
privateMetadata
, Key
"callback_id" Key -> Maybe Text -> Maybe (Key, Value)
forall v. ToJSON v => Key -> Maybe v -> Maybe (Key, Value)
.=? Maybe Text
callbackId
, Key
"external_id" Key -> Maybe Text -> Maybe (Key, Value)
forall v. ToJSON v => Key -> Maybe v -> Maybe (Key, Value)
.=? Maybe Text
externalId
]
)
Object -> Object -> Object
forall a. Semigroup a => a -> a -> a
<> Object
innerObj
)
Value
_ -> String -> Value
forall a. HasCallStack => String -> a
error String
"inner of SlackView is not an object"
data HomeTabView = HomeTabView
{ HomeTabView -> Expected "home"
type_ :: Expected "home"
}
deriving stock (Int -> HomeTabView -> ShowS
[HomeTabView] -> ShowS
HomeTabView -> String
(Int -> HomeTabView -> ShowS)
-> (HomeTabView -> String)
-> ([HomeTabView] -> ShowS)
-> Show HomeTabView
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> HomeTabView -> ShowS
showsPrec :: Int -> HomeTabView -> ShowS
$cshow :: HomeTabView -> String
show :: HomeTabView -> String
$cshowList :: [HomeTabView] -> ShowS
showList :: [HomeTabView] -> ShowS
Show, HomeTabView -> HomeTabView -> Bool
(HomeTabView -> HomeTabView -> Bool)
-> (HomeTabView -> HomeTabView -> Bool) -> Eq HomeTabView
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: HomeTabView -> HomeTabView -> Bool
== :: HomeTabView -> HomeTabView -> Bool
$c/= :: HomeTabView -> HomeTabView -> Bool
/= :: HomeTabView -> HomeTabView -> Bool
Eq, (forall x. HomeTabView -> Rep HomeTabView x)
-> (forall x. Rep HomeTabView x -> HomeTabView)
-> Generic HomeTabView
forall x. Rep HomeTabView x -> HomeTabView
forall x. HomeTabView -> Rep HomeTabView x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. HomeTabView -> Rep HomeTabView x
from :: forall x. HomeTabView -> Rep HomeTabView x
$cto :: forall x. Rep HomeTabView x -> HomeTabView
to :: forall x. Rep HomeTabView x -> HomeTabView
Generic)
$(deriveJSON snakeCaseOptionsEatTrailingUnderscore ''HomeTabView)
data ModalView = ModalView
{ ModalView -> Expected "modal"
type_ :: Expected "modal"
, ModalView -> SlackPlainTextOnly
title :: SlackPlainTextOnly
, ModalView -> Maybe SlackPlainTextOnly
close :: Maybe SlackPlainTextOnly
, ModalView -> Maybe SlackPlainTextOnly
submit :: Maybe SlackPlainTextOnly
, ModalView -> Maybe Bool
submitDisabled :: Maybe Bool
}
deriving stock (Int -> ModalView -> ShowS
[ModalView] -> ShowS
ModalView -> String
(Int -> ModalView -> ShowS)
-> (ModalView -> String)
-> ([ModalView] -> ShowS)
-> Show ModalView
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ModalView -> ShowS
showsPrec :: Int -> ModalView -> ShowS
$cshow :: ModalView -> String
show :: ModalView -> String
$cshowList :: [ModalView] -> ShowS
showList :: [ModalView] -> ShowS
Show, ModalView -> ModalView -> Bool
(ModalView -> ModalView -> Bool)
-> (ModalView -> ModalView -> Bool) -> Eq ModalView
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ModalView -> ModalView -> Bool
== :: ModalView -> ModalView -> Bool
$c/= :: ModalView -> ModalView -> Bool
/= :: ModalView -> ModalView -> Bool
Eq, (forall x. ModalView -> Rep ModalView x)
-> (forall x. Rep ModalView x -> ModalView) -> Generic ModalView
forall x. Rep ModalView x -> ModalView
forall x. ModalView -> Rep ModalView x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ModalView -> Rep ModalView x
from :: forall x. ModalView -> Rep ModalView x
$cto :: forall x. Rep ModalView x -> ModalView
to :: forall x. Rep ModalView x -> ModalView
Generic)
$(deriveJSON snakeCaseOptionsEatTrailingUnderscore ''ModalView)
data PublishReq = PublishReq
{ PublishReq -> UserId
userId :: UserId
, PublishReq -> SlackView HomeTabView
view :: SlackView HomeTabView
}
deriving stock (Int -> PublishReq -> ShowS
[PublishReq] -> ShowS
PublishReq -> String
(Int -> PublishReq -> ShowS)
-> (PublishReq -> String)
-> ([PublishReq] -> ShowS)
-> Show PublishReq
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PublishReq -> ShowS
showsPrec :: Int -> PublishReq -> ShowS
$cshow :: PublishReq -> String
show :: PublishReq -> String
$cshowList :: [PublishReq] -> ShowS
showList :: [PublishReq] -> ShowS
Show)
instance ToForm PublishReq where
toForm :: PublishReq -> Form
toForm PublishReq {UserId
SlackView HomeTabView
$sel:userId:PublishReq :: PublishReq -> UserId
$sel:view:PublishReq :: PublishReq -> SlackView HomeTabView
userId :: UserId
view :: SlackView HomeTabView
..} =
[ (Text
"user_id" :: Text, UserId -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam UserId
userId)
, (Text
"view", Text -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam (Text -> Text) -> (ByteString -> Text) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteString -> Text
forall textual binary. Utf8 textual binary => binary -> textual
decodeUtf8 (ByteString -> Text) -> ByteString -> Text
forall a b. (a -> b) -> a -> b
$ SlackView HomeTabView -> ByteString
forall a. ToJSON a => a -> ByteString
A.encode SlackView HomeTabView
view)
]
data PublishResp = PublishResp
{ PublishResp -> SlackView HomeTabView
view :: SlackView HomeTabView
}
deriving stock (Int -> PublishResp -> ShowS
[PublishResp] -> ShowS
PublishResp -> String
(Int -> PublishResp -> ShowS)
-> (PublishResp -> String)
-> ([PublishResp] -> ShowS)
-> Show PublishResp
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PublishResp -> ShowS
showsPrec :: Int -> PublishResp -> ShowS
$cshow :: PublishResp -> String
show :: PublishResp -> String
$cshowList :: [PublishResp] -> ShowS
showList :: [PublishResp] -> ShowS
Show)
$(deriveJSON snakeCaseOptions ''PublishResp)
type Api =
"views.publish"
:> AuthProtect "token"
:> ReqBody '[FormUrlEncoded] PublishReq
:> Post '[JSON] (ResponseJSON PublishResp)
viewsPublish :: SlackConfig -> PublishReq -> IO (Response PublishResp)
viewsPublish :: SlackConfig -> PublishReq -> IO (Response PublishResp)
viewsPublish SlackConfig
slackConfig PublishReq
req = do
let authR :: AuthenticatedRequest (AuthProtect "token")
authR = SlackConfig -> AuthenticatedRequest (AuthProtect "token")
mkSlackAuthenticateReq SlackConfig
slackConfig
ClientM (ResponseJSON PublishResp)
-> Manager -> IO (Response PublishResp)
forall a. ClientM (ResponseJSON a) -> Manager -> IO (Response a)
run (AuthenticatedRequest (AuthProtect "token")
-> PublishReq -> ClientM (ResponseJSON PublishResp)
viewsPublish_ AuthenticatedRequest (AuthProtect "token")
authR PublishReq
req) (Manager -> IO (Response PublishResp))
-> (SlackConfig -> Manager)
-> SlackConfig
-> IO (Response PublishResp)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. SlackConfig -> Manager
slackConfigManager (SlackConfig -> IO (Response PublishResp))
-> SlackConfig -> IO (Response PublishResp)
forall a b. (a -> b) -> a -> b
$ SlackConfig
slackConfig
viewsPublish_ :: AuthenticatedRequest (AuthProtect "token") -> PublishReq -> ClientM (ResponseJSON PublishResp)
viewsPublish_ :: AuthenticatedRequest (AuthProtect "token")
-> PublishReq -> ClientM (ResponseJSON PublishResp)
viewsPublish_ = Proxy Api -> Client ClientM Api
forall api.
HasClient ClientM api =>
Proxy api -> Client ClientM api
client (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @Api)