{-# 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 Data.Aeson qualified as Aeson import Data.HashMap.Strict qualified as H import Data.Scientific (toBoundedInteger) import Data.Text qualified as T import Optics.TH import TextShow qualified import TextShow.TH -- | Empty type to flag application IDs data Application -- | Empty type to flag application command IDs data ApplicationCommand newtype InteractionToken = InteractionToken { fromInteractionToken :: T.Text } deriving stock (Show) deriving (Aeson.FromJSON, Aeson.ToJSON) via T.Text data Interaction = Interaction { id :: Snowflake Interaction , applicationID :: Snowflake Application , type_ :: InteractionType , data_ :: Maybe InteractionData , guildID :: Maybe (Snowflake Guild) , channelID :: Maybe (Snowflake Channel) , member :: Maybe Member , user :: Maybe User , token :: InteractionToken , version :: Int , message :: Maybe Message , locale :: Maybe T.Text , guildLocale :: Maybe T.Text } deriving (Show) deriving (HasID Interaction) via HasIDField "id" Interaction deriving (HasID Application) via HasIDField "applicationID" Interaction instance Aeson.FromJSON Interaction where parseJSON = Aeson.withObject "Interaction" $ \v -> Interaction <$> v .: "id" <*> v .: "application_id" <*> v .: "type" <*> v .:? "data" <*> v .:? "guild_id" <*> v .:? "channel_id" <*> v .:? "member" <*> v .:? "user" <*> v .: "token" <*> v .: "version" <*> v .:? "message" <*> v .:? "locale" <*> v .:? "guild_locale" data InteractionData = InteractionData { id :: Maybe (Snowflake ApplicationCommand) , name :: Maybe T.Text , resolved :: Maybe ResolvedInteractionData , -- , options :: [ApplicationCommandInteractionDataOptions] -- No commands yet customID :: Maybe CustomID , componentType :: Maybe ComponentType , values :: Maybe [T.Text] , targetID :: Maybe (Snowflake ()) , components :: Maybe [Aeson.Value] } deriving (Show) deriving (TextShow.TextShow) via TextShow.FromStringShow InteractionData instance Aeson.FromJSON InteractionData where parseJSON = Aeson.withObject "InteractionData" $ \v -> InteractionData <$> v .:? "id" <*> v .:? "name" <*> v .:? "resolved" <*> v .:? "custom_id" <*> v .:? "component_type" <*> v .:? "values" <*> v .:? "target_id" <*> v .:? "components" data ResolvedInteractionData = ResolvedInteractionData { users :: H.HashMap (Snowflake User) User , members :: H.HashMap (Snowflake Member) Member , roles :: H.HashMap (Snowflake Role) Role , channels :: H.HashMap (Snowflake Channel) (Partial Channel) , messages :: H.HashMap (Snowflake Message) (Partial Message) , attachments :: H.HashMap (Snowflake Attachment) Attachment } deriving (Show) deriving (TextShow.TextShow) via TextShow.FromStringShow ResolvedInteractionData instance Aeson.FromJSON ResolvedInteractionData where parseJSON = Aeson.withObject "ResolvedInteractionData" $ \v -> ResolvedInteractionData <$> v .:? "users" .!= H.empty <*> v .:? "members" .!= H.empty <*> v .:? "roles" .!= H.empty <*> v .:? "channels" .!= H.empty <*> v .:? "messages" .!= H.empty <*> v .:? "attachments" .!= H.empty data InteractionType = PingType | ApplicationCommandType | MessageComponentType | ApplicationCommandAutoCompleteType | ModalSubmitType deriving (Eq, Show) instance Aeson.FromJSON InteractionType where parseJSON = Aeson.withScientific "InteractionType" $ \n -> case toBoundedInteger @Int n of Just 1 -> pure PingType Just 2 -> pure ApplicationCommandType Just 3 -> pure MessageComponentType Just 4 -> pure ApplicationCommandAutoCompleteType Just 5 -> pure ModalSubmitType _ -> fail $ "Invalid InteractionType: " <> show n $(deriveTextShow ''InteractionToken) $(deriveTextShow ''InteractionType) $(deriveTextShow ''Interaction) $(makeFieldLabelsNoPrefix ''InteractionToken) $(makeFieldLabelsNoPrefix ''Interaction) $(makeFieldLabelsNoPrefix ''InteractionData) $(makeFieldLabelsNoPrefix ''ResolvedInteractionData) $(makeFieldLabelsNoPrefix ''InteractionType)