{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}

module Web.Slack.Experimental.Blocks.Types where

import Control.Monad (MonadFail (..))
import Data.Aeson (Object, Result (..), Value (..), fromJSON, withArray)
import Data.Aeson.Types ((.!=))
import Data.StringVariants
import Data.Vector qualified as V
import Refined
import Refined.Unsafe (reallyUnsafeRefine)
import Web.Slack.AesonUtils
import Web.Slack.Common (ConversationId, UserId)
import Web.Slack.Prelude

-- | Class of types that can be turned into part of a Slack Message. 'message'
-- is the primary way of converting primitive and domain-level types into things
-- that can be shown in a slack message.
class Slack a where
  message :: a -> SlackText

newtype SlackText = SlackText {SlackText -> [Text]
unSlackTexts :: [Text]}
  deriving newtype (NonEmpty SlackText -> SlackText
SlackText -> SlackText -> SlackText
(SlackText -> SlackText -> SlackText)
-> (NonEmpty SlackText -> SlackText)
-> (forall b. Integral b => b -> SlackText -> SlackText)
-> Semigroup SlackText
forall b. Integral b => b -> SlackText -> SlackText
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: SlackText -> SlackText -> SlackText
<> :: SlackText -> SlackText -> SlackText
$csconcat :: NonEmpty SlackText -> SlackText
sconcat :: NonEmpty SlackText -> SlackText
$cstimes :: forall b. Integral b => b -> SlackText -> SlackText
stimes :: forall b. Integral b => b -> SlackText -> SlackText
Semigroup, Semigroup SlackText
SlackText
Semigroup SlackText =>
SlackText
-> (SlackText -> SlackText -> SlackText)
-> ([SlackText] -> SlackText)
-> Monoid SlackText
[SlackText] -> SlackText
SlackText -> SlackText -> SlackText
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: SlackText
mempty :: SlackText
$cmappend :: SlackText -> SlackText -> SlackText
mappend :: SlackText -> SlackText -> SlackText
$cmconcat :: [SlackText] -> SlackText
mconcat :: [SlackText] -> SlackText
Monoid, SlackText -> SlackText -> Bool
(SlackText -> SlackText -> Bool)
-> (SlackText -> SlackText -> Bool) -> Eq SlackText
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackText -> SlackText -> Bool
== :: SlackText -> SlackText -> Bool
$c/= :: SlackText -> SlackText -> Bool
/= :: SlackText -> SlackText -> Bool
Eq)

-- | Render a link with optional link text
link :: Text -> Maybe Text -> SlackText
link :: Text -> Maybe Text -> SlackText
link Text
uri = \case
  Maybe Text
Nothing -> Text -> SlackText
forall a. Slack a => a -> SlackText
message (Text -> SlackText) -> Text -> SlackText
forall a b. (a -> b) -> a -> b
$ Text
"<" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
uri Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
">"
  Just Text
linkText -> Text -> SlackText
forall a. Slack a => a -> SlackText
message (Text -> SlackText) -> Text -> SlackText
forall a b. (a -> b) -> a -> b
$ Text
"<" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
uri Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"|" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
linkText Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
">"

data SlackPlainTextOnly = SlackPlainTextOnly SlackText
  deriving stock (SlackPlainTextOnly -> SlackPlainTextOnly -> Bool
(SlackPlainTextOnly -> SlackPlainTextOnly -> Bool)
-> (SlackPlainTextOnly -> SlackPlainTextOnly -> Bool)
-> Eq SlackPlainTextOnly
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackPlainTextOnly -> SlackPlainTextOnly -> Bool
== :: SlackPlainTextOnly -> SlackPlainTextOnly -> Bool
$c/= :: SlackPlainTextOnly -> SlackPlainTextOnly -> Bool
/= :: SlackPlainTextOnly -> SlackPlainTextOnly -> Bool
Eq, Int -> SlackPlainTextOnly -> ShowS
[SlackPlainTextOnly] -> ShowS
SlackPlainTextOnly -> String
(Int -> SlackPlainTextOnly -> ShowS)
-> (SlackPlainTextOnly -> String)
-> ([SlackPlainTextOnly] -> ShowS)
-> Show SlackPlainTextOnly
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackPlainTextOnly -> ShowS
showsPrec :: Int -> SlackPlainTextOnly -> ShowS
$cshow :: SlackPlainTextOnly -> String
show :: SlackPlainTextOnly -> String
$cshowList :: [SlackPlainTextOnly] -> ShowS
showList :: [SlackPlainTextOnly] -> ShowS
Show)

instance IsString SlackPlainTextOnly where
  fromString :: String -> SlackPlainTextOnly
fromString = SlackText -> SlackPlainTextOnly
SlackPlainTextOnly (SlackText -> SlackPlainTextOnly)
-> (String -> SlackText) -> String -> SlackPlainTextOnly
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
. String -> SlackText
forall a. Slack a => a -> SlackText
message

instance ToJSON SlackPlainTextOnly where
  toJSON :: SlackPlainTextOnly -> Value
toJSON (SlackPlainTextOnly (SlackText [Text]
arr)) =
    [Pair] -> Value
object
      [ Key
"type" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (Text
"plain_text" :: Text)
      , Key
"text" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Element [Text] -> [Text] -> Element [Text]
forall mono.
(MonoFoldable mono, Monoid (Element mono)) =>
Element mono -> mono -> Element mono
intercalate Text
Element [Text]
"\n" [Text]
arr
      ]

instance FromJSON SlackPlainTextOnly where
  parseJSON :: Value -> Parser SlackPlainTextOnly
parseJSON = String
-> (Object -> Parser SlackPlainTextOnly)
-> Value
-> Parser SlackPlainTextOnly
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlackPlainTextOnly" ((Object -> Parser SlackPlainTextOnly)
 -> Value -> Parser SlackPlainTextOnly)
-> (Object -> Parser SlackPlainTextOnly)
-> Value
-> Parser SlackPlainTextOnly
forall a b. (a -> b) -> a -> b
$ \Object
obj -> do
    Text
text <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
    SlackPlainTextOnly -> Parser SlackPlainTextOnly
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SlackPlainTextOnly -> Parser SlackPlainTextOnly)
-> ([Text] -> SlackPlainTextOnly)
-> [Text]
-> Parser SlackPlainTextOnly
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
. SlackText -> SlackPlainTextOnly
SlackPlainTextOnly (SlackText -> SlackPlainTextOnly)
-> ([Text] -> SlackText) -> [Text] -> SlackPlainTextOnly
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
. [Text] -> SlackText
SlackText ([Text] -> Parser SlackPlainTextOnly)
-> [Text] -> Parser SlackPlainTextOnly
forall a b. (a -> b) -> a -> b
$ Text -> [Text]
forall t. Textual t => t -> [t]
lines Text
text

-- | Create a 'SlackPlainTextOnly'. Some API points can can take either markdown or plain text,
-- but some can take only plain text. This enforces the latter.
plaintextonly :: (Slack a) => a -> SlackPlainTextOnly
plaintextonly :: forall a. Slack a => a -> SlackPlainTextOnly
plaintextonly a
a = SlackText -> SlackPlainTextOnly
SlackPlainTextOnly (SlackText -> SlackPlainTextOnly)
-> SlackText -> SlackPlainTextOnly
forall a b. (a -> b) -> a -> b
$ a -> SlackText
forall a. Slack a => a -> SlackText
message a
a

data SlackTextObject
  = SlackPlainText SlackText
  | SlackMarkdownText SlackText
  deriving stock (SlackTextObject -> SlackTextObject -> Bool
(SlackTextObject -> SlackTextObject -> Bool)
-> (SlackTextObject -> SlackTextObject -> Bool)
-> Eq SlackTextObject
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackTextObject -> SlackTextObject -> Bool
== :: SlackTextObject -> SlackTextObject -> Bool
$c/= :: SlackTextObject -> SlackTextObject -> Bool
/= :: SlackTextObject -> SlackTextObject -> Bool
Eq, Int -> SlackTextObject -> ShowS
[SlackTextObject] -> ShowS
SlackTextObject -> String
(Int -> SlackTextObject -> ShowS)
-> (SlackTextObject -> String)
-> ([SlackTextObject] -> ShowS)
-> Show SlackTextObject
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackTextObject -> ShowS
showsPrec :: Int -> SlackTextObject -> ShowS
$cshow :: SlackTextObject -> String
show :: SlackTextObject -> String
$cshowList :: [SlackTextObject] -> ShowS
showList :: [SlackTextObject] -> ShowS
Show)

instance ToJSON SlackTextObject where
  toJSON :: SlackTextObject -> Value
toJSON (SlackPlainText (SlackText [Text]
arr)) =
    [Pair] -> Value
object
      [ Key
"type" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (Text
"plain_text" :: Text)
      , Key
"text" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Element [Text] -> [Text] -> Element [Text]
forall mono.
(MonoFoldable mono, Monoid (Element mono)) =>
Element mono -> mono -> Element mono
intercalate Text
Element [Text]
"\n" [Text]
arr
      ]
  toJSON (SlackMarkdownText (SlackText [Text]
arr)) =
    [Pair] -> Value
object
      [ Key
"type" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (Text
"mrkdwn" :: Text)
      , Key
"text" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Element [Text] -> [Text] -> Element [Text]
forall mono.
(MonoFoldable mono, Monoid (Element mono)) =>
Element mono -> mono -> Element mono
intercalate Text
Element [Text]
"\n" [Text]
arr
      ]

-- | Create a plain text 'SlackTextObject' where the API allows either markdown or plain text.
plaintext :: (Slack a) => a -> SlackTextObject
plaintext :: forall a. Slack a => a -> SlackTextObject
plaintext = SlackText -> SlackTextObject
SlackPlainText (SlackText -> SlackTextObject)
-> (a -> SlackText) -> a -> SlackTextObject
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
. a -> SlackText
forall a. Slack a => a -> SlackText
message

-- | Create a markdown 'SlackTextObject' where the API allows either markdown or plain text.
mrkdwn :: (Slack a) => a -> SlackTextObject
mrkdwn :: forall a. Slack a => a -> SlackTextObject
mrkdwn = SlackText -> SlackTextObject
SlackMarkdownText (SlackText -> SlackTextObject)
-> (a -> SlackText) -> a -> SlackTextObject
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
. a -> SlackText
forall a. Slack a => a -> SlackText
message

instance FromJSON SlackTextObject where
  parseJSON :: Value -> Parser SlackTextObject
parseJSON = String
-> (Object -> Parser SlackTextObject)
-> Value
-> Parser SlackTextObject
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlackTextObject" ((Object -> Parser SlackTextObject)
 -> Value -> Parser SlackTextObject)
-> (Object -> Parser SlackTextObject)
-> Value
-> Parser SlackTextObject
forall a b. (a -> b) -> a -> b
$ \Object
obj -> do
    (Text
slackTextType :: Text) <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
    case Text
slackTextType of
      Text
"plain_text" -> do
        Text
text <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
        SlackTextObject -> Parser SlackTextObject
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SlackTextObject -> Parser SlackTextObject)
-> ([Text] -> SlackTextObject) -> [Text] -> Parser SlackTextObject
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
. SlackText -> SlackTextObject
SlackPlainText (SlackText -> SlackTextObject)
-> ([Text] -> SlackText) -> [Text] -> SlackTextObject
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
. [Text] -> SlackText
SlackText ([Text] -> Parser SlackTextObject)
-> [Text] -> Parser SlackTextObject
forall a b. (a -> b) -> a -> b
$ Text -> [Text]
forall t. Textual t => t -> [t]
lines Text
text
      Text
"mrkdwn" -> do
        Text
text <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
        SlackTextObject -> Parser SlackTextObject
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SlackTextObject -> Parser SlackTextObject)
-> ([Text] -> SlackTextObject) -> [Text] -> Parser SlackTextObject
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
. SlackText -> SlackTextObject
SlackMarkdownText (SlackText -> SlackTextObject)
-> ([Text] -> SlackText) -> [Text] -> SlackTextObject
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
. [Text] -> SlackText
SlackText ([Text] -> Parser SlackTextObject)
-> [Text] -> Parser SlackTextObject
forall a b. (a -> b) -> a -> b
$ Text -> [Text]
forall t. Textual t => t -> [t]
lines Text
text
      Text
_ -> String -> Parser SlackTextObject
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Unknown SlackTextObject type, must be one of ['plain_text', 'mrkdwn']"

instance Show SlackText where
  show :: SlackText -> String
