{-# LANGUAGE TemplateHaskell #-}

-- | Discord Interactions
module Calamity.Types.Model.Interaction (
  Interaction (..),
  InteractionToken (..),
  InteractionData (..),
  ResolvedInteractionData (..),
  InteractionType (..),
  Application,
  ApplicationCommand,
) where

import Calamity.Types.Model.Channel (Attachment, Channel, Partial)
import Calamity.Types.Model.Channel.Component
import Calamity.Types.Model.Channel.Message (Message)
import Calamity.Types.Model.Guild (Guild, Role)
import Calamity.Types.Model.Guild.Member (Member)
import Calamity.Types.Model.User (User)
import Calamity.Types.Snowflake
import Data.Aeson ((.:), (.:?), (.!=))
import qualified Data.Aeson as Aeson
import qualified Data.HashMap.Strict as H
import Data.Scientific (toBoundedInteger)
import qualified Data.Text as T
import Optics.TH
import qualified TextShow
import TextShow.TH

-- | Empty type to flag application IDs
data Application

-- | Empty type to flag application command IDs
data ApplicationCommand

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

data Interaction = Interaction
  { Interaction -> Snowflake Interaction
id :: Snowflake Interaction
  , Interaction -> Snowflake Application
applicationID :: Snowflake Application
  , Interaction -> InteractionType
type_ :: InteractionType
  , Interaction -> Maybe InteractionData
data_ :: Maybe InteractionData
  , Interaction -> Maybe (Snowflake Guild)
guildID :: Maybe (Snowflake Guild)
  , Interaction -> Maybe (Snowflake Channel)
channelID :: Maybe (Snowflake Channel)
  , Interaction -> Maybe Member
member :: Maybe Member
  , Interaction -> Maybe User
user :: Maybe User
  , Interaction -> InteractionToken
token :: InteractionToken
  , Interaction -> Int
version :: Int
  , Interaction -> Maybe Message
message :: Maybe Message
  , Interaction -> Maybe Text
locale :: Maybe T.Text
  , Interaction -> Maybe Text
guildLocale :: Maybe T.Text
  }
  deriving (Int -> Interaction -> ShowS
[Interaction] -> ShowS
Interaction -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Interaction] -> ShowS
$cshowList :: [Interaction] -> ShowS
show :: Interaction -> String
$cshow :: Interaction -> String
showsPrec :: Int -> Interaction -> ShowS
$cshowsPrec :: Int -> Interaction -> ShowS
Show)
  deriving (HasID Interaction) via HasIDField "id" Interaction
  deriving (HasID Application) via HasIDField "applicationID" Interaction

instance Aeson.FromJSON Interaction where
  parseJSON :: Value -> Parser Interaction
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"Interaction" forall a b. (a -> b) -> a -> b
$ \Object
v ->
    Snowflake Interaction
-> Snowflake Application
-> InteractionType
-> Maybe InteractionData
-> Maybe (Snowflake Guild)
-> Maybe (Snowflake Channel)
-> Maybe Member
-> Maybe User
-> InteractionToken
-> Int
-> Maybe Message
-> Maybe Text
-> Maybe Text
-> Interaction
Interaction
      forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"application_id"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"data"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"guild_id"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"channel_id"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"member"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"user"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"token"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"version"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"message"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"locale"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"guild_locale"

