-- | A message from a channel
module Calamity.Types.Model.Channel.Message
    ( Message(..)
    , UpdatedMessage(..)
    , MessageType(..) ) where

import           Calamity.Internal.AesonThings
import           Calamity.Internal.Utils          ()
import           Calamity.Types.Model.Channel
import {-# SOURCE #-} Calamity.Types.Model.Guild.Guild
import           Calamity.Types.Model.Guild.Role
import           Calamity.Types.Model.User
import           Calamity.Types.Snowflake

import           Data.Aeson
import           Data.Scientific
import           Data.Text.Lazy                   ( Text )
import           Data.Time
import qualified Data.Vector.Unboxed              as UV

import           GHC.Generics

import           TextShow
import qualified TextShow.Generic                 as TSG

-- NOTE: make sure we fill in the guildID field when retrieving from REST
data Message = Message
  { Message -> Snowflake Message
id              :: Snowflake Message
  , Message -> Snowflake Channel
channelID       :: Snowflake Channel
  , Message -> Maybe (Snowflake Guild)
guildID         :: Maybe (Snowflake Guild)
  , Message -> Snowflake User
author          :: Snowflake User
  , Message -> Text
content         :: Text
  , Message -> UTCTime
timestamp       :: UTCTime
  , Message -> Maybe UTCTime
editedTimestamp :: Maybe UTCTime
  , Message -> Bool
tts             :: Bool
  , Message -> Bool
mentionEveryone :: Bool
  , Message -> Vector (Snowflake User)
mentions        :: UV.Vector (Snowflake User)
  , Message -> Vector (Snowflake Role)
mentionRoles    :: UV.Vector (Snowflake Role)
  , Message -> [Attachment]
attachments     :: [Attachment]
  , Message -> [Embed]
embeds          :: [Embed]
  , Message -> [Reaction]
reactions       :: [Reaction]
  , Message -> Maybe (Snowflake Message)
nonce           :: Maybe (Snowflake Message)
  , Message -> Bool
pinned          :: Bool
  , Message -> Maybe (Snowflake ())
webhookID       :: Maybe (Snowflake ())
  , Message -> MessageType
type_           :: MessageType
  }
  deriving ( Message -> Message -> Bool
(Message -> Message -> Bool)
-> (Message -> Message -> Bool) -> Eq Message
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Message -> Message -> Bool
$c/= :: Message -> Message -> Bool
== :: Message -> Message -> Bool
$c== :: Message -> Message -> Bool
Eq, Int -> Message -> ShowS
[Message] -> ShowS
Message -> String
(Int -> Message -> ShowS)
-> (Message -> String) -> ([Message] -> ShowS) -> Show Message
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Message] -> ShowS
$cshowList :: [Message] -> ShowS
show :: Message -> String
$cshow :: Message -> String
showsPrec :: Int -> Message -> ShowS
$cshowsPrec :: Int -> Message -> ShowS
Show, (forall x. Message -> Rep Message x)
-> (forall x. Rep Message x -> Message) -> Generic Message
forall x. Rep Message x -> Message
forall x. Message -> Rep Message x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Message x -> Message
$cfrom :: forall x. Message -> Rep Message x
Generic )
  deriving ( Int -> Message -> Builder
Int -> Message -> Text
Int -> Message -> Text
[Message] -> Builder
[Message] -> Text
[Message] -> Text
Message -> Builder
Message -> Text
Message -> Text
(Int -> Message -> Builder)
-> (Message -> Builder)
-> ([Message] -> Builder)
-> (Int -> Message -> Text)
-> (Message -> Text)
-> ([Message] -> Text)
-> (Int -> Message -> Text)
-> (Message -> Text)
-> ([Message] -> Text)
-> TextShow Message
forall a.
(Int -> a -> Builder)
-> (a -> Builder)
-> ([a] -> Builder)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> TextShow a
showtlList :: [Message] -> Text
$cshowtlList :: [Message] -> Text
showtl :: Message -> Text
$cshowtl :: Message -> Text
showtlPrec :: Int -> Message -> Text
$cshowtlPrec :: Int -> Message -> Text
showtList :: [Message] -> Text
$cshowtList :: [Message] -> Text
showt :: Message -> Text
$cshowt :: Message -> Text
showtPrec :: Int -> Message -> Text
$cshowtPrec :: Int -> Message -> Text
showbList :: [Message] -> Builder
$cshowbList :: [Message] -> Builder
showb :: Message -> Builder
$cshowb :: Message -> Builder
showbPrec :: Int -> Message -> Builder
$cshowbPrec :: Int -> Message -> Builder
TextShow ) via TSG.FromGeneric Message
  deriving ( [Message] -> Encoding
[Message] -> Value
Message -> Encoding
Message -> Value
(Message -> Value)
-> (Message -> Encoding)
-> ([Message] -> Value)
-> ([Message] -> Encoding)
-> ToJSON Message
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [Message] -> Encoding
$ctoEncodingList :: [Message] -> Encoding
toJSONList :: [Message] -> Value
$ctoJSONList :: [Message] -> Value
toEncoding :: Message -> Encoding
$ctoEncoding :: Message -> Encoding
toJSON :: Message -> Value
$ctoJSON :: Message -> Value
ToJSON ) via CalamityJSON Message
  deriving ( Value -> Parser [Message]
Value -> Parser Message
(Value -> Parser Message)
-> (Value -> Parser [Message]) -> FromJSON Message
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [Message]
$cparseJSONList :: Value -> Parser [Message]
parseJSON :: Value -> Parser Message
$cparseJSON :: Value -> Parser Message
FromJSON ) via WithSpecialCases
      '["author" `ExtractField` "id", "mentions" `ExtractFields` "id",
        "reactions" `IfNoneThen` DefaultToEmptyArray]
      Message
  deriving ( HasID Message ) via HasIDField "id" Message
  deriving ( HasID Channel ) via HasIDField "channelID" Message
  deriving ( HasID User ) via HasIDField "author" Message