show (SlackText [Text]
arr) = Text -> String
forall a. Show a => a -> String
show (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ [Text] -> Element [Text]
forall mono.
(MonoFoldable mono, Monoid (Element mono)) =>
mono -> Element mono
concat [Text]
arr

instance ToJSON SlackText where
  toJSON :: SlackText -> Value
toJSON (SlackText [Text]
arr) = Text -> Value
forall a. ToJSON a => a -> Value
toJSON (Text -> Value) -> Text -> Value
forall a b. (a -> b) -> a -> b
$ [Text] -> Element [Text]
forall mono.
(MonoFoldable mono, Monoid (Element mono)) =>
mono -> Element mono
concat [Text]
arr

instance IsString SlackText where
  fromString :: String -> SlackText
fromString = String -> SlackText
forall a. Slack a => a -> SlackText
message

instance Slack Text where
  message :: Text -> SlackText
message Text
text = [Text] -> SlackText
SlackText [Text
text]

instance Slack String where
  message :: String -> SlackText
message = forall a. Slack a => a -> SlackText
message @Text (Text -> SlackText) -> (String -> Text) -> String -> SlackText
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
. String -> Text
[Element Text] -> Text
forall seq. IsSequence seq => [Element seq] -> seq
pack

instance Slack Int where
  message :: Int -> SlackText
message = String -> SlackText
forall a. Slack a => a -> SlackText
message (String -> SlackText) -> (Int -> String) -> Int -> SlackText
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
. Int -> String
forall a. Show a => a -> String
show

-- | Represents an optional setting for some Slack Setting.
newtype OptionalSetting a = OptionalSetting {forall a. OptionalSetting a -> Maybe a
unOptionalSetting :: Maybe a}
  deriving newtype (OptionalSetting a -> OptionalSetting a -> Bool
(OptionalSetting a -> OptionalSetting a -> Bool)
-> (OptionalSetting a -> OptionalSetting a -> Bool)
-> Eq (OptionalSetting a)
forall a. Eq a => OptionalSetting a -> OptionalSetting a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => OptionalSetting a -> OptionalSetting a -> Bool
== :: OptionalSetting a -> OptionalSetting a -> Bool
$c/= :: forall a. Eq a => OptionalSetting a -> OptionalSetting a -> Bool
/= :: OptionalSetting a -> OptionalSetting a -> Bool
Eq)

-- | Allows using bare Strings without having to use 'setting'
instance IsString (OptionalSetting String) where
  fromString :: String -> OptionalSetting String
fromString = Maybe String -> OptionalSetting String
forall a. Maybe a -> OptionalSetting a
OptionalSetting (Maybe String -> OptionalSetting String)
-> (String -> Maybe String) -> String -> OptionalSetting String
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
. String -> Maybe String
forall a. a -> Maybe a
Just

-- | Allows using bare Texts without having to use 'setting'
instance IsString (OptionalSetting Text) where
  fromString :: String -> OptionalSetting Text
fromString = Maybe Text -> OptionalSetting Text
forall a. Maybe a -> OptionalSetting a
OptionalSetting (Maybe Text -> OptionalSetting Text)
-> (String -> Maybe Text) -> String -> OptionalSetting 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
. Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> (String -> Text) -> String -> Maybe 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
. String -> Text
[Element Text] -> Text
forall seq. IsSequence seq => [Element seq] -> seq
pack

-- | Sets a setting.
setting :: a -> OptionalSetting a
setting :: forall a. a -> OptionalSetting a
setting = Maybe a -> OptionalSetting a
forall a. Maybe a -> OptionalSetting a
OptionalSetting (Maybe a -> OptionalSetting a)
-> (a -> Maybe a) -> a -> OptionalSetting a
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
. a -> Maybe a
forall a. a -> Maybe a
Just

-- | Sets the empty setting.
emptySetting :: OptionalSetting a
emptySetting :: forall a. OptionalSetting a
emptySetting = Maybe a -> OptionalSetting a
forall a. Maybe a -> OptionalSetting a
OptionalSetting Maybe a
forall a. Maybe a
Nothing

-- | Styles for Slack [buttons](https://api.slack.com/reference/block-kit/block-elements#button).
-- If no style is given, the default style (black) is used.
data SlackStyle
  = -- | Green button
    SlackStylePrimary
  | -- | Red button
    SlackStyleDanger
  deriving stock (SlackStyle -> SlackStyle -> Bool
(SlackStyle -> SlackStyle -> Bool)
-> (SlackStyle -> SlackStyle -> Bool) -> Eq SlackStyle
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackStyle -> SlackStyle -> Bool
== :: SlackStyle -> SlackStyle -> Bool
$c/= :: SlackStyle -> SlackStyle -> Bool
/= :: SlackStyle -> SlackStyle -> Bool
Eq, Int -> SlackStyle -> ShowS
[SlackStyle] -> ShowS
SlackStyle -> String
(Int -> SlackStyle -> ShowS)
-> (SlackStyle -> String)
-> ([SlackStyle] -> ShowS)
-> Show SlackStyle
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackStyle -> ShowS
showsPrec :: Int -> SlackStyle -> ShowS
$cshow :: SlackStyle -> String
show :: SlackStyle -> String
$cshowList :: [SlackStyle] -> ShowS
showList :: [SlackStyle] -> ShowS
Show)

$(deriveJSON (jsonDeriveWithAffix "SlackStyle" jsonDeriveOptionsSnakeCase) ''SlackStyle)

-- | Used to identify an action. The ID used should be unique among all actions in the block.
--
--   This is limited to 255 characters, per the Slack documentation at
--   <https://api.slack.com/reference/block-kit/block-elements#button>
newtype SlackActionId = SlackActionId {SlackActionId -> NonEmptyText 255
unSlackActionId :: NonEmptyText 255}
  deriving stock (Int -> SlackActionId -> ShowS
[SlackActionId] -> ShowS
SlackActionId -> String
(Int -> SlackActionId -> ShowS)
-> (SlackActionId -> String)
-> ([SlackActionId] -> ShowS)
-> Show SlackActionId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackActionId -> ShowS
showsPrec :: Int -> SlackActionId -> ShowS
$cshow :: SlackActionId -> String
show :: SlackActionId -> String
$cshowList :: [SlackActionId] -> ShowS
showList :: [SlackActionId] -> ShowS
Show, SlackActionId -> SlackActionId -> Bool
(SlackActionId -> SlackActionId -> Bool)
-> (SlackActionId -> SlackActionId -> Bool) -> Eq SlackActionId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackActionId -> SlackActionId -> Bool
== :: SlackActionId -> SlackActionId -> Bool
$c/= :: SlackActionId -> SlackActionId -> Bool
/= :: SlackActionId -> SlackActionId -> Bool
Eq)
  deriving newtype (Value -> Parser [SlackActionId]
Value -> Parser SlackActionId
(Value -> Parser SlackActionId)
-> (Value -> Parser [SlackActionId]) -> FromJSON SlackActionId
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
$cparseJSON :: Value -> Parser SlackActionId
parseJSON :: Value -> Parser SlackActionId
$cparseJSONList :: Value -> Parser [SlackActionId]
parseJSONList :: Value -> Parser [SlackActionId]
FromJSON, [SlackActionId] -> Value
[SlackActionId] -> Encoding
SlackActionId -> Value
SlackActionId -> Encoding
(SlackActionId -> Value)
-> (SlackActionId -> Encoding)
-> ([SlackActionId] -> Value)
-> ([SlackActionId] -> Encoding)
-> ToJSON SlackActionId
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
$ctoJSON :: SlackActionId -> Value
toJSON :: SlackActionId -> Value
$ctoEncoding :: SlackActionId -> Encoding
toEncoding :: SlackActionId -> Encoding
$ctoJSONList :: [SlackActionId] -> Value
toJSONList :: [SlackActionId] -> Value
$ctoEncodingList :: [SlackActionId] -> Encoding
toEncodingList :: [SlackActionId] -> Encoding
ToJSON)

-- FIXME(jadel): SlackActionId might be worth turning into something more type
-- safe: possibly parameterize SlackAction over a sum type parameter

data SlackImage = SlackImage
  { SlackImage -> Maybe Text
slackImageTitle :: !(Maybe Text)
  , SlackImage -> Text
slackImageAltText :: !Text
  -- ^ Optional Title
  , SlackImage -> Text
slackImageUrl :: !Text
  }
  deriving stock (SlackImage -> SlackImage -> Bool
(SlackImage -> SlackImage -> Bool)
-> (SlackImage -> SlackImage -> Bool) -> Eq SlackImage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackImage -> SlackImage -> Bool
== :: SlackImage -> SlackImage -> Bool
$c/= :: SlackImage -> SlackImage -> Bool
/= :: SlackImage -> SlackImage -> Bool
Eq)

instance Show SlackImage where
  show :: SlackImage -> String
show (SlackImage Maybe Text
_ Text
altText Text
_) = Text -> [Element Text]
forall mono. MonoFoldable mono => mono -> [Element mono]
unpack Text
altText

data SlackContent
  = SlackContentText SlackText
  | SlackContentImage SlackImage
  deriving stock (SlackContent -> SlackContent -> Bool
(SlackContent -> SlackContent -> Bool)
-> (SlackContent -> SlackContent -> Bool) -> Eq SlackContent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackContent -> SlackContent -> Bool
== :: SlackContent -> SlackContent -> Bool
$c/= :: SlackContent -> SlackContent -> Bool
/= :: SlackContent -> SlackContent -> Bool
Eq)

slackContentToSlackText :: SlackContent -> Maybe SlackText
slackContentToSlackText :: SlackContent -> Maybe SlackText
slackContentToSlackText SlackContent
c = case SlackContent
c of
  SlackContentText SlackText
slackText ->
    SlackText -> Maybe SlackText
forall a. a -> Maybe a
Just SlackText
slackText
  SlackContentImage SlackImage
_ ->
    Maybe SlackText
forall a. Maybe a
Nothing

instance Show SlackContent where
  show :: SlackContent -> String
show (SlackContentText SlackText
t) = SlackText -> String
forall a. Show a => a -> String
show SlackText
t
  show (SlackContentImage SlackImage
i) = SlackImage -> String
forall a. Show a => a -> String
show SlackImage
i

instance ToJSON SlackContent where
  toJSON :: SlackContent -> Value
toJSON (SlackContentText SlackText
t) =
    [Pair] -> Value
object
      [ Key
"type" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (Text
"mrkdwn" :: Text)
      , Key
"text" Key -> SlackText -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= SlackText
t
      ]
  toJSON (SlackContentImage (SlackImage Maybe Text
mtitle Text
altText Text
url)) =
    [Pair] -> Value
object
      ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$ [ Key
"type" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (Text
"image" :: Text)
        , Key
"image_url" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Text
url
        , Key
"alt_text" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Text
altText
        ]
      [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> [Pair] -> (Text -> [Pair]) -> Maybe Text -> [Pair]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] Text -> [Pair]
forall {a} {v}. (KeyValue a, ToJSON v) => v -> [a]
mkTitle Maybe Text
mtitle
    where
      mkTitle :: v -> [a]
mkTitle v
title =
        [ Key
"title"
            Key -> Value -> a
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> a
.= [Pair] -> Value
object
              [ Key
"type" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (Text
"plain_text" :: Text)
              , Key
"text" Key -> v -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= v
title
              ]
        ]

instance FromJSON SlackContent where
  parseJSON :: Value -> Parser SlackContent
parseJSON = String
-> (Object -> Parser SlackContent) -> Value -> Parser SlackContent
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlackContent" ((Object -> Parser SlackContent) -> Value -> Parser SlackContent)
-> (Object -> Parser SlackContent) -> Value -> Parser SlackContent
forall a b. (a -> b) -> a -> b
$ \Object
obj -> do
    (Text
slackContentType :: Text) <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
    case Text
slackContentType of
      Text
"mrkdwn" -> do
        (String
slackContentText :: String) <- Object
obj Object -> Key -> Parser String
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
        pure $ SlackText -> SlackContent
SlackContentText (SlackText -> SlackContent) -> SlackText -> SlackContent
forall a b. (a -> b) -> a -> b
$ String -> SlackText
forall a. IsString a => String -> a
fromString String
slackContentText
      Text
"image" -> do
        (Text
slackImageUrl :: Text) <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"image_url"
        (Text
slackImageAltText :: Text) <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"alt_text"
        (Maybe Object
slackImageTitleObj :: Maybe Object) <- Object
obj Object -> Key -> Parser (Maybe Object)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"title"
        (Maybe Text
slackImageTitleText :: Maybe Text) <- case Maybe Object
slackImageTitleObj of
          Just Object
innerObj -> Object
innerObj Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
          Maybe Object
Nothing -> Maybe Text -> Parser (Maybe Text)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Text
forall a. Maybe a
Nothing
        pure $ SlackImage -> SlackContent
SlackContentImage (SlackImage -> SlackContent) -> SlackImage -> SlackContent
forall a b. (a -> b) -> a -> b
$ Maybe Text -> Text -> Text -> SlackImage
SlackImage Maybe Text
slackImageTitleText Text
slackImageAltText Text
slackImageUrl
      Text
_ -> String -> Parser SlackContent
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Unknown SlackContent type, must be one of ['mrkdwn', 'image']"

newtype SlackContext = SlackContext [SlackContent]
  deriving newtype (NonEmpty SlackContext -> SlackContext
SlackContext -> SlackContext -> SlackContext
(SlackContext -> SlackContext -> SlackContext)
-> (NonEmpty SlackContext -> SlackContext)
-> (forall b. Integral b => b -> SlackContext -> SlackContext)
-> Semigroup SlackContext
forall b. Integral b => b -> SlackContext -> SlackContext
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: SlackContext -> SlackContext -> SlackContext
<> :: SlackContext -> SlackContext -> SlackContext
$csconcat :: NonEmpty SlackContext -> SlackContext
sconcat :: NonEmpty SlackContext -> SlackContext
$cstimes :: forall b. Integral b => b -> SlackContext -> SlackContext
stimes :: forall b. Integral b => b -> SlackContext -> SlackContext
Semigroup, Semigroup SlackContext
SlackContext
Semigroup SlackContext =>
SlackContext
-> (SlackContext -> SlackContext -> SlackContext)
-> ([SlackContext] -> SlackContext)
-> Monoid SlackContext
[SlackContext] -> SlackContext
SlackContext -> SlackContext -> SlackContext
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: SlackContext
mempty :: SlackContext
$cmappend :: SlackContext -> SlackContext -> SlackContext
mappend :: SlackContext -> SlackContext -> SlackContext
$cmconcat :: [SlackContext] -> SlackContext
mconcat :: [SlackContext] -> SlackContext
Monoid, SlackContext -> SlackContext -> Bool
(SlackContext -> SlackContext -> Bool)
-> (SlackContext -> SlackContext -> Bool) -> Eq SlackContext
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackContext -> SlackContext -> Bool
== :: SlackContext -> SlackContext -> Bool
$c/= :: SlackContext -> SlackContext -> Bool
/= :: SlackContext -> SlackContext -> Bool
Eq)

instance Show SlackContext where
  show :: SlackContext -> String
show (SlackContext [SlackContent]
arr) = [SlackContent] -> String
forall a. Show a => a -> String
show [SlackContent]
arr

instance ToJSON SlackContext where
  toJSON :: SlackContext -> Value
toJSON (SlackContext [SlackContent]
arr) = [SlackContent] -> Value
forall a. ToJSON a => a -> Value
toJSON [SlackContent]
arr

instance FromJSON SlackContext where
  parseJSON :: Value -> Parser SlackContext
parseJSON = String
-> (Array -> Parser SlackContext) -> Value -> Parser SlackContext
forall a. String -> (Array -> Parser a) -> Value -> Parser a
withArray String
"SlackContext" ((Array -> Parser SlackContext) -> Value -> Parser SlackContext)
-> (Array -> Parser SlackContext) -> Value -> Parser SlackContext
forall a b. (a -> b) -> a -> b
$ \Array
arr -> do
    (Vector SlackContent
parsedAsArrayOfSlackContents :: V.Vector SlackContent) <- (Value -> Parser SlackContent)
-> Array -> Parser (Vector SlackContent)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Vector a -> f (Vector b)
traverse Value -> Parser SlackContent
forall a. FromJSON a => Value -> Parser a
parseJSON Array
arr
    let slackContentList :: [SlackContent]
slackContentList = Vector SlackContent -> [SlackContent]
forall a. Vector a -> [a]
V.toList Vector SlackContent
parsedAsArrayOfSlackContents
    SlackContext -> Parser SlackContext
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SlackContext -> Parser SlackContext)
-> SlackContext -> Parser SlackContext
forall a b. (a -> b) -> a -> b
$ [SlackContent] -> SlackContext
SlackContext [SlackContent]
slackContentList

type SlackActionListConstraints = SizeGreaterThan 0 && SizeLessThan 6

-- | List that enforces that Slack actions must have between 1 and 5 actions.
newtype SlackActionList = SlackActionList {SlackActionList -> Refined SlackActionListConstraints [SlackAction]
unSlackActionList :: Refined SlackActionListConstraints [SlackAction]}
  deriving stock (Int -> SlackActionList -> ShowS
[SlackActionList] -> ShowS
SlackActionList -> String
(Int -> SlackActionList -> ShowS)
-> (SlackActionList -> String)
-> ([SlackActionList] -> ShowS)
-> Show SlackActionList
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackActionList -> ShowS
showsPrec :: Int -> SlackActionList -> ShowS
$cshow :: SlackActionList -> String
show :: SlackActionList -> String
$cshowList :: [SlackActionList] -> ShowS
showList :: [SlackActionList] -> ShowS
Show)
  deriving newtype (SlackActionList -> SlackActionList -> Bool
(SlackActionList -> SlackActionList -> Bool)
-> (SlackActionList -> SlackActionList -> Bool)
-> Eq SlackActionList
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackActionList -> SlackActionList -> Bool
== :: SlackActionList -> SlackActionList -> Bool
$c/= :: SlackActionList -> SlackActionList -> Bool
/= :: SlackActionList -> SlackActionList -> Bool
Eq, Value -> Parser [SlackActionList]
Value -> Parser SlackActionList
(Value -> Parser SlackActionList)
-> (Value -> Parser [SlackActionList]) -> FromJSON SlackActionList
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
$cparseJSON :: Value -> Parser SlackActionList
parseJSON :: Value -> Parser SlackActionList
$cparseJSONList :: Value -> Parser [SlackActionList]
parseJSONList :: Value -> Parser [SlackActionList]
FromJSON, [SlackActionList] -> Value
[SlackActionList] -> Encoding
SlackActionList -> Value
SlackActionList -> Encoding
(SlackActionList -> Value)
-> (SlackActionList -> Encoding)
-> ([SlackActionList] -> Value)
-> ([SlackActionList] -> Encoding)
-> ToJSON SlackActionList
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
$ctoJSON :: SlackActionList -> Value
toJSON :: SlackActionList -> Value
$ctoEncoding :: SlackActionList -> Encoding
toEncoding :: SlackActionList -> Encoding
$ctoJSONList :: [SlackActionList] -> Value
toJSONList :: [SlackActionList] -> Value
$ctoEncodingList :: [SlackActionList] -> Encoding
toEncodingList :: [SlackActionList] -> Encoding
ToJSON)

-- | Helper to allow using up to a 5-tuple for a 'SlackActionList'
class ToSlackActionList a where
  toSlackActionList :: a -> SlackActionList

instance ToSlackActionList SlackActionList where
  toSlackActionList :: SlackActionList -> SlackActionList
toSlackActionList = SlackActionList -> SlackActionList
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

instance ToSlackActionList SlackAction where
  toSlackActionList :: SlackAction -> SlackActionList
toSlackActionList SlackAction
a = Refined SlackActionListConstraints [SlackAction] -> SlackActionList
SlackActionList (Refined SlackActionListConstraints [SlackAction]
 -> SlackActionList)
-> Refined SlackActionListConstraints [SlackAction]
-> SlackActionList
forall a b. (a -> b) -> a -> b
$ [SlackAction] -> Refined SlackActionListConstraints [SlackAction]
forall {k} x (p :: k). x -> Refined p x
reallyUnsafeRefine [SlackAction
a]

instance ToSlackActionList (SlackAction, SlackAction) where
  toSlackActionList :: (SlackAction, SlackAction) -> SlackActionList
toSlackActionList (SlackAction
a, SlackAction
b) = Refined SlackActionListConstraints [SlackAction] -> SlackActionList
SlackActionList (Refined SlackActionListConstraints [SlackAction]
 -> SlackActionList)
-> Refined SlackActionListConstraints [SlackAction]
-> SlackActionList
forall a b. (a -> b) -> a -> b
$ [SlackAction] -> Refined SlackActionListConstraints [SlackAction]
forall {k} x (p :: k). x -> Refined p x
reallyUnsafeRefine [SlackAction
a, SlackAction
b]

instance ToSlackActionList (SlackAction, SlackAction, SlackAction) where
  toSlackActionList :: (SlackAction, SlackAction, SlackAction) -> SlackActionList
toSlackActionList (SlackAction
a, SlackAction
b, SlackAction
c) = Refined SlackActionListConstraints [SlackAction] -> SlackActionList
SlackActionList (Refined SlackActionListConstraints [SlackAction]
 -> SlackActionList)
-> Refined SlackActionListConstraints [SlackAction]
-> SlackActionList
forall a b. (a -> b) -> a -> b
$ [SlackAction] -> Refined SlackActionListConstraints [SlackAction]
forall {k} x (p :: k). x -> Refined p x
reallyUnsafeRefine [SlackAction
a, SlackAction
b, SlackAction
c]

instance ToSlackActionList (SlackAction, SlackAction, SlackAction, SlackAction) where
  toSlackActionList :: (SlackAction, SlackAction, SlackAction, SlackAction)
-> SlackActionList
toSlackActionList (SlackAction
a, SlackAction
b, SlackAction
c, SlackAction
d) = Refined SlackActionListConstraints [SlackAction] -> SlackActionList
SlackActionList (Refined SlackActionListConstraints [SlackAction]
 -> SlackActionList)
-> Refined SlackActionListConstraints [SlackAction]
-> SlackActionList
forall a b. (a -> b) -> a -> b
$ [SlackAction] -> Refined SlackActionListConstraints [SlackAction]
forall {k} x (p :: k). x -> Refined p x
reallyUnsafeRefine [SlackAction
a, SlackAction
b, SlackAction
c, SlackAction
d]

instance ToSlackActionList (SlackAction, SlackAction, SlackAction, SlackAction, SlackAction) where
  toSlackActionList :: (SlackAction, SlackAction, SlackAction, SlackAction, SlackAction)
-> SlackActionList
toSlackActionList (SlackAction
a, SlackAction
b, SlackAction
c, SlackAction
d, SlackAction
e) = Refined SlackActionListConstraints [SlackAction] -> SlackActionList
SlackActionList (Refined SlackActionListConstraints [SlackAction]
 -> SlackActionList)
-> Refined SlackActionListConstraints [SlackAction]
-> SlackActionList
forall a b. (a -> b) -> a -> b
$ [SlackAction] -> Refined SlackActionListConstraints [SlackAction]
forall {k} x (p :: k). x -> Refined p x
reallyUnsafeRefine [SlackAction
a, SlackAction
b, SlackAction
c, SlackAction
d, SlackAction
e]

-- | A rich text style. You can't actually send these, for some reason.
data RichStyle = RichStyle
  { RichStyle -> Bool
rsBold :: Bool
  , RichStyle -> Bool
rsItalic :: Bool
  }
  deriving stock (RichStyle -> RichStyle -> Bool
(RichStyle -> RichStyle -> Bool)
-> (RichStyle -> RichStyle -> Bool) -> Eq RichStyle
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RichStyle -> RichStyle -> Bool
== :: RichStyle -> RichStyle -> Bool
$c/= :: RichStyle -> RichStyle -> Bool
/= :: RichStyle -> RichStyle -> Bool
Eq, Int -> RichStyle -> ShowS
[RichStyle] -> ShowS
RichStyle -> String
(Int -> RichStyle -> ShowS)
-> (RichStyle -> String)
-> ([RichStyle] -> ShowS)
-> Show RichStyle
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RichStyle -> ShowS
showsPrec :: Int -> RichStyle -> ShowS
$cshow :: RichStyle -> String
show :: RichStyle -> String
$cshowList :: [RichStyle] -> ShowS
showList :: [RichStyle] -> ShowS
Show)

instance Semigroup RichStyle where
  RichStyle
a <> :: RichStyle -> RichStyle -> RichStyle
<> RichStyle
b = RichStyle {rsBold :: Bool
rsBold = RichStyle -> Bool
rsBold RichStyle
a Bool -> Bool -> Bool
|| RichStyle -> Bool
rsBold RichStyle
b, rsItalic :: Bool
rsItalic = RichStyle -> Bool
rsItalic RichStyle
a Bool -> Bool -> Bool
|| RichStyle -> Bool
rsItalic RichStyle
b}

instance Monoid RichStyle where
  mempty :: RichStyle
mempty = RichStyle {rsBold :: Bool
rsBold = Bool
False, rsItalic :: Bool
rsItalic = Bool
False}

instance FromJSON RichStyle where
  parseJSON :: Value -> Parser RichStyle
parseJSON = String -> (Object -> Parser RichStyle) -> Value -> Parser RichStyle
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"RichStyle" \Object
obj -> do
    Bool
rsBold <- Object
obj Object -> Key -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"bold" Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Bool
False
    Bool
rsItalic <- Object
obj Object -> Key -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"italic" Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Bool
False
    pure RichStyle {Bool
rsBold :: Bool
rsItalic :: Bool
rsBold :: Bool
rsItalic :: Bool
..}

data RichLinkAttrs = RichLinkAttrs
  { RichLinkAttrs -> RichStyle
style :: RichStyle
  , RichLinkAttrs -> Text
url :: Text
  , RichLinkAttrs -> Maybe Text
text :: Maybe Text
  -- ^ Probably is empty in the case of links that are just the URL
  }
  deriving stock (RichLinkAttrs -> RichLinkAttrs -> Bool
(RichLinkAttrs -> RichLinkAttrs -> Bool)
-> (RichLinkAttrs -> RichLinkAttrs -> Bool) -> Eq RichLinkAttrs
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RichLinkAttrs -> RichLinkAttrs -> Bool
== :: RichLinkAttrs -> RichLinkAttrs -> Bool
$c/= :: RichLinkAttrs -> RichLinkAttrs -> Bool
/= :: RichLinkAttrs -> RichLinkAttrs -> Bool
Eq, Int -> RichLinkAttrs -> ShowS
[RichLinkAttrs] -> ShowS
RichLinkAttrs -> String
(Int -> RichLinkAttrs -> ShowS)
-> (RichLinkAttrs -> String)
-> ([RichLinkAttrs] -> ShowS)
-> Show RichLinkAttrs
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RichLinkAttrs -> ShowS
showsPrec :: Int -> RichLinkAttrs -> ShowS
$cshow :: RichLinkAttrs -> String
show :: RichLinkAttrs -> String
$cshowList :: [RichLinkAttrs] -> ShowS
showList :: [RichLinkAttrs] -> ShowS
Show)

-- | Seemingly only documented at
--  <https://api.slack.com/changelog/2019-09-what-they-see-is-what-you-get-and-more-and-less>
--
--  They warn of undocumented element types. Joy.
data RichItem
  = RichItemText Text RichStyle
  | RichItemChannel ConversationId
  | RichItemUser UserId RichStyle
  | RichItemLink RichLinkAttrs
  | RichItemEmoji Text
  | RichItemOther Text Value
  -- FIXME(jadel): date, usergroup, team, broadcast
  deriving stock (RichItem -> RichItem -> Bool
(RichItem -> RichItem -> Bool)
-> (RichItem -> RichItem -> Bool) -> Eq RichItem
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RichItem -> RichItem -> Bool
== :: RichItem -> RichItem -> Bool
$c/= :: RichItem -> RichItem -> Bool
/= :: RichItem -> RichItem -> Bool
Eq, Int -> RichItem -> ShowS
[RichItem] -> ShowS
RichItem -> String
(Int -> RichItem -> ShowS)
-> (RichItem -> String) -> ([RichItem] -> ShowS) -> Show RichItem
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RichItem -> ShowS
showsPrec :: Int -> RichItem -> ShowS
$cshow :: RichItem -> String
show :: RichItem -> String
$cshowList :: [RichItem] -> ShowS
showList :: [RichItem] -> ShowS
Show)

instance FromJSON RichItem where
  parseJSON :: Value -> Parser RichItem
parseJSON = String -> (Object -> Parser RichItem) -> Value -> Parser RichItem
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"RichItem" \Object
obj -> do
    Text
kind :: Text <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
    case Text
kind of
      Text
"text" -> do
        RichStyle
style <- Object
obj Object -> Key -> Parser (Maybe RichStyle)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"style" Parser (Maybe RichStyle) -> RichStyle -> Parser RichStyle
forall a. Parser (Maybe a) -> a -> Parser a
.!= RichStyle
forall a. Monoid a => a
mempty
        Text
text <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
        pure $ Text -> RichStyle -> RichItem
RichItemText Text
text RichStyle
style
      Text
"channel" -> do
        ConversationId
channelId <- Object
obj Object -> Key -> Parser ConversationId
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"channel_id"
        pure $ ConversationId -> RichItem
RichItemChannel ConversationId
channelId
      Text
"emoji" -> do
        Text
name <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
        pure $ Text -> RichItem
RichItemEmoji Text
name
      Text
"link" -> do
        Text
url <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"url"
        Maybe Text
text <- Object
obj Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"text"
        RichStyle
style <- Object
obj Object -> Key -> Parser (Maybe RichStyle)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"style" Parser (Maybe RichStyle) -> RichStyle -> Parser RichStyle
forall a. Parser (Maybe a) -> a -> Parser a
.!= RichStyle
forall a. Monoid a => a
mempty
        pure $ RichLinkAttrs -> RichItem
RichItemLink RichLinkAttrs {Maybe Text
Text
RichStyle
style :: RichStyle
url :: Text
text :: Maybe Text
url :: Text
text :: Maybe Text
style :: RichStyle
..}
      Text
"user" -> do
        UserId
userId <- Object
obj Object -> Key -> Parser UserId
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"user_id"
        RichStyle
style <- Object
obj Object -> Key -> Parser (Maybe RichStyle)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"style" Parser (Maybe RichStyle) -> RichStyle -> Parser RichStyle
forall a. Parser (Maybe a) -> a -> Parser a
.!= RichStyle
forall a. Monoid a => a
mempty
        pure $ UserId -> RichStyle -> RichItem
RichItemUser UserId
userId RichStyle
style
      Text
_ -> RichItem -> Parser RichItem
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RichItem -> Parser RichItem) -> RichItem -> Parser RichItem
forall a b. (a -> b) -> a -> b
$ Text -> Value -> RichItem
RichItemOther Text
kind (Object -> Value
Object Object
obj)