data InteractionData = InteractionData
  { InteractionData -> Maybe (Snowflake ApplicationCommand)
id :: Maybe (Snowflake ApplicationCommand)
  , InteractionData -> Maybe Text
name :: Maybe T.Text
  , InteractionData -> Maybe ResolvedInteractionData
resolved :: Maybe ResolvedInteractionData
  , -- , options :: [ApplicationCommandInteractionDataOptions]
    -- No commands yet
    InteractionData -> Maybe CustomID
customID :: Maybe CustomID
  , InteractionData -> Maybe ComponentType
componentType :: Maybe ComponentType
  , InteractionData -> Maybe [Text]
values :: Maybe [T.Text]
  , InteractionData -> Maybe (Snowflake ())
targetID :: Maybe (Snowflake ())
  , InteractionData -> Maybe [Value]
components :: Maybe [Aeson.Value]
  }
  deriving (Int -> InteractionData -> ShowS
[InteractionData] -> ShowS
InteractionData -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [InteractionData] -> ShowS
$cshowList :: [InteractionData] -> ShowS
show :: InteractionData -> String
$cshow :: InteractionData -> String
showsPrec :: Int -> InteractionData -> ShowS
$cshowsPrec :: Int -> InteractionData -> ShowS
Show)
  deriving (Int -> InteractionData -> Builder
Int -> InteractionData -> Text
Int -> InteractionData -> Text
[InteractionData] -> Builder
[InteractionData] -> Text
[InteractionData] -> Text
InteractionData -> Builder
InteractionData -> Text
InteractionData -> Text
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 :: [InteractionData] -> Text
$cshowtlList :: [InteractionData] -> Text
showtl :: InteractionData -> Text
$cshowtl :: InteractionData -> Text
showtlPrec :: Int -> InteractionData -> Text
$cshowtlPrec :: Int -> InteractionData -> Text
showtList :: [InteractionData] -> Text
$cshowtList :: [InteractionData] -> Text
showt :: InteractionData -> Text
$cshowt :: InteractionData -> Text
showtPrec :: Int -> InteractionData -> Text
$cshowtPrec :: Int -> InteractionData -> Text
showbList :: [InteractionData] -> Builder
$cshowbList :: [InteractionData] -> Builder
showb :: InteractionData -> Builder
$cshowb :: InteractionData -> Builder
showbPrec :: Int -> InteractionData -> Builder
$cshowbPrec :: Int -> InteractionData -> Builder
TextShow.TextShow) via TextShow.FromStringShow InteractionData

instance Aeson.FromJSON InteractionData where
  parseJSON :: Value -> Parser InteractionData
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"InteractionData" forall a b. (a -> b) -> a -> b
$ \Object
v ->
    Maybe (Snowflake ApplicationCommand)
-> Maybe Text
-> Maybe ResolvedInteractionData
-> Maybe CustomID
-> Maybe ComponentType
-> Maybe [Text]
-> Maybe (Snowflake ())
-> Maybe [Value]
-> InteractionData
InteractionData
      forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"id"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"name"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"resolved"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"custom_id"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"component_type"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"values"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"target_id"
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"components"

data ResolvedInteractionData = ResolvedInteractionData
  { ResolvedInteractionData -> HashMap (Snowflake User) User
users :: H.HashMap (Snowflake User) User
  , ResolvedInteractionData -> HashMap (Snowflake Member) Member
members :: H.HashMap (Snowflake Member) Member
  , ResolvedInteractionData -> HashMap (Snowflake Role) Role
roles :: H.HashMap (Snowflake Role) Role
  , ResolvedInteractionData
-> HashMap (Snowflake Channel) (Partial Channel)
channels :: H.HashMap (Snowflake Channel) (Partial Channel)
  , ResolvedInteractionData
-> HashMap (Snowflake Message) (Partial Message)
messages :: H.HashMap (Snowflake Message) (Partial Message)
  , ResolvedInteractionData
-> HashMap (Snowflake Attachment) Attachment
attachments :: H.HashMap (Snowflake Attachment) Attachment
  }
  deriving (Int -> ResolvedInteractionData -> ShowS
[ResolvedInteractionData] -> ShowS
ResolvedInteractionData -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ResolvedInteractionData] -> ShowS
$cshowList :: [ResolvedInteractionData] -> ShowS
show :: ResolvedInteractionData -> String
$cshow :: ResolvedInteractionData -> String
showsPrec :: Int -> ResolvedInteractionData -> ShowS
$cshowsPrec :: Int -> ResolvedInteractionData -> ShowS
Show)
  deriving (Int -> ResolvedInteractionData -> Builder
Int -> ResolvedInteractionData -> Text
Int -> ResolvedInteractionData -> Text
[ResolvedInteractionData] -> Builder
[ResolvedInteractionData] -> Text
[ResolvedInteractionData] -> Text
ResolvedInteractionData -> Builder
ResolvedInteractionData -> Text
ResolvedInteractionData -> Text
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 :: [ResolvedInteractionData] -> Text
$cshowtlList :: [ResolvedInteractionData] -> Text
showtl :: ResolvedInteractionData -> Text
$cshowtl :: ResolvedInteractionData -> Text
showtlPrec :: Int -> ResolvedInteractionData -> Text
$cshowtlPrec :: Int -> ResolvedInteractionData -> Text
showtList :: [ResolvedInteractionData] -> Text
$cshowtList :: [ResolvedInteractionData] -> Text
showt :: ResolvedInteractionData -> Text
$cshowt :: ResolvedInteractionData -> Text
showtPrec :: Int -> ResolvedInteractionData -> Text
$cshowtPrec :: Int -> ResolvedInteractionData -> Text
showbList :: [ResolvedInteractionData] -> Builder
$cshowbList :: [ResolvedInteractionData] -> Builder
showb :: ResolvedInteractionData -> Builder
$cshowb :: ResolvedInteractionData -> Builder
showbPrec :: Int -> ResolvedInteractionData -> Builder
$cshowbPrec :: Int -> ResolvedInteractionData -> Builder
TextShow.TextShow) via TextShow.FromStringShow ResolvedInteractionData