data UpdatedMessage = UpdatedMessage
  { UpdatedMessage -> Snowflake Message
id              :: Snowflake Message
  , UpdatedMessage -> Snowflake Channel
channelID       :: Snowflake Channel
  , UpdatedMessage -> Maybe Text
content         :: Maybe Text
  , UpdatedMessage -> Maybe UTCTime
editedTimestamp :: Maybe UTCTime
  , UpdatedMessage -> Maybe Bool
tts             :: Maybe Bool
  , UpdatedMessage -> Maybe Bool
mentionEveryone :: Maybe Bool
  , UpdatedMessage -> Maybe (Vector (Snowflake User))
mentions        :: Maybe (UV.Vector (Snowflake User))
  , UpdatedMessage -> Maybe (Vector (Snowflake Role))
mentionRoles    :: Maybe (UV.Vector (Snowflake Role))
  , UpdatedMessage -> Maybe [Attachment]
attachments     :: Maybe [Attachment]
  , UpdatedMessage -> Maybe [Embed]
embeds          :: Maybe [Embed]
  , UpdatedMessage -> Maybe [Reaction]
reactions       :: Maybe [Reaction]
  , UpdatedMessage -> Maybe Bool
pinned          :: Maybe Bool
  }
  deriving ( UpdatedMessage -> UpdatedMessage -> Bool
(UpdatedMessage -> UpdatedMessage -> Bool)
-> (UpdatedMessage -> UpdatedMessage -> Bool) -> Eq UpdatedMessage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UpdatedMessage -> UpdatedMessage -> Bool
$c/= :: UpdatedMessage -> UpdatedMessage -> Bool
== :: UpdatedMessage -> UpdatedMessage -> Bool
$c== :: UpdatedMessage -> UpdatedMessage -> Bool
Eq, Int -> UpdatedMessage -> ShowS
[UpdatedMessage] -> ShowS
UpdatedMessage -> String
(Int -> UpdatedMessage -> ShowS)
-> (UpdatedMessage -> String)
-> ([UpdatedMessage] -> ShowS)
-> Show UpdatedMessage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UpdatedMessage] -> ShowS
$cshowList :: [UpdatedMessage] -> ShowS
show :: UpdatedMessage -> String
$cshow :: UpdatedMessage -> String
showsPrec :: Int -> UpdatedMessage -> ShowS
$cshowsPrec :: Int -> UpdatedMessage -> ShowS
Show, (forall x. UpdatedMessage -> Rep UpdatedMessage x)
-> (forall x. Rep UpdatedMessage x -> UpdatedMessage)
-> Generic UpdatedMessage
forall x. Rep UpdatedMessage x -> UpdatedMessage
forall x. UpdatedMessage -> Rep UpdatedMessage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep UpdatedMessage x -> UpdatedMessage
$cfrom :: forall x. UpdatedMessage -> Rep UpdatedMessage x
Generic )
  deriving ( Int -> UpdatedMessage -> Builder
Int -> UpdatedMessage -> Text
Int -> UpdatedMessage -> Text
[UpdatedMessage] -> Builder
[UpdatedMessage] -> Text
[UpdatedMessage] -> Text
UpdatedMessage -> Builder
UpdatedMessage -> Text
UpdatedMessage -> Text
(Int -> UpdatedMessage -> Builder)
-> (UpdatedMessage -> Builder)
-> ([UpdatedMessage] -> Builder)
-> (Int -> UpdatedMessage -> Text)
-> (UpdatedMessage -> Text)
-> ([UpdatedMessage] -> Text)
-> (Int -> UpdatedMessage -> Text)
-> (UpdatedMessage -> Text)
-> ([UpdatedMessage] -> Text)
-> TextShow UpdatedMessage
forall a.
(Int -> a -> Builder)
-> (a -> Builder)
-> ([a] -> Builder)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> TextShow a
showtlList :: [UpdatedMessage] -> Text
$cshowtlList :: [UpdatedMessage] -> Text
showtl :: UpdatedMessage -> Text
$cshowtl :: UpdatedMessage -> Text
showtlPrec :: Int -> UpdatedMessage -> Text
$cshowtlPrec :: Int -> UpdatedMessage -> Text
showtList :: [UpdatedMessage] -> Text
$cshowtList :: [UpdatedMessage] -> Text
showt :: UpdatedMessage -> Text
$cshowt :: UpdatedMessage -> Text
showtPrec :: Int -> UpdatedMessage -> Text
$cshowtPrec :: Int -> UpdatedMessage -> Text
showbList :: [UpdatedMessage] -> Builder
$cshowbList :: [UpdatedMessage] -> Builder
showb :: UpdatedMessage -> Builder
$cshowb :: UpdatedMessage -> Builder
showbPrec :: Int -> UpdatedMessage -> Builder
$cshowbPrec :: Int -> UpdatedMessage -> Builder
TextShow ) via TSG.FromGeneric UpdatedMessage
  deriving ( Value -> Parser [UpdatedMessage]
Value -> Parser UpdatedMessage
(Value -> Parser UpdatedMessage)
-> (Value -> Parser [UpdatedMessage]) -> FromJSON UpdatedMessage
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [UpdatedMessage]
$cparseJSONList :: Value -> Parser [UpdatedMessage]
parseJSON :: Value -> Parser UpdatedMessage
$cparseJSON :: Value -> Parser UpdatedMessage
FromJSON ) via WithSpecialCases
      '["author" `ExtractField` "id", "mentions" `ExtractFields` "id"]
      UpdatedMessage
  deriving ( HasID Message ) via HasIDField "id" UpdatedMessage
  deriving ( HasID Channel ) via HasIDField "channelID" UpdatedMessage