data RichTextSectionItem
  = RichTextSectionItemRichText [RichItem]
  | RichTextSectionItemUnknown Text Value
  deriving stock (RichTextSectionItem -> RichTextSectionItem -> Bool
(RichTextSectionItem -> RichTextSectionItem -> Bool)
-> (RichTextSectionItem -> RichTextSectionItem -> Bool)
-> Eq RichTextSectionItem
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RichTextSectionItem -> RichTextSectionItem -> Bool
== :: RichTextSectionItem -> RichTextSectionItem -> Bool
$c/= :: RichTextSectionItem -> RichTextSectionItem -> Bool
/= :: RichTextSectionItem -> RichTextSectionItem -> Bool
Eq, Int -> RichTextSectionItem -> ShowS
[RichTextSectionItem] -> ShowS
RichTextSectionItem -> String
(Int -> RichTextSectionItem -> ShowS)
-> (RichTextSectionItem -> String)
-> ([RichTextSectionItem] -> ShowS)
-> Show RichTextSectionItem
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RichTextSectionItem -> ShowS
showsPrec :: Int -> RichTextSectionItem -> ShowS
$cshow :: RichTextSectionItem -> String
show :: RichTextSectionItem -> String
$cshowList :: [RichTextSectionItem] -> ShowS
showList :: [RichTextSectionItem] -> ShowS
Show)