instance Aeson.FromJSON ResolvedInteractionData where
  parseJSON :: Value -> Parser ResolvedInteractionData
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"ResolvedInteractionData" forall a b. (a -> b) -> a -> b
$ \Object
v ->
    HashMap (Snowflake User) User
-> HashMap (Snowflake Member) Member
-> HashMap (Snowflake Role) Role
-> HashMap (Snowflake Channel) (Partial Channel)
-> HashMap (Snowflake Message) (Partial Message)
-> HashMap (Snowflake Attachment) Attachment
-> ResolvedInteractionData
ResolvedInteractionData
      forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"users" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall k v. HashMap k v
H.empty
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"members" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall k v. HashMap k v
H.empty
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"roles" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall k v. HashMap k v
H.empty
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"channels" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall k v. HashMap k v
H.empty
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"messages" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall k v. HashMap k v
H.empty
      forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"attachments" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall k v. HashMap k v
H.empty

data InteractionType
  = PingType
  | ApplicationCommandType
  | MessageComponentType
  | ApplicationCommandAutoCompleteType
  | ModalSubmitType
  deriving (InteractionType -> InteractionType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: InteractionType -> InteractionType -> Bool
$c/= :: InteractionType -> InteractionType -> Bool
== :: InteractionType -> InteractionType -> Bool
$c== :: InteractionType -> InteractionType -> Bool
Eq, Int -> InteractionType -> ShowS
[InteractionType] -> ShowS
InteractionType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [InteractionType] -> ShowS
$cshowList :: [InteractionType] -> ShowS
show :: InteractionType -> String
$cshow :: InteractionType -> String
showsPrec :: Int -> InteractionType -> ShowS
$cshowsPrec :: Int -> InteractionType -> ShowS
Show)

instance Aeson.FromJSON InteractionType where
  parseJSON :: Value -> Parser InteractionType
parseJSON = forall a. String -> (Scientific -> Parser a) -> Value -> Parser a
Aeson.withScientific String
"InteractionType" forall a b. (a -> b) -> a -> b
$ \Scientific
n -> case forall i. (Integral i, Bounded i) => Scientific -> Maybe i
toBoundedInteger @Int Scientific
n of
    Just Int
1 -> forall (f :: * -> *) a. Applicative f => a -> f a
pure InteractionType
PingType
    Just Int
2 -> forall (f :: * -> *) a. Applicative f => a -> f a
pure InteractionType
ApplicationCommandType
    Just Int
3 -> forall (f :: * -> *) a. Applicative f => a -> f a
pure InteractionType
MessageComponentType
    Just Int
4 -> forall (f :: * -> *) a. Applicative f => a -> f a
pure InteractionType
ApplicationCommandAutoCompleteType
    Just Int
5 -> forall (f :: * -> *) a. Applicative f => a -> f a
pure InteractionType
ModalSubmitType
    Maybe Int
_ -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Invalid InteractionType: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Scientific
n

$(deriveTextShow ''InteractionToken)
$(deriveTextShow ''InteractionType)
$(deriveTextShow ''Interaction)
$(makeFieldLabelsNoPrefix ''InteractionToken)
$(makeFieldLabelsNoPrefix ''Interaction)
$(makeFieldLabelsNoPrefix ''InteractionData)
$(makeFieldLabelsNoPrefix ''ResolvedInteractionData)
$(makeFieldLabelsNoPrefix ''InteractionType)