-- Thanks sbrg (https://github.com/saevarb/haskord/blob/d1bb07bcc4f3dbc29f2dfd3351ff9f16fc100c07/haskord-lib/src/Haskord/Types/Common.hs#L264)
data MessageType
  = Default
  | RecipientAdd
  | RecipientRemove
  | Call
  | ChannelNameChange
  | ChannelIconChange
  | ChannelPinnedMessage
  | GuildMemberJoin
  deriving ( MessageType -> MessageType -> Bool
(MessageType -> MessageType -> Bool)
-> (MessageType -> MessageType -> Bool) -> Eq MessageType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MessageType -> MessageType -> Bool
$c/= :: MessageType -> MessageType -> Bool
== :: MessageType -> MessageType -> Bool
$c== :: MessageType -> MessageType -> Bool
Eq, Int -> MessageType -> ShowS
[MessageType] -> ShowS
MessageType -> String
(Int -> MessageType -> ShowS)
-> (MessageType -> String)
-> ([MessageType] -> ShowS)
-> Show MessageType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MessageType] -> ShowS
$cshowList :: [MessageType] -> ShowS
show :: MessageType -> String
$cshow :: MessageType -> String
showsPrec :: Int -> MessageType -> ShowS
$cshowsPrec :: Int -> MessageType -> ShowS
Show, Int -> MessageType
MessageType -> Int
MessageType -> [MessageType]
MessageType -> MessageType
MessageType -> MessageType -> [MessageType]
MessageType -> MessageType -> MessageType -> [MessageType]
(MessageType -> MessageType)
-> (MessageType -> MessageType)
-> (Int -> MessageType)
-> (MessageType -> Int)
-> (MessageType -> [MessageType])
-> (MessageType -> MessageType -> [MessageType])
-> (MessageType -> MessageType -> [MessageType])
-> (MessageType -> MessageType -> MessageType -> [MessageType])
-> Enum MessageType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: MessageType -> MessageType -> MessageType -> [MessageType]
$cenumFromThenTo :: MessageType -> MessageType -> MessageType -> [MessageType]
enumFromTo :: MessageType -> MessageType -> [MessageType]
$cenumFromTo :: MessageType -> MessageType -> [MessageType]
enumFromThen :: MessageType -> MessageType -> [MessageType]
$cenumFromThen :: MessageType -> MessageType -> [MessageType]
enumFrom :: MessageType -> [MessageType]
$cenumFrom :: MessageType -> [MessageType]
fromEnum :: MessageType -> Int
$cfromEnum :: MessageType -> Int
toEnum :: Int -> MessageType
$ctoEnum :: Int -> MessageType
pred :: MessageType -> MessageType
$cpred :: MessageType -> MessageType
succ :: MessageType -> MessageType
$csucc :: MessageType -> MessageType
Enum, (forall x. MessageType -> Rep MessageType x)
-> (forall x. Rep MessageType x -> MessageType)
-> Generic MessageType
forall x. Rep MessageType x -> MessageType
forall x. MessageType -> Rep MessageType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MessageType x -> MessageType
$cfrom :: forall x. MessageType -> Rep MessageType x
Generic )
  deriving ( Int -> MessageType -> Builder
Int -> MessageType -> Text
Int -> MessageType -> Text
[MessageType] -> Builder
[MessageType] -> Text
[MessageType] -> Text
MessageType -> Builder
MessageType -> Text
MessageType -> Text
(Int -> MessageType -> Builder)
-> (MessageType -> Builder)
-> ([MessageType] -> Builder)
-> (Int -> MessageType -> Text)
-> (MessageType -> Text)
-> ([MessageType] -> Text)
-> (Int -> MessageType -> Text)
-> (MessageType -> Text)
-> ([MessageType] -> Text)
-> TextShow MessageType
forall a.
(Int -> a -> Builder)
-> (a -> Builder)
-> ([a] -> Builder)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> TextShow a
showtlList :: [MessageType] -> Text
$cshowtlList :: [MessageType] -> Text
showtl :: MessageType -> Text
$cshowtl :: MessageType -> Text
showtlPrec :: Int -> MessageType -> Text
$cshowtlPrec :: Int -> MessageType -> Text
showtList :: [MessageType] -> Text
$cshowtList :: [MessageType] -> Text
showt :: MessageType -> Text
$cshowt :: MessageType -> Text
showtPrec :: Int -> MessageType -> Text
$cshowtPrec :: Int -> MessageType -> Text
showbList :: [MessageType] -> Builder
$cshowbList :: [MessageType] -> Builder
showb :: MessageType -> Builder
$cshowb :: MessageType -> Builder
showbPrec :: Int -> MessageType -> Builder
$cshowbPrec :: Int -> MessageType -> Builder
TextShow ) via TSG.FromGeneric MessageType