instance FromJSON RichTextSectionItem where
  parseJSON :: Value -> Parser RichTextSectionItem
parseJSON = String
-> (Object -> Parser RichTextSectionItem)
-> Value
-> Parser RichTextSectionItem
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"RichTextSectionItem" \Object
obj -> do
    Text
kind <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
    case Text
kind of
      Text
"rich_text_section" -> do
        [RichItem]
elts <- Object
obj Object -> Key -> Parser [RichItem]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"elements"
        pure $ [RichItem] -> RichTextSectionItem
RichTextSectionItemRichText [RichItem]
elts
      Text
_ -> RichTextSectionItem -> Parser RichTextSectionItem
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RichTextSectionItem -> Parser RichTextSectionItem)
-> RichTextSectionItem -> Parser RichTextSectionItem
forall a b. (a -> b) -> a -> b
$ Text -> Value -> RichTextSectionItem
RichTextSectionItemUnknown Text
kind (Object -> Value
Object Object
obj)

data RichText = RichText
  { RichText -> Maybe (NonEmptyText 255)
blockId :: Maybe SlackBlockId
  , RichText -> [RichTextSectionItem]
elements :: [RichTextSectionItem]
  }
  deriving stock (RichText -> RichText -> Bool
(RichText -> RichText -> Bool)
-> (RichText -> RichText -> Bool) -> Eq RichText
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RichText -> RichText -> Bool
== :: RichText -> RichText -> Bool
$c/= :: RichText -> RichText -> Bool
/= :: RichText -> RichText -> Bool
Eq, Int -> RichText -> ShowS
[RichText] -> ShowS
RichText -> String
(Int -> RichText -> ShowS)
-> (RichText -> String) -> ([RichText] -> ShowS) -> Show RichText
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RichText -> ShowS
showsPrec :: Int -> RichText -> ShowS
$cshow :: RichText -> String
show :: RichText -> String
$cshowList :: [RichText] -> ShowS
showList :: [RichText] -> ShowS
Show)

instance FromJSON RichText where
  parseJSON :: Value -> Parser RichText
parseJSON = String -> (Object -> Parser RichText) -> Value -> Parser RichText
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"RichText" \Object
obj -> do
    Maybe (NonEmptyText 255)
blockId <- Object
obj Object -> Key -> Parser (Maybe (NonEmptyText 255))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"block_id"
    [RichTextSectionItem]
elements <- Object
obj Object -> Key -> Parser [RichTextSectionItem]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"elements"
    pure RichText {[RichTextSectionItem]
Maybe (NonEmptyText 255)
blockId :: Maybe (NonEmptyText 255)
elements :: [RichTextSectionItem]
blockId :: Maybe (NonEmptyText 255)
elements :: [RichTextSectionItem]
..}

-- | Accessory is a type of optional block element that floats to the right of text in a BlockSection.
--   <https://api.slack.com/reference/block-kit/blocks#section_fields>
data SlackAccessory
  = SlackButtonAccessory SlackAction -- button
  deriving stock (SlackAccessory -> SlackAccessory -> Bool
(SlackAccessory -> SlackAccessory -> Bool)
-> (SlackAccessory -> SlackAccessory -> Bool) -> Eq SlackAccessory
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackAccessory -> SlackAccessory -> Bool
== :: SlackAccessory -> SlackAccessory -> Bool
$c/= :: SlackAccessory -> SlackAccessory -> Bool
/= :: SlackAccessory -> SlackAccessory -> Bool
Eq)

instance ToJSON SlackAccessory where
  toJSON :: SlackAccessory -> Value
toJSON (SlackButtonAccessory SlackAction
btn) = SlackAction -> Value
forall a. ToJSON a => a -> Value
toJSON SlackAction
btn

instance FromJSON SlackAccessory where
  parseJSON :: Value -> Parser SlackAccessory
parseJSON Value
v = SlackAction -> SlackAccessory
SlackButtonAccessory (SlackAction -> SlackAccessory)
-> Parser SlackAction -> Parser SlackAccessory
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser SlackAction
forall a. FromJSON a => Value -> Parser a
parseJSON Value
v

instance Show SlackAccessory where
  show :: SlackAccessory -> String
show (SlackButtonAccessory SlackAction
btn) = SlackAction -> String
forall a. Show a => a -> String
show SlackAction
btn

-- | Small helper function for constructing a section with a button accessory out of a button and text components
sectionWithButtonAccessory :: SlackAction -> SlackText -> SlackBlock
sectionWithButtonAccessory :: SlackAction -> SlackText -> SlackBlock
sectionWithButtonAccessory SlackAction
btn SlackText
txt =
  SlackSection -> SlackBlock
SlackBlockSection
    (SlackSection -> SlackBlock) -> SlackSection -> SlackBlock
forall a b. (a -> b) -> a -> b
$ (SlackText -> SlackSection
slackSectionWithText SlackText
txt)
      { slackSectionAccessory = Just $ SlackButtonAccessory btn
      }

-- | <https://api.slack.com/reference/block-kit/blocks#section>
data SlackSection = SlackSection
  { SlackSection -> Maybe SlackText
slackSectionText :: Maybe SlackText
  -- ^ May be absent if 'slackSectionFields' is present.
  , SlackSection -> Maybe (NonEmptyText 255)
slackSectionBlockId :: Maybe SlackBlockId
  , SlackSection -> Maybe [SlackText]
slackSectionFields :: Maybe [SlackText]
  -- ^ Required if 'slackSectionText' is not provided.
  , SlackSection -> Maybe SlackAccessory
slackSectionAccessory :: Maybe SlackAccessory
  }
  deriving stock (SlackSection -> SlackSection -> Bool
(SlackSection -> SlackSection -> Bool)
-> (SlackSection -> SlackSection -> Bool) -> Eq SlackSection
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackSection -> SlackSection -> Bool
== :: SlackSection -> SlackSection -> Bool
$c/= :: SlackSection -> SlackSection -> Bool
/= :: SlackSection -> SlackSection -> Bool
Eq, Int -> SlackSection -> ShowS
[SlackSection] -> ShowS
SlackSection -> String
(Int -> SlackSection -> ShowS)
-> (SlackSection -> String)
-> ([SlackSection] -> ShowS)
-> Show SlackSection
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackSection -> ShowS
showsPrec :: Int -> SlackSection -> ShowS
$cshow :: SlackSection -> String
show :: SlackSection -> String
$cshowList :: [SlackSection] -> ShowS
showList :: [SlackSection] -> ShowS
Show)

slackSectionWithText :: SlackText -> SlackSection
slackSectionWithText :: SlackText -> SlackSection
slackSectionWithText SlackText
t =
  SlackSection
    { slackSectionText :: Maybe SlackText
slackSectionText = SlackText -> Maybe SlackText
forall a. a -> Maybe a
Just SlackText
t
    , slackSectionBlockId :: Maybe (NonEmptyText 255)
slackSectionBlockId = Maybe (NonEmptyText 255)
forall a. Maybe a
Nothing
    , slackSectionFields :: Maybe [SlackText]
slackSectionFields = Maybe [SlackText]
forall a. Maybe a
Nothing
    , slackSectionAccessory :: Maybe SlackAccessory
slackSectionAccessory = Maybe SlackAccessory
forall a. Maybe a
Nothing
    }

data SlackBlock
  = SlackBlockSection SlackSection
  | SlackBlockImage SlackImage
  | SlackBlockContext SlackContext
  | SlackBlockDivider
  | SlackBlockRichText RichText
  | SlackBlockActions (Maybe SlackBlockId) SlackActionList -- 1 to 5 elements
  | SlackBlockHeader SlackPlainTextOnly -- max length 150
  deriving stock (SlackBlock -> SlackBlock -> Bool
(SlackBlock -> SlackBlock -> Bool)
-> (SlackBlock -> SlackBlock -> Bool) -> Eq SlackBlock
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackBlock -> SlackBlock -> Bool
== :: SlackBlock -> SlackBlock -> Bool
$c/= :: SlackBlock -> SlackBlock -> Bool
/= :: SlackBlock -> SlackBlock -> Bool
Eq)

instance Show SlackBlock where
  show :: SlackBlock -> String
show (SlackBlockSection SlackSection
section) = SlackSection -> String
forall a. Show a => a -> String
show SlackSection
section
  show (SlackBlockImage SlackImage
i) = SlackImage -> String
forall a. Show a => a -> String
show SlackImage
i
  show (SlackBlockContext SlackContext
contents) = SlackContext -> String
forall a. Show a => a -> String
show SlackContext
contents
  show SlackBlock
SlackBlockDivider = String
"|"
  show (SlackBlockActions Maybe (NonEmptyText 255)
mBlockId SlackActionList
as) =
    ShowS
forall a. Show a => a -> String
show
      ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall a. Monoid a => [a] -> a
mconcat
        [ String
"actions("
        , Maybe (NonEmptyText 255) -> String
forall a. Show a => a -> String
show Maybe (NonEmptyText 255)
mBlockId
        , String
") = ["
        , ShowS
forall a. Show a => a -> String
show ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ Element [String] -> [String] -> Element [String]
forall mono.
(MonoFoldable mono, Monoid (Element mono)) =>
Element mono -> mono -> Element mono
intercalate String
Element [String]
", " ((SlackAction -> String) -> [SlackAction] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map SlackAction -> String
forall a. Show a => a -> String
show (Refined SlackActionListConstraints [SlackAction] -> [SlackAction]
forall {k} (p :: k) x. Refined p x -> x
unrefine (Refined SlackActionListConstraints [SlackAction] -> [SlackAction])
-> Refined SlackActionListConstraints [SlackAction]
-> [SlackAction]
forall a b. (a -> b) -> a -> b
$ SlackActionList -> Refined SlackActionListConstraints [SlackAction]
unSlackActionList SlackActionList
as))
        , String
"]"
        ]
  show (SlackBlockRichText RichText
rt) = RichText -> String
forall a. Show a => a -> String
show RichText
rt
  show (SlackBlockHeader SlackPlainTextOnly
p) = SlackPlainTextOnly -> String
forall a. Show a => a -> String
show SlackPlainTextOnly
p

instance ToJSON SlackBlock where
  toJSON :: SlackBlock -> Value
toJSON (SlackBlockSection SlackSection {Maybe [SlackText]
Maybe (NonEmptyText 255)
Maybe SlackText
Maybe SlackAccessory
slackSectionAccessory :: SlackSection -> Maybe SlackAccessory
slackSectionText :: SlackSection -> Maybe SlackText
slackSectionFields :: SlackSection -> Maybe [SlackText]
slackSectionBlockId :: SlackSection -> Maybe (NonEmptyText 255)
slackSectionText :: Maybe SlackText
slackSectionBlockId :: Maybe (NonEmptyText 255)
slackSectionFields :: Maybe [SlackText]
slackSectionAccessory :: Maybe SlackAccessory
..}) =
    [Maybe Pair] -> Value
