packages feed

calamity-0.1.30.2: Calamity/Types/Model/Channel/Embed.hs

-- | 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.AesonThings
import Calamity.Internal.IntColour
import Calamity.Internal.OverriddenVia
import Calamity.Internal.Utils
import Control.Lens
import Data.Aeson
import Data.Colour (Colour)
import Data.Default.Class
import Data.Generics.Labels ()
import Data.Semigroup
import Data.Text.Lazy (Text)
import Data.Time
import Data.Word
import GHC.Generics
import TextShow
import qualified TextShow.Generic as TSG

data Embed' = Embed'
    { title :: Maybe Text
    , type_ :: Maybe Text
    , description :: Maybe Text
    , url :: Maybe Text
    , timestamp :: Maybe (CalamityFromStringShow UTCTime)
    , color :: Maybe IntColour
    , footer :: Maybe EmbedFooter
    , image :: Maybe EmbedImage
    , thumbnail :: Maybe EmbedThumbnail
    , video :: Maybe EmbedVideo
    , provider :: Maybe EmbedProvider
    , author :: Maybe EmbedAuthor
    , fields :: [EmbedField]
    }
    deriving (Generic)
    deriving (FromJSON) via WithSpecialCases '[IfNoneThen "fields" DefaultToEmptyArray] Embed'
    deriving (ToJSON) via CalamityJSON Embed'
    deriving (TextShow) via TSG.FromGeneric Embed'

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, Generic, Default)
    deriving (TextShow, FromJSON, ToJSON) via OverriddenVia Embed Embed'

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

data EmbedFooter = EmbedFooter
    { text :: Text
    , iconUrl :: Maybe Text
    , proxyIconUrl :: Maybe Text
    }
    deriving (Eq, Show, Generic)
    deriving (TextShow) via TSG.FromGeneric EmbedFooter
    deriving (ToJSON, FromJSON) via CalamityJSON EmbedFooter

{- | Create an embed footer with a provided content

 The remaining fields are set to Nothing
-}
embedFooter :: Text -> EmbedFooter
embedFooter text = EmbedFooter text Nothing Nothing

instance Semigroup EmbedFooter where
    l <> r =
        l
            & #text %~ (<> (r ^. #text))
            & #iconUrl %~ getLast . (<> Last (r ^. #iconUrl)) . Last
            & #proxyIconUrl %~ getLast . (<> Last (r ^. #proxyIconUrl)) . Last

data EmbedImage = EmbedImage
    { url :: Text
    , proxyUrl :: Maybe Text
    , width :: Maybe Word64
    , height :: Maybe Word64
    }
    deriving (Eq, Show, Generic)
    deriving (TextShow) via TSG.FromGeneric EmbedImage
    deriving (FromJSON, ToJSON) via CalamityJSON EmbedImage

{- | 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, Generic)
    deriving (TextShow) via TSG.FromGeneric EmbedThumbnail
    deriving (FromJSON, ToJSON) via CalamityJSON EmbedThumbnail

{- | 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, Generic)
    deriving (TextShow) via TSG.FromGeneric EmbedVideo
    deriving (FromJSON, ToJSON) via CalamityJSON EmbedVideo

data EmbedProvider = EmbedProvider
    { name :: Maybe Text
    , url :: Maybe Text
    }
    deriving (Eq, Show, Generic)
    deriving (TextShow) via TSG.FromGeneric EmbedProvider
    deriving (ToJSON, FromJSON) via CalamityJSON EmbedProvider

data EmbedAuthor = EmbedAuthor
    { name :: Maybe Text
    , url :: Maybe Text
    , iconUrl :: Maybe Text
    , proxyIconURL :: Maybe Text
    }
    deriving (Eq, Show, Generic, Default)
    deriving (TextShow) via TSG.FromGeneric EmbedAuthor
    deriving (ToJSON, FromJSON) via CalamityJSON EmbedAuthor

{- | 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, Generic)
    deriving (TextShow) via TSG.FromGeneric EmbedField
    deriving
        (FromJSON)
        via WithSpecialCases
                '[IfNoneThen "inline" DefaultToFalse]
                EmbedField
    deriving (ToJSON) via CalamityJSON EmbedField

-- | Create a non-inline embed field
embedField ::
    -- | Name
    Text ->
    -- | Value
    Text ->
    EmbedField
embedField name value = EmbedField name value False