instance ToJSON MessageType where
  toJSON :: MessageType -> Value
toJSON t :: MessageType
t = Scientific -> Value
Number (Scientific -> Value) -> Scientific -> Value
forall a b. (a -> b) -> a -> b
$ Int -> Scientific
forall a b. (Integral a, Num b) => a -> b
fromIntegral (MessageType -> Int
forall a. Enum a => a -> Int
fromEnum MessageType
t)

instance FromJSON MessageType where
  parseJSON :: Value -> Parser MessageType
parseJSON = String
-> (Scientific -> Parser MessageType)
-> Value
-> Parser MessageType
forall a. String -> (Scientific -> Parser a) -> Value -> Parser a
withScientific "MessageType" ((Scientific -> Parser MessageType) -> Value -> Parser MessageType)
-> (Scientific -> Parser MessageType)
-> Value
-> Parser MessageType
forall a b. (a -> b) -> a -> b
$ \n :: Scientific
n -> case Scientific -> Maybe Int
forall i. (Integral i, Bounded i) => Scientific -> Maybe i
toBoundedInteger Scientific
n of
    Just v :: Int
v  -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure (MessageType -> Parser MessageType)
-> MessageType -> Parser MessageType
forall a b. (a -> b) -> a -> b
$ Int -> MessageType
forall a. Enum a => Int -> a
toEnum Int
v
    Nothing -> String -> Parser MessageType
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser MessageType) -> String -> Parser MessageType
forall a b. (a -> b) -> a -> b
$ "Invalid MessageType: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Scientific -> String
forall a. Show a => a -> String
show Scientific
n