objectOptional
      [ Key
"type" Key -> Text -> Maybe Pair
forall v. ToJSON v => Key -> v -> Maybe Pair
.=! (Text
"section" :: Text)
      , Key
"text" Key -> Maybe SlackContent -> Maybe Pair
forall v. ToJSON v => Key -> Maybe v -> Maybe Pair
.=? (SlackText -> SlackContent
SlackContentText (SlackText -> SlackContent)
-> Maybe SlackText -> Maybe SlackContent
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe SlackText
slackSectionText)
      , Key
"block_id" Key -> Maybe (NonEmptyText 255) -> Maybe Pair
forall v. ToJSON v => Key -> Maybe v -> Maybe Pair
.=? Maybe (NonEmptyText 255)
slackSectionBlockId
      , Key
"fields" Key -> Maybe [SlackContent] -> Maybe Pair
forall v. ToJSON v => Key -> Maybe v -> Maybe Pair
.=? ((SlackText -> SlackContent) -> [SlackText] -> [SlackContent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map SlackText -> SlackContent
SlackContentText ([SlackText] -> [SlackContent])
-> Maybe [SlackText] -> Maybe [SlackContent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe [SlackText]
slackSectionFields)
      , Key
"accessory" Key -> Maybe SlackAccessory -> Maybe Pair
forall v. ToJSON v => Key -> Maybe v -> Maybe Pair
.=? Maybe SlackAccessory
slackSectionAccessory
      ]
  toJSON (SlackBlockImage SlackImage
i) = SlackContent -> Value
forall a. ToJSON a => a -> Value
toJSON (SlackImage -> SlackContent
SlackContentImage SlackImage
i)
  toJSON (SlackBlockContext SlackContext
contents) =
    [Pair] -> Value
object
      [ Key
"type" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (Text
"context" :: Text)
      , Key
"elements" Key -> SlackContext -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= SlackContext
contents
      ]
  toJSON SlackBlock
SlackBlockDivider =
    [Pair] -> Value
object
      [ Key
"type" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (Text
"divider" :: Text)
      ]
  toJSON (SlackBlockActions Maybe (NonEmptyText 255)
mBlockId SlackActionList
as) =
    [Maybe Pair] -> Value
objectOptional
      [ Key
"type" Key -> Text -> Maybe Pair
forall v. ToJSON v => Key -> v -> Maybe Pair
.=! (Text
"actions" :: Text)
      , Key
"block_id" Key -> Maybe (NonEmptyText 255) -> Maybe Pair
forall v. ToJSON v => Key -> Maybe v -> Maybe Pair
.=? Maybe (NonEmptyText 255)
mBlockId
      , Key
"elements" Key -> SlackActionList -> Maybe Pair
forall v. ToJSON v => Key -> v -> Maybe Pair
.=! SlackActionList
as
      ]
  -- FIXME(jadel): should this be an error? Slack doesn't accept these
  toJSON (SlackBlockRichText RichText
_) =
    [Pair] -> Value
object []
  toJSON (SlackBlockHeader SlackPlainTextOnly
slackPlainText) =
    [Pair] -> Value
object
      [ Key
"type" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (Text
"header" :: Text)
      , Key
"text" Key -> SlackPlainTextOnly -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= SlackPlainTextOnly
slackPlainText
      ]

instance FromJSON SlackBlock where
  parseJSON :: Value -> Parser SlackBlock
parseJSON = String
-> (Object -> Parser SlackBlock) -> Value -> Parser SlackBlock
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlackBlock" ((Object -> Parser SlackBlock) -> Value -> Parser SlackBlock)
-> (Object -> Parser SlackBlock) -> Value -> Parser SlackBlock
forall a b. (a -> b) -> a -> b
$ \Object
obj -> do
    (Text
slackBlockType :: Text) <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
    case Text
slackBlockType of
      Text
"section" -> do
        Maybe SlackContent
slackSectionTextContent <- Object
obj Object -> Key -> Parser (Maybe SlackContent)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"text"
        let slackSectionText :: Maybe SlackText
slackSectionText = Maybe SlackContent
slackSectionTextContent Maybe SlackContent
-> (SlackContent -> Maybe SlackText) -> Maybe SlackText
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= SlackContent -> Maybe SlackText
slackContentToSlackText
        Maybe (NonEmptyText 255)
slackSectionBlockId <- Object
obj Object -> Key -> Parser (Maybe (NonEmptyText 255))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"block_id"
        Maybe [SlackContent]
slackSectionFieldsContent <- Object
obj Object -> Key -> Parser (Maybe [SlackContent])
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"fields"
        let slackSectionFields :: Maybe [SlackText]
slackSectionFields = Maybe [SlackContent]
slackSectionFieldsContent Maybe [SlackContent]
-> ([SlackContent] -> Maybe [SlackText]) -> Maybe [SlackText]
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (SlackContent -> Maybe SlackText)
-> [SlackContent] -> Maybe [SlackText]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse SlackContent -> Maybe SlackText
slackContentToSlackText
        (Maybe Value
slackSectionAccessoryValue :: Maybe Value) <- Object
obj Object -> Key -> Parser (Maybe Value)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"accessory"
        -- The section accessory can be any block element but `SlackAcessory`
        -- only implements button.
        let slackSectionAccessory :: Maybe SlackAccessory
slackSectionAccessory =
              Maybe Value
slackSectionAccessoryValue Maybe Value
-> (Value -> Maybe SlackAccessory) -> Maybe SlackAccessory
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Value
v ->
                case Value -> Result SlackAccessory
forall a. FromJSON a => Value -> Result a
fromJSON Value
v of
                  Error String
_ ->
                    Maybe SlackAccessory
forall a. Maybe a
Nothing
                  Success SlackAccessory
slackAccessory ->
                    SlackAccessory -> Maybe SlackAccessory
forall a. a -> Maybe a
Just SlackAccessory
slackAccessory
        pure $ SlackSection -> SlackBlock
SlackBlockSection SlackSection {Maybe [SlackText]
Maybe (NonEmptyText 255)
Maybe SlackText
Maybe SlackAccessory
slackSectionAccessory :: Maybe SlackAccessory
slackSectionText :: Maybe SlackText
slackSectionFields :: Maybe [SlackText]
slackSectionBlockId :: Maybe (NonEmptyText 255)
slackSectionText :: Maybe SlackText
slackSectionBlockId :: Maybe (NonEmptyText 255)
slackSectionFields :: Maybe [SlackText]
slackSectionAccessory :: Maybe SlackAccessory
..}
      Text
"context" -> do
        SlackContext
slackContent <- Object
obj Object -> Key -> Parser SlackContext
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"elements"
        pure $ SlackContext -> SlackBlock
SlackBlockContext SlackContext
slackContent
      Text
"image" -> do
        SlackContentImage SlackImage
i <- Value -> Parser SlackContent
forall a. FromJSON a => Value -> Parser a
parseJSON (Value -> Parser SlackContent) -> Value -> Parser SlackContent
forall a b. (a -> b) -> a -> b
$ Object -> Value
Object Object
obj
        SlackBlock -> Parser SlackBlock
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SlackBlock -> Parser SlackBlock)
-> SlackBlock -> Parser SlackBlock
forall a b. (a -> b) -> a -> b
$ SlackImage -> SlackBlock
SlackBlockImage SlackImage
i
      Text
"divider" -> SlackBlock -> Parser SlackBlock
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SlackBlock
SlackBlockDivider
      Text
"actions" -> do
        SlackActionList
slackActions <- Object
obj Object -> Key -> Parser SlackActionList
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"elements"
        Maybe (NonEmptyText 255)
mBlockId <- Object
obj Object -> Key -> Parser (Maybe (NonEmptyText 255))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"block_id"
        pure $ Maybe (NonEmptyText 255) -> SlackActionList -> SlackBlock
SlackBlockActions Maybe (NonEmptyText 255)
mBlockId SlackActionList
slackActions
      Text
"rich_text" -> do
        [RichTextSectionItem]
elements <- Object
obj Object -> Key -> Parser [RichTextSectionItem]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"elements"
        Maybe (NonEmptyText 255)
mBlockId <- Object
obj Object -> Key -> Parser (Maybe (NonEmptyText 255))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"block_id"
        SlackBlock -> Parser SlackBlock
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
          (SlackBlock -> Parser SlackBlock)
-> (RichText -> SlackBlock) -> RichText -> Parser SlackBlock
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
. RichText -> SlackBlock
SlackBlockRichText
          (RichText -> Parser SlackBlock) -> RichText -> Parser SlackBlock
forall a b. (a -> b) -> a -> b
$ RichText
            { blockId :: Maybe (NonEmptyText 255)
blockId = Maybe (NonEmptyText 255)
mBlockId
            , [RichTextSectionItem]
elements :: [RichTextSectionItem]
elements :: [RichTextSectionItem]
elements
            }
      Text
"header" -> do
        (Value
headerContentObj :: Value) <- Object
obj Object -> Key -> Parser Value
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
        SlackPlainTextOnly
headerContentText <- Value -> Parser SlackPlainTextOnly
forall a. FromJSON a => Value -> Parser a
parseJSON Value
headerContentObj
        pure $ SlackPlainTextOnly -> SlackBlock
SlackBlockHeader SlackPlainTextOnly
headerContentText
      Text
_ -> String -> Parser SlackBlock
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Unknown SlackBlock type, must be one of ['section', 'context', 'image', 'divider', 'actions', 'rich_text', 'header']"

newtype SlackMessage = SlackMessage [SlackBlock]
  deriving newtype (NonEmpty SlackMessage -> SlackMessage
SlackMessage -> SlackMessage -> SlackMessage
(SlackMessage -> SlackMessage -> SlackMessage)
-> (NonEmpty SlackMessage -> SlackMessage)
-> (forall b. Integral b => b -> SlackMessage -> SlackMessage)
-> Semigroup SlackMessage
forall b. Integral b => b -> SlackMessage -> SlackMessage
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: SlackMessage -> SlackMessage -> SlackMessage
<> :: SlackMessage -> SlackMessage -> SlackMessage
$csconcat :: NonEmpty SlackMessage -> SlackMessage
sconcat :: NonEmpty SlackMessage -> SlackMessage
$cstimes :: forall b. Integral b => b -> SlackMessage -> SlackMessage
stimes :: forall b. Integral b => b -> SlackMessage -> SlackMessage
Semigroup, Semigroup SlackMessage
SlackMessage
Semigroup SlackMessage =>
SlackMessage
-> (SlackMessage -> SlackMessage -> SlackMessage)
-> ([SlackMessage] -> SlackMessage)
-> Monoid SlackMessage
[SlackMessage] -> SlackMessage
SlackMessage -> SlackMessage -> SlackMessage
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: SlackMessage
mempty :: SlackMessage
$cmappend :: SlackMessage -> SlackMessage -> SlackMessage
mappend :: SlackMessage -> SlackMessage -> SlackMessage
$cmconcat :: [SlackMessage] -> SlackMessage
mconcat :: [SlackMessage] -> SlackMessage
Monoid, SlackMessage -> SlackMessage -> Bool
(SlackMessage -> SlackMessage -> Bool)
-> (SlackMessage -> SlackMessage -> Bool) -> Eq SlackMessage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackMessage -> SlackMessage -> Bool
== :: SlackMessage -> SlackMessage -> Bool
$c/= :: SlackMessage -> SlackMessage -> Bool
/= :: SlackMessage -> SlackMessage -> Bool
Eq)

instance Show SlackMessage where
  show :: SlackMessage -> String
show (SlackMessage [SlackBlock]
arr) = Element [String] -> [String] -> Element [String]
forall mono.
(MonoFoldable mono, Monoid (Element mono)) =>
Element mono -> mono -> Element mono
intercalate String
Element [String]
" " ((SlackBlock -> String) -> [SlackBlock] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map SlackBlock -> String
forall a. Show a => a -> String
show [SlackBlock]
arr)

instance ToJSON SlackMessage where
  toJSON :: SlackMessage -> Value
toJSON (SlackMessage [SlackBlock]
arr) = [SlackBlock] -> Value
forall a. ToJSON a => a -> Value
toJSON [SlackBlock]
arr

instance FromJSON SlackMessage where
  parseJSON :: Value -> Parser SlackMessage
parseJSON = String
-> (Array -> Parser SlackMessage) -> Value -> Parser SlackMessage
forall a. String -> (Array -> Parser a) -> Value -> Parser a
withArray String
"SlackMessage" ((Array -> Parser SlackMessage) -> Value -> Parser SlackMessage)
-> (Array -> Parser SlackMessage) -> Value -> Parser SlackMessage
forall a b. (a -> b) -> a -> b
$ \Array
arr -> do
    (Vector SlackBlock
parsedAsArrayOfSlackBlocks :: V.Vector SlackBlock) <- (Value -> Parser SlackBlock) -> Array -> Parser (Vector SlackBlock)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Vector a -> f (Vector b)
traverse Value -> Parser SlackBlock
forall a. FromJSON a => Value -> Parser a
parseJSON Array
arr
    let slackBlockList :: [SlackBlock]
slackBlockList = Vector SlackBlock -> [SlackBlock]
forall a. Vector a -> [a]
V.toList Vector SlackBlock
parsedAsArrayOfSlackBlocks
    SlackMessage -> Parser SlackMessage
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SlackMessage -> Parser SlackMessage)
-> SlackMessage -> Parser SlackMessage
forall a b. (a -> b) -> a -> b
$ [SlackBlock] -> SlackMessage
SlackMessage [SlackBlock]
slackBlockList

