calamity-0.11.0.0: Calamity/Types/Model/Channel/Embed.hs
{-# LANGUAGE TemplateHaskell #-}
-- | Message embeds
module Calamity.Types.Model.Channel.Embed (
Embed (..),
embedFooter,
embedImage,
embedThumbnail,
embedAuthor,
embedAuthor',
embedField,
EmbedFooter (..),
EmbedImage (..),
EmbedThumbnail (..),
EmbedVideo (..),
EmbedProvider (..),
EmbedAuthor (..),
EmbedField (..),
) where
import Calamity.Internal.IntColour (IntColour (..))
import Calamity.Internal.Utils (CalamityToJSON (..), CalamityToJSON' (..), (.=), (.?=))
import Data.Aeson ((.!=), (.:), (.:?))
import Data.Aeson qualified as Aeson
import Data.Colour (Colour)
import Data.Default.Class
import Data.Semigroup
import Data.Text (Text)
import Data.Time
import Data.Word
import Optics ((%~), (&), (^.))
import Optics.TH
import TextShow qualified
import TextShow.TH
data Embed = Embed
{ title :: Maybe Text
, type_ :: Maybe Text
, description :: Maybe Text
, url :: Maybe Text
, timestamp :: Maybe UTCTime
, color :: Maybe (Colour Double)
, footer :: Maybe EmbedFooter
, image :: Maybe EmbedImage
, thumbnail :: Maybe EmbedThumbnail
, video :: Maybe EmbedVideo
, provider :: Maybe EmbedProvider
, author :: Maybe EmbedAuthor
, fields :: [EmbedField]
}
deriving (Eq, Show)
deriving (TextShow.TextShow) via TextShow.FromStringShow Embed
deriving (Aeson.ToJSON) via CalamityToJSON Embed
instance Default Embed where
def =
Embed
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
[]
instance CalamityToJSON' Embed where
toPairs Embed {..} =
[ "title" .?= title
, "type" .?= type_
, "description" .?= description
, "url" .?= url
, "timestamp" .?= timestamp
, "color" .?= (IntColour <$> color)
, "footer" .?= footer
, "image" .?= image
, "thumbnail" .?= thumbnail
, "video" .?= video
, "provider" .?= provider
, "author" .?= author
, "fields" .= fields
]
instance Aeson.FromJSON Embed where
parseJSON = Aeson.withObject "Embed" $ \v ->
Embed
<$> v .:? "title"
<*> v .:? "type"
<*> v .:? "description"
<*> v .:? "url"
<*> v .:? "timestamp"
<*> (fmap fromIntColour <$> v .:? "color")
<*> v .:? "footer"
<*> v .:? "image"
<*> v .:? "thumbnail"
<*> v .:? "video"
<*> v .:? "provider"
<*> v .:? "author"
<*> v .:? "fields" .!= []
data EmbedFooter = EmbedFooter
{ text :: Text
, iconUrl :: Maybe Text
, proxyIconUrl :: Maybe Text
}
deriving (Eq, Show)
deriving (Aeson.ToJSON) via CalamityToJSON EmbedFooter
instance CalamityToJSON' EmbedFooter where
toPairs EmbedFooter {..} =
[ "text" .= text
, "icon_url" .?= iconUrl
, "proxy_icon_url" .?= proxyIconUrl
]
instance Aeson.FromJSON EmbedFooter where
parseJSON = Aeson.withObject "EmbedFooter" $ \v ->
EmbedFooter
<$> v .: "text"
<*> v .:? "icon_url"
<*> v .:? "proxy_icon_url"
{- | Create an embed footer with a provided content
The remaining fields are set to Nothing
-}
embedFooter :: Text -> EmbedFooter
embedFooter text = EmbedFooter text Nothing Nothing
data EmbedImage = EmbedImage
{ url :: Text
, proxyUrl :: Maybe Text
, width :: Maybe Word64
, height :: Maybe Word64
}
deriving (Eq, Show)
deriving (Aeson.ToJSON) via CalamityToJSON EmbedImage
instance CalamityToJSON' EmbedImage where
toPairs EmbedImage {..} =
[ "url" .= url
, "proxy_url" .= proxyUrl
, "width" .= width
, "height" .= height
]
instance Aeson.FromJSON EmbedImage where
parseJSON = Aeson.withObject "EmbedImage" $ \v ->
EmbedImage
<$> v .: "url"
<*> v .:? "proxy_url"
<*> v .:? "width"
<*> v .:? "height"
{- | Create an embed image with a provided url
The remaining fields are set to Nothing
-}
embedImage :: Text -> EmbedImage
embedImage url = EmbedImage url Nothing Nothing Nothing
data EmbedThumbnail = EmbedThumbnail
{ url :: Text
, proxyUrl :: Maybe Text
, width :: Maybe Word64
, height :: Maybe Word64
}
deriving (Eq, Show)
deriving (Aeson.ToJSON) via CalamityToJSON EmbedThumbnail
instance CalamityToJSON' EmbedThumbnail where
toPairs EmbedThumbnail {..} =
[ "url" .= url
, "proxy_url" .?= proxyUrl
, "width" .?= width
, "height" .?= height
]
instance Aeson.FromJSON EmbedThumbnail where
parseJSON = Aeson.withObject "EmbedThumbnail" $ \v ->
EmbedThumbnail
<$> v .: "url"
<*> v .:? "proxy_url"
<*> v .:? "width"
<*> v .:? "height"
{- | Create an embed thumbnail with a provided url
The remaining fields are set to Nothing
-}
embedThumbnail :: Text -> EmbedThumbnail
embedThumbnail url = EmbedThumbnail url Nothing Nothing Nothing
data EmbedVideo = EmbedVideo
{ url :: Maybe Text
, proxyUrl :: Maybe Text
, width :: Maybe Word64
, height :: Maybe Word64
}
deriving (Eq, Show)
deriving (Aeson.ToJSON) via CalamityToJSON EmbedVideo
instance CalamityToJSON' EmbedVideo where
toPairs EmbedVideo {..} =
[ "url" .= url
, "proxy_url" .= proxyUrl
, "width" .= width
, "height" .= height
]
instance Aeson.FromJSON EmbedVideo where
parseJSON = Aeson.withObject "EmbedVideo" $ \v ->
EmbedVideo
<$> v .: "url"
<*> v .:? "proxy_url"
<*> v .:? "width"
<*> v .:? "height"
data EmbedProvider = EmbedProvider
{ name :: Maybe Text
, url :: Maybe Text
}
deriving (Eq, Show)
deriving (Aeson.ToJSON) via CalamityToJSON EmbedProvider
instance CalamityToJSON' EmbedProvider where
toPairs EmbedProvider {..} =
[ "name" .= name
, "url" .= url
]
instance Aeson.FromJSON EmbedProvider where
parseJSON = Aeson.withObject "EmbedProvider" $ \v ->
EmbedProvider
<$> v .:? "name"
<*> v .:? "url"
data EmbedAuthor = EmbedAuthor
{ name :: Maybe Text
, url :: Maybe Text
, iconUrl :: Maybe Text
, proxyIconUrl :: Maybe Text
}
deriving (Eq, Show)
deriving (Aeson.ToJSON) via CalamityToJSON EmbedAuthor
instance Default EmbedAuthor where
def = EmbedAuthor Nothing Nothing Nothing Nothing
instance CalamityToJSON' EmbedAuthor where
toPairs EmbedAuthor {..} =
[ "name" .?= name
, "url" .?= url
, "icon_url" .?= iconUrl
, "proxy_icon_url" .?= proxyIconUrl
]
instance Aeson.FromJSON EmbedAuthor where
parseJSON = Aeson.withObject "EmbedAuthor" $ \v ->
EmbedAuthor
<$> v .:? "name"
<*> v .:? "url"
<*> v .:? "icon_url"
<*> v .:? "proxy_icon_url"
{- | Create an embed author with the given name
The remaining fields are set to Nothing
-}
embedAuthor :: Text -> EmbedAuthor
embedAuthor name = EmbedAuthor (Just name) Nothing Nothing Nothing
{- | Create an embed author with the given name, url, and icon url
The remaining fields are set to Nothing
-}
embedAuthor' ::
-- | Name
Text ->
-- | Url
Text ->
-- | Icon url
Text ->
EmbedAuthor
embedAuthor' name url iconUrl = EmbedAuthor (Just name) (Just url) (Just iconUrl) Nothing
data EmbedField = EmbedField
{ name :: Text
, value :: Text
, inline :: Bool
}
deriving (Eq, Show)
deriving (Aeson.ToJSON) via CalamityToJSON EmbedField
instance CalamityToJSON' EmbedField where
toPairs EmbedField {..} =
[ "name" .= name
, "value" .= value
, "inline" .= inline
]
instance Aeson.FromJSON EmbedField where
parseJSON = Aeson.withObject "EmbedField" $ \v ->
EmbedField
<$> v .: "name"
<*> v .: "value"
<*> v .:? "inline" .!= False
-- | Create a non-inline embed field
embedField ::
-- | Name
Text ->
-- | Value
Text ->
EmbedField
embedField name value = EmbedField name value False
$(makeFieldLabelsNoPrefix ''Embed)
$(deriveTextShow ''EmbedFooter)
$(makeFieldLabelsNoPrefix ''EmbedFooter)
$(deriveTextShow ''EmbedImage)
$(makeFieldLabelsNoPrefix ''EmbedImage)
$(deriveTextShow ''EmbedThumbnail)
$(makeFieldLabelsNoPrefix ''EmbedThumbnail)
$(deriveTextShow ''EmbedVideo)
$(makeFieldLabelsNoPrefix ''EmbedVideo)
$(deriveTextShow ''EmbedProvider)
$(makeFieldLabelsNoPrefix ''EmbedProvider)
$(deriveTextShow ''EmbedAuthor)
$(makeFieldLabelsNoPrefix ''EmbedAuthor)
$(deriveTextShow ''EmbedField)
$(makeFieldLabelsNoPrefix ''EmbedField)
instance Semigroup EmbedFooter where
l <> r =
l
& #text
%~ (<> (r ^. #text))
& #iconUrl
%~ getLast
. (<> Last (r ^. #iconUrl))
. Last
& #proxyIconUrl
%~ getLast
. (<> Last (r ^. #proxyIconUrl))
. Last
instance Semigroup Embed where
l <> r =
l
& #title
%~ (<> (r ^. #title))
& #type_
%~ getLast
. (<> Last (r ^. #type_))
. Last
& #description
%~ (<> (r ^. #description))
& #url
%~ getLast
. (<> Last (r ^. #url))
. Last
& #timestamp
%~ getLast
. (<> Last (r ^. #timestamp))
. Last
& #color
%~ getLast
. (<> Last (r ^. #color))
. Last
& #footer
%~ (<> (r ^. #footer))
& #image
%~ getLast
. (<> Last (r ^. #image))
. Last
& #thumbnail
%~ getLast
. (<> Last (r ^. #thumbnail))
. Last
& #video
%~ getLast
. (<> Last (r ^. #video))
. Last
& #provider
%~ getLast
. (<> Last (r ^. #provider))
. Last
& #author
%~ getLast
. (<> Last (r ^. #author))
. Last
& #fields
%~ (<> (r ^. #fields))
instance Monoid Embed where
mempty = def