textToMessage :: Text -> SlackMessage
textToMessage :: Text -> SlackMessage
textToMessage = SlackText -> SlackMessage
forall a. Markdown a => SlackText -> a
markdown (SlackText -> SlackMessage)
-> (Text -> SlackText) -> Text -> SlackMessage
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
. Text -> SlackText
forall a. Slack a => a -> SlackText
message

class Markdown a where
  markdown :: SlackText -> a

instance Markdown SlackMessage where
  markdown :: SlackText -> SlackMessage
markdown SlackText
t = [SlackBlock] -> SlackMessage
SlackMessage [SlackSection -> SlackBlock
SlackBlockSection (SlackText -> SlackSection
slackSectionWithText SlackText
t)]

instance Markdown SlackContext where
  markdown :: SlackText -> SlackContext
markdown SlackText
t = [SlackContent] -> SlackContext
SlackContext [SlackText -> SlackContent
SlackContentText SlackText
t]

class Image a where
  image :: SlackImage -> a

instance Image SlackMessage where
  image :: SlackImage -> SlackMessage
image SlackImage
i = [SlackBlock] -> SlackMessage
SlackMessage [SlackImage -> SlackBlock
SlackBlockImage SlackImage
i]

instance Image SlackContext where
  image :: SlackImage -> SlackContext
image SlackImage
i = [SlackContent] -> SlackContext
SlackContext [SlackImage -> SlackContent
SlackContentImage SlackImage
i]

context :: SlackContext -> SlackMessage
context :: SlackContext -> SlackMessage
context SlackContext
c = [SlackBlock] -> SlackMessage
SlackMessage [SlackContext -> SlackBlock
SlackBlockContext SlackContext
c]

textToContext :: Text -> SlackMessage
textToContext :: Text -> SlackMessage
textToContext = SlackContext -> SlackMessage
context (SlackContext -> SlackMessage)
-> (Text -> SlackContext) -> Text -> SlackMessage
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
. SlackText -> SlackContext
forall a. Markdown a => SlackText -> a
markdown (SlackText -> SlackContext)
-> (Text -> SlackText) -> Text -> SlackContext
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
. Text -> SlackText
forall a. Slack a => a -> SlackText
message

-- | Generates interactive components such as buttons.
actions :: (ToSlackActionList as) => as -> SlackMessage
actions :: forall as. ToSlackActionList as => as -> SlackMessage
actions as
as = [SlackBlock] -> SlackMessage
SlackMessage [Maybe (NonEmptyText 255) -> SlackActionList -> SlackBlock
SlackBlockActions Maybe (NonEmptyText 255)
forall a. Maybe a
Nothing (SlackActionList -> SlackBlock) -> SlackActionList -> SlackBlock
forall a b. (a -> b) -> a -> b
$ as -> SlackActionList
forall a. ToSlackActionList a => a -> SlackActionList
toSlackActionList as
as]

-- | Generates interactive components such as buttons with a 'SlackBlockId'.
actionsWithBlockId :: (ToSlackActionList as) => SlackBlockId -> as -> SlackMessage
actionsWithBlockId :: forall as.
ToSlackActionList as =>
NonEmptyText 255 -> as -> SlackMessage
actionsWithBlockId NonEmptyText 255
slackBlockId as
as = [SlackBlock] -> SlackMessage
SlackMessage [Maybe (NonEmptyText 255) -> SlackActionList -> SlackBlock
SlackBlockActions (NonEmptyText 255 -> Maybe (NonEmptyText 255)
forall a. a -> Maybe a
Just NonEmptyText 255
slackBlockId) (SlackActionList -> SlackBlock) -> SlackActionList -> SlackBlock
forall a b. (a -> b) -> a -> b
$ as -> SlackActionList
forall a. ToSlackActionList a => a -> SlackActionList
toSlackActionList as
as]

-- | Settings for [button elements](https://api.slack.com/reference/block-kit/block-elements#button).
data ButtonSettings = ButtonSettings
  { ButtonSettings -> OptionalSetting (NonEmptyText 3000)
buttonUrl :: OptionalSetting (NonEmptyText 3000)
  -- ^ Optional URL to load into the user's browser.
  -- However, Slack will still call the webhook and you must send an acknowledgement response.
  , ButtonSettings -> OptionalSetting (NonEmptyText 2000)
buttonValue :: OptionalSetting (NonEmptyText 2000)
  -- ^ Optional value to send with the interaction payload.
  -- One commoon use is to send state via JSON encoding.
  , ButtonSettings -> OptionalSetting SlackStyle
buttonStyle :: OptionalSetting SlackStyle
  -- ^ Optional 'SlackStyle'. If not provided, uses the default style which is a black button.
  , ButtonSettings -> OptionalSetting SlackConfirmObject
buttonConfirm :: OptionalSetting SlackConfirmObject
  -- ^ An optional confirmation dialog to display.
  }

-- | Default button settings.
buttonSettings :: ButtonSettings
buttonSettings :: ButtonSettings
buttonSettings =
  ButtonSettings
    { buttonUrl :: OptionalSetting (NonEmptyText 3000)
buttonUrl = OptionalSetting (NonEmptyText 3000)
forall a. OptionalSetting a
emptySetting
    , buttonValue :: OptionalSetting (NonEmptyText 2000)
buttonValue = OptionalSetting (NonEmptyText 2000)
forall a. OptionalSetting a
emptySetting
    , buttonStyle :: OptionalSetting SlackStyle
buttonStyle = OptionalSetting SlackStyle
forall a. OptionalSetting a
emptySetting
    , buttonConfirm :: OptionalSetting SlackConfirmObject
buttonConfirm = OptionalSetting SlackConfirmObject
forall a. OptionalSetting a
emptySetting
    }

-- | Button builder.
button :: SlackActionId -> SlackButtonText -> ButtonSettings -> SlackAction
button :: SlackActionId -> SlackButtonText -> ButtonSettings -> SlackAction
button SlackActionId
actionId SlackButtonText
buttonText ButtonSettings {OptionalSetting (NonEmptyText 2000)
OptionalSetting (NonEmptyText 3000)
OptionalSetting SlackStyle
OptionalSetting SlackConfirmObject
buttonUrl :: ButtonSettings -> OptionalSetting (NonEmptyText 3000)
buttonValue :: ButtonSettings -> OptionalSetting (NonEmptyText 2000)
buttonStyle :: ButtonSettings -> OptionalSetting SlackStyle
buttonConfirm :: ButtonSettings -> OptionalSetting SlackConfirmObject
buttonUrl :: OptionalSetting (NonEmptyText 3000)
buttonValue :: OptionalSetting (NonEmptyText 2000)
buttonStyle :: OptionalSetting SlackStyle
buttonConfirm :: OptionalSetting SlackConfirmObject
..} =
  SlackActionId -> SlackActionComponent -> SlackAction
SlackAction SlackActionId
actionId
    (SlackActionComponent -> SlackAction)
-> SlackActionComponent -> SlackAction
forall a b. (a -> b) -> a -> b
$ SlackButton
      { slackButtonText :: SlackButtonText
slackButtonText = SlackButtonText
buttonText
      , slackButtonUrl :: Maybe (NonEmptyText 3000)
slackButtonUrl = OptionalSetting (NonEmptyText 3000) -> Maybe (NonEmptyText 3000)
forall a. OptionalSetting a -> Maybe a
unOptionalSetting OptionalSetting (NonEmptyText 3000)
buttonUrl
      , slackButtonValue :: Maybe (NonEmptyText 2000)
slackButtonValue = OptionalSetting (NonEmptyText 2000) -> Maybe (NonEmptyText 2000)
forall a. OptionalSetting a -> Maybe a
unOptionalSetting OptionalSetting (NonEmptyText 2000)
buttonValue
      , slackButtonStyle :: Maybe SlackStyle
slackButtonStyle = OptionalSetting SlackStyle -> Maybe SlackStyle
forall a. OptionalSetting a -> Maybe a
unOptionalSetting OptionalSetting SlackStyle
buttonStyle
      , slackButtonConfirm :: Maybe SlackConfirmObject
slackButtonConfirm = OptionalSetting SlackConfirmObject -> Maybe SlackConfirmObject
forall a. OptionalSetting a -> Maybe a
unOptionalSetting OptionalSetting SlackConfirmObject
buttonConfirm
      }

-- | A divider block.
-- https://api.slack.com/reference/block-kit/blocks#divider
--
-- @since 1.6.2.0
divider :: SlackMessage
divider :: SlackMessage
divider = [SlackBlock] -> SlackMessage
SlackMessage [SlackBlock
SlackBlockDivider]

-- | Settings for [confirmation dialog objects](https://api.slack.com/reference/block-kit/composition-objects#confirm).
data ConfirmSettings = ConfirmSettings
  { ConfirmSettings -> Text
confirmTitle :: Text
  -- ^ Plain text title for the dialog window. Max length 100 characters.
  , ConfirmSettings -> Text
confirmText :: Text
  -- ^ Markdown explanatory text that appears in the confirm dialog.
  -- Max length is 300 characters.
  , ConfirmSettings -> Text
confirmConfirm :: Text
  -- ^ Plain text to display in the \"confirm\" button.
  -- Max length is 30 characters.
  , ConfirmSettings -> Text
confirmDeny :: Text
  -- ^ Plain text to display in the \"deny\" button.
  -- Max length is 30 characters.
  , ConfirmSettings -> OptionalSetting SlackStyle
confirmStyle :: OptionalSetting SlackStyle
  -- ^ Optional 'SlackStyle' to use for the \"confirm\" button.
  }

-- | Default settings for a \"Are you sure?\" confirmation dialog.
confirmAreYouSure :: ConfirmSettings
confirmAreYouSure :: ConfirmSettings
confirmAreYouSure =
  ConfirmSettings
    { confirmTitle :: Text
confirmTitle = Text
"Are You Sure?"
    , confirmText :: Text
confirmText = Text
"Are you sure you wish to perform this operation?"
    , confirmConfirm :: Text
confirmConfirm = Text
"Yes"
    , confirmDeny :: Text
confirmDeny = Text
"No"
    , confirmStyle :: OptionalSetting SlackStyle
confirmStyle = OptionalSetting SlackStyle
forall a. OptionalSetting a
emptySetting
    }

-- | Confirm dialog builder.
confirm :: ConfirmSettings -> SlackConfirmObject
confirm :: ConfirmSettings -> SlackConfirmObject
confirm ConfirmSettings {Text
OptionalSetting SlackStyle
confirmTitle :: ConfirmSettings -> Text
confirmText :: ConfirmSettings -> Text
confirmConfirm :: ConfirmSettings -> Text
confirmDeny :: ConfirmSettings -> Text
confirmStyle :: ConfirmSettings -> OptionalSetting SlackStyle
confirmTitle :: Text
confirmText :: Text
confirmConfirm :: Text
confirmDeny :: Text
confirmStyle :: OptionalSetting SlackStyle
..} =
  SlackConfirmObject
    { slackConfirmTitle :: SlackPlainTextOnly
slackConfirmTitle = Text -> SlackPlainTextOnly
forall a. Slack a => a -> SlackPlainTextOnly
plaintextonly Text
confirmTitle
    , slackConfirmText :: SlackTextObject
slackConfirmText = Text -> SlackTextObject
forall a. Slack a => a -> SlackTextObject
mrkdwn Text
confirmText
    , slackConfirmConfirm :: SlackPlainTextOnly
slackConfirmConfirm = Text -> SlackPlainTextOnly
forall a. Slack a => a -> SlackPlainTextOnly
plaintextonly Text
confirmConfirm
    , slackConfirmDeny :: SlackPlainTextOnly
slackConfirmDeny = Text -> SlackPlainTextOnly
forall a. Slack a => a -> SlackPlainTextOnly
plaintextonly Text
confirmDeny
    , slackConfirmStyle :: Maybe SlackStyle
slackConfirmStyle = OptionalSetting SlackStyle -> Maybe SlackStyle
forall a. OptionalSetting a -> Maybe a
unOptionalSetting OptionalSetting SlackStyle
confirmStyle
    }

-- | 'SlackBlockId' should be unique for each message and each iteration
-- of a message. If a message is updated, use a new block_id.
type SlackBlockId = NonEmptyText 255

-- | All Slack Actions must have a 'SlackActionId' and one 'SlackActionComponent' (such as a button).
data SlackAction = SlackAction SlackActionId SlackActionComponent
  deriving stock (SlackAction -> SlackAction -> Bool
(SlackAction -> SlackAction -> Bool)
-> (SlackAction -> SlackAction -> Bool) -> Eq SlackAction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackAction -> SlackAction -> Bool
== :: SlackAction -> SlackAction -> Bool
$c/= :: SlackAction -> SlackAction -> Bool
/= :: SlackAction -> SlackAction -> Bool
Eq)

instance Show SlackAction where
  show :: SlackAction -> String
show (SlackAction SlackActionId
actionId SlackActionComponent
component) = SlackActionId -> String
forall a. Show a => a -> String
show SlackActionId
actionId String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> SlackActionComponent -> String
forall a. Show a => a -> String
show SlackActionComponent
component

-- | [Confirm dialog object](https://api.slack.com/reference/block-kit/composition-objects#confirm).
data SlackConfirmObject = SlackConfirmObject
  { SlackConfirmObject -> SlackPlainTextOnly
slackConfirmTitle :: SlackPlainTextOnly -- max length 100
  , SlackConfirmObject -> SlackTextObject
slackConfirmText :: SlackTextObject -- max length 300
  , SlackConfirmObject -> SlackPlainTextOnly
slackConfirmConfirm :: SlackPlainTextOnly -- max length 30
  , SlackConfirmObject -> SlackPlainTextOnly
slackConfirmDeny :: SlackPlainTextOnly -- max length 30
  , SlackConfirmObject -> Maybe SlackStyle
slackConfirmStyle :: Maybe SlackStyle
  }
  deriving stock (SlackConfirmObject -> SlackConfirmObject -> Bool
(SlackConfirmObject -> SlackConfirmObject -> Bool)
-> (SlackConfirmObject -> SlackConfirmObject -> Bool)
-> Eq SlackConfirmObject
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackConfirmObject -> SlackConfirmObject -> Bool
== :: SlackConfirmObject -> SlackConfirmObject -> Bool
$c/= :: SlackConfirmObject -> SlackConfirmObject -> Bool
/= :: SlackConfirmObject -> SlackConfirmObject -> Bool
Eq, Int -> SlackConfirmObject -> ShowS
[SlackConfirmObject] -> ShowS
SlackConfirmObject -> String
(Int -> SlackConfirmObject -> ShowS)
-> (SlackConfirmObject -> String)
-> ([SlackConfirmObject] -> ShowS)
-> Show SlackConfirmObject
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackConfirmObject -> ShowS
showsPrec :: Int -> SlackConfirmObject -> ShowS
$cshow :: SlackConfirmObject -> String
show :: SlackConfirmObject -> String
$cshowList :: [SlackConfirmObject] -> ShowS
showList :: [SlackConfirmObject] -> ShowS
Show)

instance ToJSON SlackConfirmObject where
  toJSON :: SlackConfirmObject -> Value
toJSON SlackConfirmObject {Maybe SlackStyle
SlackTextObject
SlackPlainTextOnly
slackConfirmTitle :: SlackConfirmObject -> SlackPlainTextOnly
slackConfirmText :: SlackConfirmObject -> SlackTextObject
slackConfirmConfirm :: SlackConfirmObject -> SlackPlainTextOnly
slackConfirmDeny :: SlackConfirmObject -> SlackPlainTextOnly
slackConfirmStyle :: SlackConfirmObject -> Maybe SlackStyle
slackConfirmTitle :: SlackPlainTextOnly
slackConfirmText :: SlackTextObject
slackConfirmConfirm :: SlackPlainTextOnly
slackConfirmDeny :: SlackPlainTextOnly
slackConfirmStyle :: Maybe SlackStyle
..} =
    [Maybe Pair] -> Value
objectOptional
      [ Key
"title" Key -> SlackPlainTextOnly -> Maybe Pair
forall v. ToJSON v => Key -> v -> Maybe Pair
.=! SlackPlainTextOnly
slackConfirmTitle
      , Key
"text" Key -> SlackTextObject -> Maybe Pair
forall v. ToJSON v => Key -> v -> Maybe Pair
.=! SlackTextObject
slackConfirmText
      , Key
"confirm" Key -> SlackPlainTextOnly -> Maybe Pair
forall v. ToJSON v => Key -> v -> Maybe Pair
.=! SlackPlainTextOnly
slackConfirmConfirm
      , Key
"deny" Key -> SlackPlainTextOnly -> Maybe Pair
forall v. ToJSON v => Key -> v -> Maybe Pair
.=! SlackPlainTextOnly
slackConfirmDeny
      , Key
"style" Key -> Maybe SlackStyle -> Maybe Pair
forall v. ToJSON v => Key -> Maybe v -> Maybe Pair
.=? Maybe SlackStyle
slackConfirmStyle
      ]

instance FromJSON SlackConfirmObject where
  parseJSON :: Value -> Parser SlackConfirmObject
parseJSON = String
-> (Object -> Parser SlackConfirmObject)
-> Value
-> Parser SlackConfirmObject
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlackConfirmObject" ((Object -> Parser SlackConfirmObject)
 -> Value -> Parser SlackConfirmObject)
-> (Object -> Parser SlackConfirmObject)
-> Value
-> Parser SlackConfirmObject
forall a b. (a -> b) -> a -> b
$ \Object
obj -> do
    SlackPlainTextOnly
slackConfirmTitle <- Object
obj Object -> Key -> Parser SlackPlainTextOnly
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"title"
    SlackTextObject
slackConfirmText <- Object
obj Object -> Key -> Parser SlackTextObject
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
    SlackPlainTextOnly
slackConfirmConfirm <- Object
obj Object -> Key -> Parser SlackPlainTextOnly
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"confirm"
    SlackPlainTextOnly
slackConfirmDeny <- Object
obj Object -> Key -> Parser SlackPlainTextOnly
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"deny"
    Maybe SlackStyle
slackConfirmStyle <- Object
obj Object -> Key -> Parser (Maybe SlackStyle)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"style"
    pure SlackConfirmObject {Maybe SlackStyle
SlackTextObject
SlackPlainTextOnly
slackConfirmTitle :: SlackPlainTextOnly
slackConfirmText :: SlackTextObject
slackConfirmConfirm :: SlackPlainTextOnly
slackConfirmDeny :: SlackPlainTextOnly
slackConfirmStyle :: Maybe SlackStyle
slackConfirmTitle :: SlackPlainTextOnly
slackConfirmText :: SlackTextObject
slackConfirmConfirm :: SlackPlainTextOnly
slackConfirmDeny :: SlackPlainTextOnly
slackConfirmStyle :: Maybe SlackStyle
..}

newtype SlackResponseUrl = SlackResponseUrl {SlackResponseUrl -> Text
unSlackResponseUrl :: Text}
  deriving stock (SlackResponseUrl -> SlackResponseUrl -> Bool
(SlackResponseUrl -> SlackResponseUrl -> Bool)
-> (SlackResponseUrl -> SlackResponseUrl -> Bool)
-> Eq SlackResponseUrl
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackResponseUrl -> SlackResponseUrl -> Bool
== :: SlackResponseUrl -> SlackResponseUrl -> Bool
$c/= :: SlackResponseUrl -> SlackResponseUrl -> Bool
/= :: SlackResponseUrl -> SlackResponseUrl -> Bool
Eq, Int -> SlackResponseUrl -> ShowS
[SlackResponseUrl] -> ShowS
SlackResponseUrl -> String
(Int -> SlackResponseUrl -> ShowS)
-> (SlackResponseUrl -> String)
-> ([SlackResponseUrl] -> ShowS)
-> Show SlackResponseUrl
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackResponseUrl -> ShowS
showsPrec :: Int -> SlackResponseUrl -> ShowS
$cshow :: SlackResponseUrl -> String
show :: SlackResponseUrl -> String
$cshowList :: [SlackResponseUrl] -> ShowS
showList :: [SlackResponseUrl] -> ShowS
Show)
  deriving newtype (Value -> Parser [SlackResponseUrl]
Value -> Parser SlackResponseUrl
(Value -> Parser SlackResponseUrl)
-> (Value -> Parser [SlackResponseUrl])
-> FromJSON SlackResponseUrl
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
$cparseJSON :: Value -> Parser SlackResponseUrl
parseJSON :: Value -> Parser SlackResponseUrl
$cparseJSONList :: Value -> Parser [SlackResponseUrl]
parseJSONList :: Value -> Parser [SlackResponseUrl]
FromJSON, [SlackResponseUrl] -> Value
[SlackResponseUrl] -> Encoding
SlackResponseUrl -> Value
SlackResponseUrl -> Encoding
(SlackResponseUrl -> Value)
-> (SlackResponseUrl -> Encoding)
-> ([SlackResponseUrl] -> Value)
-> ([SlackResponseUrl] -> Encoding)
-> ToJSON SlackResponseUrl
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
$ctoJSON :: SlackResponseUrl -> Value
toJSON :: SlackResponseUrl -> Value
$ctoEncoding :: SlackResponseUrl -> Encoding
toEncoding :: SlackResponseUrl -> Encoding
$ctoJSONList :: [SlackResponseUrl] -> Value
toJSONList :: [SlackResponseUrl] -> Value
$ctoEncodingList :: [SlackResponseUrl] -> Encoding
toEncodingList :: [SlackResponseUrl] -> Encoding
ToJSON)

-- | Represents the data we get from a callback from Slack for interactive
-- operations. See https://api.slack.com/interactivity/handling#payloads
data SlackInteractivePayload = SlackInteractivePayload
  { SlackInteractivePayload -> Text
sipUserId :: Text
  , SlackInteractivePayload -> Text
sipUsername :: Text
  , SlackInteractivePayload -> Text
sipName :: Text
  , SlackInteractivePayload -> Maybe SlackResponseUrl
sipResponseUrl :: Maybe SlackResponseUrl
  , SlackInteractivePayload -> Maybe Text
sipTriggerId :: Maybe Text
  , SlackInteractivePayload -> [SlackActionResponse]
sipActions :: [SlackActionResponse]
  }
  deriving stock (Int -> SlackInteractivePayload -> ShowS
[SlackInteractivePayload] -> ShowS
SlackInteractivePayload -> String
(Int -> SlackInteractivePayload -> ShowS)
-> (SlackInteractivePayload -> String)
-> ([SlackInteractivePayload] -> ShowS)
-> Show SlackInteractivePayload
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackInteractivePayload -> ShowS
showsPrec :: Int -> SlackInteractivePayload -> ShowS
$cshow :: SlackInteractivePayload -> String
show :: SlackInteractivePayload -> String
$cshowList :: [SlackInteractivePayload] -> ShowS
showList :: [SlackInteractivePayload] -> ShowS
Show)

instance FromJSON SlackInteractivePayload where
  parseJSON :: Value -> Parser SlackInteractivePayload
parseJSON = String
-> (Object -> Parser SlackInteractivePayload)
-> Value
-> Parser SlackInteractivePayload
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlackInteractivePayload" ((Object -> Parser SlackInteractivePayload)
 -> Value -> Parser SlackInteractivePayload)
-> (Object -> Parser SlackInteractivePayload)
-> Value
-> Parser SlackInteractivePayload
forall a b. (a -> b) -> a -> b
$ \Object
obj -> do
    Object
user <- Object
obj Object -> Key -> Parser Object
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"user"
    Text
sipUserId <- Object
user Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id"
    Text
sipUsername <- Object
user Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"username"
    Text
sipName <- Object
user Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
    Maybe SlackResponseUrl
sipResponseUrl <- Object
obj Object -> Key -> Parser (Maybe SlackResponseUrl)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"response_url"
    Maybe Text
sipTriggerId <- Object
obj Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"trigger_id"
    Value
actionsObj <- Object
obj Object -> Key -> Parser Value
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"actions"
    [SlackActionResponse]
sipActions <- Value -> Parser [SlackActionResponse]
forall a. FromJSON a => Value -> Parser a
parseJSON Value
actionsObj
    pure $ SlackInteractivePayload {[SlackActionResponse]
Maybe Text
Maybe SlackResponseUrl
Text
sipUserId :: Text
sipUsername :: Text
sipName :: Text
sipResponseUrl :: Maybe SlackResponseUrl
sipTriggerId :: Maybe Text
sipActions :: [SlackActionResponse]
sipUserId :: Text
sipUsername :: Text
sipName :: Text
sipResponseUrl :: Maybe SlackResponseUrl
sipTriggerId :: Maybe Text
sipActions :: [SlackActionResponse]
..}

-- | Which component and it's IDs that triggered an interactive webhook call.
data SlackActionResponse = SlackActionResponse
  { SlackActionResponse -> NonEmptyText 255
sarBlockId :: SlackBlockId
  , SlackActionResponse -> SlackActionId
sarActionId :: SlackActionId
  , SlackActionResponse -> SlackActionComponent
sarActionComponent :: SlackActionComponent
  }
  deriving stock (Int -> SlackActionResponse -> ShowS
[SlackActionResponse] -> ShowS
SlackActionResponse -> String
(Int -> SlackActionResponse -> ShowS)
-> (SlackActionResponse -> String)
-> ([SlackActionResponse] -> ShowS)
-> Show SlackActionResponse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackActionResponse -> ShowS
showsPrec :: Int -> SlackActionResponse -> ShowS
$cshow :: SlackActionResponse -> String
show :: SlackActionResponse -> String
$cshowList :: [SlackActionResponse] -> ShowS
showList :: [SlackActionResponse] -> ShowS
Show)

instance FromJSON SlackActionResponse where
  parseJSON :: Value -> Parser SlackActionResponse
parseJSON = String
-> (Object -> Parser SlackActionResponse)
-> Value
-> Parser SlackActionResponse
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlackActionResponse" ((Object -> Parser SlackActionResponse)
 -> Value -> Parser SlackActionResponse)
-> (Object -> Parser SlackActionResponse)
-> Value
-> Parser SlackActionResponse
forall a b. (a -> b) -> a -> b
$ \Object
obj -> do
    NonEmptyText 255
sarBlockId <- Object
obj Object -> Key -> Parser (NonEmptyText 255)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"block_id"
    SlackActionId
sarActionId <- Object
obj Object -> Key -> Parser SlackActionId
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"action_id"
    SlackActionComponent
sarActionComponent <- Value -> Parser SlackActionComponent
forall a. FromJSON a => Value -> Parser a
parseJSON (Value -> Parser SlackActionComponent)
-> Value -> Parser SlackActionComponent
forall a b. (a -> b) -> a -> b
$ Object -> Value
Object Object
obj
    pure $ SlackActionResponse {NonEmptyText 255
SlackActionComponent
SlackActionId
sarBlockId :: NonEmptyText 255
sarActionId :: SlackActionId
sarActionComponent :: SlackActionComponent
sarBlockId :: NonEmptyText 255
sarActionId :: SlackActionId
sarActionComponent :: SlackActionComponent
..}

data SlackInteractiveResponseResponse = SlackInteractiveResponseResponse {SlackInteractiveResponseResponse -> Bool
unSlackInteractiveResponseResponse :: Bool}

instance FromJSON SlackInteractiveResponseResponse where
  parseJSON :: Value -> Parser SlackInteractiveResponseResponse
parseJSON = String
-> (Object -> Parser SlackInteractiveResponseResponse)
-> Value
-> Parser SlackInteractiveResponseResponse
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlackInteractiveResponseResponse" ((Object -> Parser SlackInteractiveResponseResponse)
 -> Value -> Parser SlackInteractiveResponseResponse)
-> (Object -> Parser SlackInteractiveResponseResponse)
-> Value
-> Parser SlackInteractiveResponseResponse
forall a b. (a -> b) -> a -> b
$ \Object
obj -> do
    Bool
res <- Object
obj Object -> Key -> Parser Bool
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"ok"
    pure $ Bool -> SlackInteractiveResponseResponse
SlackInteractiveResponseResponse Bool
res

-- | Type of message to send in response to an interactive webhook.
-- See Slack's [Handling user interaction in your Slack apps](https://api.slack.com/interactivity/handling#responses)
-- for a description of these fieldds.
data SlackInteractiveResponse
  = -- | Respond with a new message.
    SlackInteractiveResponse SlackMessage
  | -- | Respond with a message that only the interacting user can usee.
    Ephemeral SlackMessage
  | -- | Replace the original message.
    ReplaceOriginal SlackMessage
  | -- | Delete the original message.
    DeleteOriginal
  deriving stock (Int -> SlackInteractiveResponse -> ShowS
[SlackInteractiveResponse] -> ShowS
SlackInteractiveResponse -> String
(Int -> SlackInteractiveResponse -> ShowS)
-> (SlackInteractiveResponse -> String)
-> ([SlackInteractiveResponse] -> ShowS)
-> Show SlackInteractiveResponse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackInteractiveResponse -> ShowS
showsPrec :: Int -> SlackInteractiveResponse -> ShowS
$cshow :: SlackInteractiveResponse -> String
show :: SlackInteractiveResponse -> String
$cshowList :: [SlackInteractiveResponse] -> ShowS
showList :: [SlackInteractiveResponse] -> ShowS
Show)

instance ToJSON SlackInteractiveResponse where
  toJSON :: SlackInteractiveResponse -> Value
toJSON (SlackInteractiveResponse SlackMessage
msg) = [Pair] -> Value
object [Key
"blocks" Key -> SlackMessage -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= SlackMessage
msg]
  toJSON (Ephemeral SlackMessage
msg) = [Pair] -> Value
object [Key
"blocks" Key -> SlackMessage -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= SlackMessage
msg, Key
"replace_original" Key -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Bool
False, Key
"response_type" Key -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (Text
"ephemeral" :: Text)]
  toJSON (ReplaceOriginal SlackMessage
msg) = [Pair] -> Value
object [Key
"blocks" Key -> SlackMessage -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= SlackMessage
msg, Key
"replace_original" Key -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Bool
True]
  toJSON SlackInteractiveResponse
DeleteOriginal = [Pair] -> Value
object [Key
"delete_original" Key -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Bool
True]

-- | Text to be displayed in a 'SlackButton'.
-- Up to 75 characters, but may be truncated to 30 characters.
newtype SlackButtonText = SlackButtonText (NonEmptyText 75)
  deriving stock (Int -> SlackButtonText -> ShowS
[SlackButtonText] -> ShowS
SlackButtonText -> String
(Int -> SlackButtonText -> ShowS)
-> (SlackButtonText -> String)
-> ([SlackButtonText] -> ShowS)
-> Show SlackButtonText
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlackButtonText -> ShowS
showsPrec :: Int -> SlackButtonText -> ShowS
$cshow :: SlackButtonText -> String
show :: SlackButtonText -> String
$cshowList :: [SlackButtonText] -> ShowS
showList :: [SlackButtonText] -> ShowS
Show)
  deriving newtype (SlackButtonText -> SlackButtonText -> Bool
(SlackButtonText -> SlackButtonText -> Bool)
-> (SlackButtonText -> SlackButtonText -> Bool)
-> Eq SlackButtonText
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackButtonText -> SlackButtonText -> Bool
== :: SlackButtonText -> SlackButtonText -> Bool
$c/= :: SlackButtonText -> SlackButtonText -> Bool
/= :: SlackButtonText -> SlackButtonText -> Bool
Eq, Value -> Parser [SlackButtonText]
Value -> Parser SlackButtonText
(Value -> Parser SlackButtonText)
-> (Value -> Parser [SlackButtonText]) -> FromJSON SlackButtonText
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
$cparseJSON :: Value -> Parser SlackButtonText
parseJSON :: Value -> Parser SlackButtonText
$cparseJSONList :: Value -> Parser [SlackButtonText]
parseJSONList :: Value -> Parser [SlackButtonText]
FromJSON)

instance Slack SlackButtonText where
  message :: SlackButtonText -> SlackText
message (SlackButtonText NonEmptyText 75
m) = [Text] -> SlackText
SlackText [NonEmptyText 75 -> Text
forall (n :: Nat). NonEmptyText n -> Text
nonEmptyTextToText NonEmptyText 75
m]

-- It isn't the end of the world if this gets truncated (slack may truncate it
-- to about 30 characters anyway) so we have this convenience instance to
-- use plain strings for button text.
instance IsString SlackButtonText where
  fromString :: String -> SlackButtonText
fromString String
s = NonEmptyText 75 -> SlackButtonText
SlackButtonText (NonEmptyText 75 -> SlackButtonText)
-> (String -> NonEmptyText 75) -> String -> SlackButtonText
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
. Text -> NonEmptyText 75
forall (n :: Nat). (KnownNat n, 1 <= n) => Text -> NonEmptyText n
unsafeMkNonEmptyText (Text -> NonEmptyText 75)
-> (String -> Text) -> String -> NonEmptyText 75
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
. String -> Text
forall a b. ConvertibleStrings a b => a -> b
cs (String -> SlackButtonText) -> String -> SlackButtonText
forall a b. (a -> b) -> a -> b
$ Index String -> ShowS
forall seq. IsSequence seq => Index seq -> seq -> seq
take Int
Index String
75 String
s

-- | The component in a 'SlackAction'. Do not use directly.
-- Use the builder functions such as 'button' instead.
data SlackActionComponent = SlackButton
  { SlackActionComponent -> SlackButtonText
slackButtonText :: SlackButtonText -- max length 75, may truncate to ~30
  , SlackActionComponent -> Maybe (NonEmptyText 3000)
slackButtonUrl :: Maybe (NonEmptyText 3000) -- max length 3000
  , SlackActionComponent -> Maybe (NonEmptyText 2000)
slackButtonValue :: Maybe (NonEmptyText 2000) -- max length 2000
  , SlackActionComponent -> Maybe SlackStyle
slackButtonStyle :: Maybe SlackStyle
  , SlackActionComponent -> Maybe SlackConfirmObject
slackButtonConfirm :: Maybe SlackConfirmObject
  }
  deriving stock (SlackActionComponent -> SlackActionComponent -> Bool
(SlackActionComponent -> SlackActionComponent -> Bool)
-> (SlackActionComponent -> SlackActionComponent -> Bool)
-> Eq SlackActionComponent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlackActionComponent -> SlackActionComponent -> Bool
== :: SlackActionComponent -> SlackActionComponent -> Bool
$c/= :: SlackActionComponent -> SlackActionComponent -> Bool
/= :: SlackActionComponent -> SlackActionComponent -> Bool
Eq)

instance FromJSON SlackActionComponent where
  parseJSON :: Value -> Parser SlackActionComponent
parseJSON = String
-> (Object -> Parser SlackActionComponent)
-> Value
-> Parser SlackActionComponent
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlactActionComponent" ((Object -> Parser SlackActionComponent)
 -> Value -> Parser SlackActionComponent)
-> (Object -> Parser SlackActionComponent)
-> Value
-> Parser SlackActionComponent
forall a b. (a -> b) -> a -> b
$ \Object
obj -> do
    (Text
slackActionType :: Text) <- Object
obj Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
    case Text
slackActionType of
      Text
"button" -> do
        Object
text <- Object
obj Object -> Key -> Parser Object
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
        SlackButtonText
slackButtonText <- Object
text Object -> Key -> Parser SlackButtonText
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
        Maybe (NonEmptyText 3000)
slackButtonUrl <- Object
obj Object -> Key -> Parser (Maybe (NonEmptyText 3000))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"url"
        Maybe (NonEmptyText 2000)
slackButtonValue <- Object
obj Object -> Key -> Parser (Maybe (NonEmptyText 2000))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"value"
        Maybe SlackStyle
slackButtonStyle <- Object
obj Object -> Key -> Parser (Maybe SlackStyle)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"style"
        Maybe SlackConfirmObject
slackButtonConfirm <- Object
obj Object -> Key -> Parser (Maybe SlackConfirmObject)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"confirm"
        pure $ SlackButton {Maybe (NonEmptyText 2000)
Maybe (NonEmptyText 3000)
Maybe SlackStyle
Maybe SlackConfirmObject
SlackButtonText
slackButtonText :: SlackButtonText
slackButtonUrl :: Maybe (NonEmptyText 3000)
slackButtonValue :: Maybe (NonEmptyText 2000)
slackButtonStyle :: Maybe SlackStyle
slackButtonConfirm :: Maybe SlackConfirmObject
slackButtonText :: SlackButtonText
slackButtonUrl :: Maybe (NonEmptyText 3000)
slackButtonValue :: Maybe (NonEmptyText 2000)
slackButtonStyle :: Maybe SlackStyle
slackButtonConfirm :: Maybe SlackConfirmObject
..}
      Text
_ -> String -> Parser SlackActionComponent
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Unknown SlackActionComponent type, must be one of ['button']"

instance Show SlackActionComponent where
  show :: SlackActionComponent -> String
show SlackButton {Maybe (NonEmptyText 2000)
Maybe (NonEmptyText 3000)
Maybe SlackStyle
Maybe SlackConfirmObject
SlackButtonText
slackButtonText :: SlackActionComponent -> SlackButtonText
slackButtonUrl :: SlackActionComponent -> Maybe (NonEmptyText 3000)
slackButtonValue :: SlackActionComponent -> Maybe (NonEmptyText 2000)
slackButtonStyle :: SlackActionComponent -> Maybe SlackStyle
slackButtonConfirm :: SlackActionComponent -> Maybe SlackConfirmObject
slackButtonText :: SlackButtonText
slackButtonUrl :: Maybe (NonEmptyText 3000)
slackButtonValue :: Maybe (NonEmptyText 2000)
slackButtonStyle :: Maybe SlackStyle
slackButtonConfirm :: Maybe SlackConfirmObject
..} = String
"[button " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> SlackButtonText -> String
forall a. Show a => a -> String
show SlackButtonText
slackButtonText String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"]"

instance ToJSON SlackAction where
  toJSON :: SlackAction -> Value
toJSON (SlackAction SlackActionId
actionId SlackButton {Maybe (NonEmptyText 2000)
Maybe (NonEmptyText 3000)
Maybe SlackStyle
Maybe SlackConfirmObject
SlackButtonText
slackButtonText :: SlackActionComponent -> SlackButtonText
slackButtonUrl :: SlackActionComponent -> Maybe (NonEmptyText 3000)
slackButtonValue :: SlackActionComponent -> Maybe (NonEmptyText 2000)
slackButtonStyle :: SlackActionComponent -> Maybe SlackStyle
slackButtonConfirm :: SlackActionComponent -> Maybe SlackConfirmObject
slackButtonText :: SlackButtonText
slackButtonUrl :: Maybe (NonEmptyText 3000)
slackButtonValue :: Maybe (NonEmptyText 2000)
slackButtonStyle :: Maybe SlackStyle
slackButtonConfirm :: Maybe SlackConfirmObject
..}) =
    [Maybe Pair] -> Value
objectOptional
      [ Key
"type" Key -> Text -> Maybe Pair
forall v. ToJSON v => Key -> v -> Maybe Pair
.=! (Text
"button" :: Text)
      , Key
"action_id" Key -> SlackActionId -> Maybe Pair
forall v. ToJSON v => Key -> v -> Maybe Pair
.=! SlackActionId
actionId
      , Key
"text" Key -> SlackTextObject -> Maybe Pair
forall v. ToJSON v => Key -> v -> Maybe Pair
.=! SlackButtonText -> SlackTextObject
forall a. Slack a => a -> SlackTextObject
plaintext SlackButtonText
slackButtonText
      , Key
"url" Key -> Maybe (NonEmptyText 3000) -> Maybe Pair
forall v. ToJSON v => Key -> Maybe v -> Maybe Pair
.=? Maybe (NonEmptyText 3000)
slackButtonUrl
      , Key
"value" Key -> Maybe (NonEmptyText 2000) -> Maybe Pair
forall v. ToJSON v => Key -> Maybe v -> Maybe Pair
.=? Maybe (NonEmptyText 2000)
slackButtonValue
      , Key
"style" Key -> Maybe SlackStyle -> Maybe Pair
forall v. ToJSON v => Key -> Maybe v -> Maybe Pair
.=? Maybe SlackStyle
slackButtonStyle
      , Key
"confirm" Key -> Maybe SlackConfirmObject -> Maybe Pair
forall v. ToJSON v => Key -> Maybe v -> Maybe Pair
.=? Maybe SlackConfirmObject
slackButtonConfirm
      ]

instance FromJSON SlackAction where
  parseJSON :: Value -> Parser SlackAction
parseJSON = String
-> (Object -> Parser SlackAction) -> Value -> Parser SlackAction
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SlackAction" ((Object -> Parser SlackAction) -> Value -> Parser SlackAction)
-> (Object -> Parser SlackAction) -> Value -> Parser SlackAction
forall a b. (a -> b) -> a -> b
$ \Object
obj -> do
    SlackActionId
actionId <- Object
obj Object -> Key -> Parser SlackActionId
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"action_id"
    SlackActionComponent
slackActionComponent <- Value -> Parser SlackActionComponent
forall a. FromJSON a => Value -> Parser a
parseJSON (Value -> Parser SlackActionComponent)
-> Value -> Parser SlackActionComponent
forall a b. (a -> b) -> a -> b
$ Object -> Value
Object Object
obj
    pure $ SlackActionId -> SlackActionComponent -> SlackAction
SlackAction SlackActionId
actionId SlackActionComponent
slackActionComponent