{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE FlexibleInstances  #-}
{-# LANGUAGE RankNTypes  #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}

-- | Provides base types and utility functions needed for modules in Discord.Internal.Types
module Discord.Internal.Types.Prelude
  ( Auth (..)
  , authToken

  , Snowflake (..)
  , snowflakeCreationDate

  , RolePermissions (..)
  
  , DiscordId (..)
  , ChannelId
  , StageId
  , GuildId
  , MessageId
  , AttachmentId
  , EmojiId
  , StickerId
  , UserId
  , RoleId
  , IntegrationId
  , WebhookId
  , ParentId
  , ApplicationId
  , ApplicationCommandId
  , InteractionId
  , ScheduledEventId
  , ScheduledEventEntityId

  , DiscordToken (..)
  , InteractionToken
  , WebhookToken

  , Shard
  , epochTime

  , InternalDiscordEnum (..)

  , Base64Image (..)
  , getMimeType

  , (.==)
  , (.=?)
  , AesonKey
  , objectFromMaybes

  , ChannelTypeOption (..)
  )

 where

import Data.Bifunctor (first)
import Data.Bits (Bits(shiftR))
import Data.Data (Data (dataTypeOf), dataTypeConstrs, fromConstr)
import Data.Word (Word64)
import Data.Maybe (catMaybes)
import Text.Read (readMaybe)

import Data.Aeson.Types
import Data.Time.Clock
import Data.Time.Clock.POSIX
import Web.Internal.HttpApiData

import qualified Data.ByteString as B
import qualified Data.Text as T

#if MIN_VERSION_aeson(2, 0, 0)
import qualified Data.Aeson.Key as Key
#endif

-- | Authorization token for the Discord API
newtype Auth = Auth T.Text
  deriving (Int -> Auth -> ShowS
[Auth] -> ShowS
Auth -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Auth] -> ShowS
$cshowList :: [Auth] -> ShowS
show :: Auth -> String
$cshow :: Auth -> String
showsPrec :: Int -> Auth -> ShowS
$cshowsPrec :: Int -> Auth -> ShowS
Show, ReadPrec [Auth]
ReadPrec Auth
Int -> ReadS Auth
ReadS [Auth]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Auth]
$creadListPrec :: ReadPrec [Auth]
readPrec :: ReadPrec Auth
$creadPrec :: ReadPrec Auth
readList :: ReadS [Auth]
$creadList :: ReadS [Auth]
readsPrec :: Int -> ReadS Auth
$creadsPrec :: Int -> ReadS Auth
Read, Auth -> Auth -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Auth -> Auth -> Bool
$c/= :: Auth -> Auth -> Bool
== :: Auth -> Auth -> Bool
$c== :: Auth -> Auth -> Bool
Eq, Eq Auth
Auth -> Auth -> Bool
Auth -> Auth -> Ordering
Auth -> Auth -> Auth
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Auth -> Auth -> Auth
$cmin :: Auth -> Auth -> Auth
max :: Auth -> Auth -> Auth
$cmax :: Auth -> Auth -> Auth
>= :: Auth -> Auth -> Bool
$c>= :: Auth -> Auth -> Bool
> :: Auth -> Auth -> Bool
$c> :: Auth -> Auth -> Bool
<= :: Auth -> Auth -> Bool
$c<= :: Auth -> Auth -> Bool
< :: Auth -> Auth -> Bool
$c< :: Auth -> Auth -> Bool
compare :: Auth -> Auth -> Ordering
$ccompare :: Auth -> Auth -> Ordering
Ord)


-- | Get the raw token formatted for use with the websocket gateway
authToken :: Auth -> T.Text
authToken :: Auth -> Text
authToken (Auth Text
tok) = let token :: Text
token = Text -> Text
T.strip Text
tok
                           bot :: Text
bot = if Text
"Bot " Text -> Text -> Bool
`T.isPrefixOf` Text
token then Text
"" else Text
"Bot "
                       in Text
bot forall a. Semigroup a => a -> a -> a
<> Text
token

-- | A unique integer identifier. Can be used to calculate the creation date of an entity.
newtype Snowflake = Snowflake { Snowflake -> Word64
unSnowflake :: Word64 }
  deriving (Eq Snowflake
Snowflake -> Snowflake -> Bool
Snowflake -> Snowflake -> Ordering
Snowflake -> Snowflake -> Snowflake
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Snowflake -> Snowflake -> Snowflake
$cmin :: Snowflake -> Snowflake -> Snowflake
max :: Snowflake -> Snowflake -> Snowflake
$cmax :: Snowflake -> Snowflake -> Snowflake
>= :: Snowflake -> Snowflake -> Bool
$c>= :: Snowflake -> Snowflake -> Bool
> :: Snowflake -> Snowflake -> Bool
$c> :: Snowflake -> Snowflake -> Bool
<= :: Snowflake -> Snowflake -> Bool
$c<= :: Snowflake -> Snowflake -> Bool
< :: Snowflake -> Snowflake -> Bool
$c< :: Snowflake -> Snowflake -> Bool
compare :: Snowflake -> Snowflake -> Ordering
$ccompare :: Snowflake -> Snowflake -> Ordering
Ord, Snowflake -> Snowflake -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Snowflake -> Snowflake -> Bool
$c/= :: Snowflake -> Snowflake -> Bool
== :: Snowflake -> Snowflake -> Bool
$c== :: Snowflake -> Snowflake -> Bool
Eq, Integer -> Snowflake
Snowflake -> Snowflake
Snowflake -> Snowflake -> Snowflake
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> Snowflake
$cfromInteger :: Integer -> Snowflake
signum :: Snowflake -> Snowflake
$csignum :: Snowflake -> Snowflake
abs :: Snowflake -> Snowflake
$cabs :: Snowflake -> Snowflake
negate :: Snowflake -> Snowflake
$cnegate :: Snowflake -> Snowflake
* :: Snowflake -> Snowflake -> Snowflake
$c* :: Snowflake -> Snowflake -> Snowflake
- :: Snowflake -> Snowflake -> Snowflake
$c- :: Snowflake -> Snowflake -> Snowflake
+ :: Snowflake -> Snowflake -> Snowflake
$c+ :: Snowflake -> Snowflake -> Snowflake
Num, Enum Snowflake
Real Snowflake
Snowflake -> Integer
Snowflake -> Snowflake -> (Snowflake, Snowflake)
Snowflake -> Snowflake -> Snowflake
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
toInteger :: Snowflake -> Integer
$ctoInteger :: Snowflake -> Integer
divMod :: Snowflake -> Snowflake -> (Snowflake, Snowflake)
$cdivMod :: Snowflake -> Snowflake -> (Snowflake, Snowflake)
quotRem :: Snowflake -> Snowflake -> (Snowflake, Snowflake)
$cquotRem :: Snowflake -> Snowflake -> (Snowflake, Snowflake)
mod :: Snowflake -> Snowflake -> Snowflake
$cmod :: Snowflake -> Snowflake -> Snowflake
div :: Snowflake -> Snowflake -> Snowflake
$cdiv :: Snowflake -> Snowflake -> Snowflake
rem :: Snowflake -> Snowflake -> Snowflake
$crem :: Snowflake -> Snowflake -> Snowflake
quot :: Snowflake -> Snowflake -> Snowflake
$cquot :: Snowflake -> Snowflake -> Snowflake
Integral, Int -> Snowflake
Snowflake -> Int
Snowflake -> [Snowflake]
Snowflake -> Snowflake
Snowflake -> Snowflake -> [Snowflake]
Snowflake -> Snowflake -> Snowflake -> [Snowflake]
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 :: Snowflake -> Snowflake -> Snowflake -> [Snowflake]
$cenumFromThenTo :: Snowflake -> Snowflake -> Snowflake -> [Snowflake]
enumFromTo :: Snowflake -> Snowflake -> [Snowflake]
$cenumFromTo :: Snowflake -> Snowflake -> [Snowflake]
enumFromThen :: Snowflake -> Snowflake -> [Snowflake]
$cenumFromThen :: Snowflake -> Snowflake -> [Snowflake]
enumFrom :: Snowflake -> [Snowflake]
$cenumFrom :: Snowflake -> [Snowflake]
fromEnum :: Snowflake -> Int
$cfromEnum :: Snowflake -> Int
toEnum :: Int -> Snowflake
$ctoEnum :: Int -> Snowflake
pred :: Snowflake -> Snowflake
$cpred :: Snowflake -> Snowflake
succ :: Snowflake -> Snowflake
$csucc :: Snowflake -> Snowflake
Enum, Num Snowflake
Ord Snowflake
Snowflake -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: Snowflake -> Rational
$ctoRational :: Snowflake -> Rational
Real, Eq Snowflake
Snowflake
Int -> Snowflake
Snowflake -> Bool
Snowflake -> Int
Snowflake -> Maybe Int
Snowflake -> Snowflake
Snowflake -> Int -> Bool
Snowflake -> Int -> Snowflake
Snowflake -> Snowflake -> Snowflake
forall a.
Eq a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> a
-> (Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> Bool)
-> (a -> Maybe Int)
-> (a -> Int)
-> (a -> Bool)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int)
-> Bits a
popCount :: Snowflake -> Int
$cpopCount :: Snowflake -> Int
rotateR :: Snowflake -> Int -> Snowflake
$crotateR :: Snowflake -> Int -> Snowflake
rotateL :: Snowflake -> Int -> Snowflake
$crotateL :: Snowflake -> Int -> Snowflake
unsafeShiftR :: Snowflake -> Int -> Snowflake
$cunsafeShiftR :: Snowflake -> Int -> Snowflake
shiftR :: Snowflake -> Int -> Snowflake
$cshiftR :: Snowflake -> Int -> Snowflake
unsafeShiftL :: Snowflake -> Int -> Snowflake
$cunsafeShiftL :: Snowflake -> Int -> Snowflake
shiftL :: Snowflake -> Int -> Snowflake
$cshiftL :: Snowflake -> Int -> Snowflake
isSigned :: Snowflake -> Bool
$cisSigned :: Snowflake -> Bool
bitSize :: Snowflake -> Int
$cbitSize :: Snowflake -> Int
bitSizeMaybe :: Snowflake -> Maybe Int
$cbitSizeMaybe :: Snowflake -> Maybe Int
testBit :: Snowflake -> Int -> Bool
$ctestBit :: Snowflake -> Int -> Bool
complementBit :: Snowflake -> Int -> Snowflake
$ccomplementBit :: Snowflake -> Int -> Snowflake
clearBit :: Snowflake -> Int -> Snowflake
$cclearBit :: Snowflake -> Int -> Snowflake
setBit :: Snowflake -> Int -> Snowflake
$csetBit :: Snowflake -> Int -> Snowflake
bit :: Int -> Snowflake
$cbit :: Int -> Snowflake
zeroBits :: Snowflake
$czeroBits :: Snowflake
rotate :: Snowflake -> Int -> Snowflake
$crotate :: Snowflake -> Int -> Snowflake
shift :: Snowflake -> Int -> Snowflake
$cshift :: Snowflake -> Int -> Snowflake
complement :: Snowflake -> Snowflake
$ccomplement :: Snowflake -> Snowflake
xor :: Snowflake -> Snowflake -> Snowflake
$cxor :: Snowflake -> Snowflake -> Snowflake
.|. :: Snowflake -> Snowflake -> Snowflake
$c.|. :: Snowflake -> Snowflake -> Snowflake
.&. :: Snowflake -> Snowflake -> Snowflake
$c.&. :: Snowflake -> Snowflake -> Snowflake
Bits)

instance Show Snowflake where
  show :: Snowflake -> String
show (Snowflake Word64
a) = forall a. Show a => a -> String
show Word64
a

instance Read Snowflake where
  readsPrec :: Int -> ReadS Snowflake
readsPrec Int
p = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Word64 -> Snowflake
Snowflake) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Read a => Int -> ReadS a
readsPrec Int
p

instance ToJSON Snowflake where
  toJSON :: Snowflake -> Value
toJSON (Snowflake Word64
snowflake) = Text -> Value
String forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Word64
snowflake

instance FromJSON Snowflake where
  parseJSON :: Value -> Parser Snowflake
parseJSON =
    forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText
      String
"Snowflake"
      ( \Text
snowflake ->
          case forall a. Read a => String -> Maybe a
readMaybe (Text -> String
T.unpack Text
snowflake) of
            Maybe Snowflake
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"null snowflake"
            (Just Snowflake
i) -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Snowflake
i
      )

instance ToHttpApiData Snowflake where
  toUrlPiece :: Snowflake -> Text
toUrlPiece = String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show

newtype RolePermissions = RolePermissions { RolePermissions -> Integer
getRolePermissions :: Integer } 
  deriving (RolePermissions -> RolePermissions -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RolePermissions -> RolePermissions -> Bool
$c/= :: RolePermissions -> RolePermissions -> Bool
== :: RolePermissions -> RolePermissions -> Bool
$c== :: RolePermissions -> RolePermissions -> Bool
Eq, Eq RolePermissions
RolePermissions -> RolePermissions -> Bool
RolePermissions -> RolePermissions -> Ordering
RolePermissions -> RolePermissions -> RolePermissions
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: RolePermissions -> RolePermissions -> RolePermissions
$cmin :: RolePermissions -> RolePermissions -> RolePermissions
max :: RolePermissions -> RolePermissions -> RolePermissions
$cmax :: RolePermissions -> RolePermissions -> RolePermissions
>= :: RolePermissions -> RolePermissions -> Bool
$c>= :: RolePermissions -> RolePermissions -> Bool
> :: RolePermissions -> RolePermissions -> Bool
$c> :: RolePermissions -> RolePermissions -> Bool
<= :: RolePermissions -> RolePermissions -> Bool
$c<= :: RolePermissions -> RolePermissions -> Bool
< :: RolePermissions -> RolePermissions -> Bool
$c< :: RolePermissions -> RolePermissions -> Bool
compare :: RolePermissions -> RolePermissions -> Ordering
$ccompare :: RolePermissions -> RolePermissions -> Ordering
Ord, Integer -> RolePermissions
RolePermissions -> RolePermissions
RolePermissions -> RolePermissions -> RolePermissions
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> RolePermissions
$cfromInteger :: Integer -> RolePermissions
signum :: RolePermissions -> RolePermissions
$csignum :: RolePermissions -> RolePermissions
abs :: RolePermissions -> RolePermissions
$cabs :: RolePermissions -> RolePermissions
negate :: RolePermissions -> RolePermissions
$cnegate :: RolePermissions -> RolePermissions
* :: RolePermissions -> RolePermissions -> RolePermissions
$c* :: RolePermissions -> RolePermissions -> RolePermissions
- :: RolePermissions -> RolePermissions -> RolePermissions
$c- :: RolePermissions -> RolePermissions -> RolePermissions
+ :: RolePermissions -> RolePermissions -> RolePermissions
$c+ :: RolePermissions -> RolePermissions -> RolePermissions
Num, Eq RolePermissions
RolePermissions
Int -> RolePermissions
RolePermissions -> Bool
RolePermissions -> Int
RolePermissions -> Maybe Int
RolePermissions -> RolePermissions
RolePermissions -> Int -> Bool
RolePermissions -> Int -> RolePermissions
RolePermissions -> RolePermissions -> RolePermissions
forall a.
Eq a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> a
-> (Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> Bool)
-> (a -> Maybe Int)
-> (a -> Int)
-> (a -> Bool)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int)
-> Bits a
popCount :: RolePermissions -> Int
$cpopCount :: RolePermissions -> Int
rotateR :: RolePermissions -> Int -> RolePermissions
$crotateR :: RolePermissions -> Int -> RolePermissions
rotateL :: RolePermissions -> Int -> RolePermissions
$crotateL :: RolePermissions -> Int -> RolePermissions
unsafeShiftR :: RolePermissions -> Int -> RolePermissions
$cunsafeShiftR :: RolePermissions -> Int -> RolePermissions
shiftR :: RolePermissions -> Int -> RolePermissions
$cshiftR :: RolePermissions -> Int -> RolePermissions
unsafeShiftL :: RolePermissions -> Int -> RolePermissions
$cunsafeShiftL :: RolePermissions -> Int -> RolePermissions
shiftL :: RolePermissions -> Int -> RolePermissions
$cshiftL :: RolePermissions -> Int -> RolePermissions
isSigned :: RolePermissions -> Bool
$cisSigned :: RolePermissions -> Bool
bitSize :: RolePermissions -> Int
$cbitSize :: RolePermissions -> Int
bitSizeMaybe :: RolePermissions -> Maybe Int
$cbitSizeMaybe :: RolePermissions -> Maybe Int
testBit :: RolePermissions -> Int -> Bool
$ctestBit :: RolePermissions -> Int -> Bool
complementBit :: RolePermissions -> Int -> RolePermissions
$ccomplementBit :: RolePermissions -> Int -> RolePermissions
clearBit :: RolePermissions -> Int -> RolePermissions
$cclearBit :: RolePermissions -> Int -> RolePermissions
setBit :: RolePermissions -> Int -> RolePermissions
$csetBit :: RolePermissions -> Int -> RolePermissions
bit :: Int -> RolePermissions
$cbit :: Int -> RolePermissions
zeroBits :: RolePermissions
$czeroBits :: RolePermissions
rotate :: RolePermissions -> Int -> RolePermissions
$crotate :: RolePermissions -> Int -> RolePermissions
shift :: RolePermissions -> Int -> RolePermissions
$cshift :: RolePermissions -> Int -> RolePermissions
complement :: RolePermissions -> RolePermissions
$ccomplement :: RolePermissions -> RolePermissions
xor :: RolePermissions -> RolePermissions -> RolePermissions
$cxor :: RolePermissions -> RolePermissions -> RolePermissions
.|. :: RolePermissions -> RolePermissions -> RolePermissions
$c.|. :: RolePermissions -> RolePermissions -> RolePermissions
.&. :: RolePermissions -> RolePermissions -> RolePermissions
$c.&. :: RolePermissions -> RolePermissions -> RolePermissions
Bits, Int -> RolePermissions
RolePermissions -> Int
RolePermissions -> [RolePermissions]
RolePermissions -> RolePermissions
RolePermissions -> RolePermissions -> [RolePermissions]
RolePermissions
-> RolePermissions -> RolePermissions -> [RolePermissions]
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 :: RolePermissions
-> RolePermissions -> RolePermissions -> [RolePermissions]
$cenumFromThenTo :: RolePermissions
-> RolePermissions -> RolePermissions -> [RolePermissions]
enumFromTo :: RolePermissions -> RolePermissions -> [RolePermissions]
$cenumFromTo :: RolePermissions -> RolePermissions -> [RolePermissions]
enumFromThen :: RolePermissions -> RolePermissions -> [RolePermissions]
$cenumFromThen :: RolePermissions -> RolePermissions -> [RolePermissions]
enumFrom :: RolePermissions -> [RolePermissions]
$cenumFrom :: RolePermissions -> [RolePermissions]
fromEnum :: RolePermissions -> Int
$cfromEnum :: RolePermissions -> Int
toEnum :: Int -> RolePermissions
$ctoEnum :: Int -> RolePermissions
pred :: RolePermissions -> RolePermissions
$cpred :: RolePermissions -> RolePermissions
succ :: RolePermissions -> RolePermissions
$csucc :: RolePermissions -> RolePermissions
Enum, Num RolePermissions
Ord RolePermissions
RolePermissions -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: RolePermissions -> Rational
$ctoRational :: RolePermissions -> Rational
Real, Enum RolePermissions
Real RolePermissions
RolePermissions -> Integer
RolePermissions
-> RolePermissions -> (RolePermissions, RolePermissions)
RolePermissions -> RolePermissions -> RolePermissions
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
toInteger :: RolePermissions -> Integer
$ctoInteger :: RolePermissions -> Integer
divMod :: RolePermissions
-> RolePermissions -> (RolePermissions, RolePermissions)
$cdivMod :: RolePermissions
-> RolePermissions -> (RolePermissions, RolePermissions)
quotRem :: RolePermissions
-> RolePermissions -> (RolePermissions, RolePermissions)
$cquotRem :: RolePermissions
-> RolePermissions -> (RolePermissions, RolePermissions)
mod :: RolePermissions -> RolePermissions -> RolePermissions
$cmod :: RolePermissions -> RolePermissions -> RolePermissions
div :: RolePermissions -> RolePermissions -> RolePermissions
$cdiv :: RolePermissions -> RolePermissions -> RolePermissions
rem :: RolePermissions -> RolePermissions -> RolePermissions
$crem :: RolePermissions -> RolePermissions -> RolePermissions
quot :: RolePermissions -> RolePermissions -> RolePermissions
$cquot :: RolePermissions -> RolePermissions -> RolePermissions
Integral)

instance Read RolePermissions where
  readsPrec :: Int -> ReadS RolePermissions
readsPrec Int
p = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Integer -> RolePermissions
RolePermissions) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Read a => Int -> ReadS a
readsPrec Int
p

instance ToJSON RolePermissions where
  toJSON :: RolePermissions -> Value
toJSON = forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. RolePermissions -> Integer
getRolePermissions

-- In v8 and above, all permissions are serialized as strings.
-- See https://discord.com/developers/docs/topics/permissions#permissions.
instance FromJSON RolePermissions where
  parseJSON :: Value -> Parser RolePermissions
parseJSON = forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"RolePermissions" forall a b. (a -> b) -> a -> b
$
      \Text
text -> case forall a. Read a => String -> Maybe a
readMaybe (Text -> String
T.unpack Text
text) of
              Just Integer
perms -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Integer -> RolePermissions
RolePermissions Integer
perms
              Maybe Integer
Nothing    -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalid role permissions integer string"

instance Show RolePermissions where
  show :: RolePermissions -> String
show = forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. RolePermissions -> Integer
getRolePermissions

newtype DiscordId a = DiscordId { forall a. DiscordId a -> Snowflake
unId :: Snowflake }
  deriving (DiscordId a -> DiscordId a -> Bool
DiscordId a -> DiscordId a -> Ordering
DiscordId a -> DiscordId a -> DiscordId a
forall {a}. Eq (DiscordId a)
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. DiscordId a -> DiscordId a -> Bool
forall a. DiscordId a -> DiscordId a -> Ordering
forall a. DiscordId a -> DiscordId a -> DiscordId a
min :: DiscordId a -> DiscordId a -> DiscordId a
$cmin :: forall a. DiscordId a -> DiscordId a -> DiscordId a
max :: DiscordId a -> DiscordId a -> DiscordId a
$cmax :: forall a. DiscordId a -> DiscordId a -> DiscordId a
>= :: DiscordId a -> DiscordId a -> Bool
$c>= :: forall a. DiscordId a -> DiscordId a -> Bool
> :: DiscordId a -> DiscordId a -> Bool
$c> :: forall a. DiscordId a -> DiscordId a -> Bool
<= :: DiscordId a -> DiscordId a -> Bool
$c<= :: forall a. DiscordId a -> DiscordId a -> Bool
< :: DiscordId a -> DiscordId a -> Bool
$c< :: forall a. DiscordId a -> DiscordId a -> Bool
compare :: DiscordId a -> DiscordId a -> Ordering
$ccompare :: forall a. DiscordId a -> DiscordId a -> Ordering
Ord, DiscordId a -> DiscordId a -> Bool
forall a. DiscordId a -> DiscordId a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DiscordId a -> DiscordId a -> Bool
$c/= :: forall a. DiscordId a -> DiscordId a -> Bool
== :: DiscordId a -> DiscordId a -> Bool
$c== :: forall a. DiscordId a -> DiscordId a -> Bool
Eq, Integer -> DiscordId a
DiscordId a -> DiscordId a
DiscordId a -> DiscordId a -> DiscordId a
forall a. Integer -> DiscordId a
forall a. DiscordId a -> DiscordId a
forall a. DiscordId a -> DiscordId a -> DiscordId a
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> DiscordId a
$cfromInteger :: forall a. Integer -> DiscordId a
signum :: DiscordId a -> DiscordId a
$csignum :: forall a. DiscordId a -> DiscordId a
abs :: DiscordId a -> DiscordId a
$cabs :: forall a. DiscordId a -> DiscordId a
negate :: DiscordId a -> DiscordId a
$cnegate :: forall a. DiscordId a -> DiscordId a
* :: DiscordId a -> DiscordId a -> DiscordId a
$c* :: forall a. DiscordId a -> DiscordId a -> DiscordId a
- :: DiscordId a -> DiscordId a -> DiscordId a
$c- :: forall a. DiscordId a -> DiscordId a -> DiscordId a
+ :: DiscordId a -> DiscordId a -> DiscordId a
$c+ :: forall a. DiscordId a -> DiscordId a -> DiscordId a
Num, DiscordId a -> Integer
DiscordId a -> DiscordId a -> (DiscordId a, DiscordId a)
DiscordId a -> DiscordId a -> DiscordId a
forall {a}. Enum (DiscordId a)
forall {a}. Real (DiscordId a)
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
forall a. DiscordId a -> Integer
forall a. DiscordId a -> DiscordId a -> (DiscordId a, DiscordId a)
forall a. DiscordId a -> DiscordId a -> DiscordId a
toInteger :: DiscordId a -> Integer
$ctoInteger :: forall a. DiscordId a -> Integer
divMod :: DiscordId a -> DiscordId a -> (DiscordId a, DiscordId a)
$cdivMod :: forall a. DiscordId a -> DiscordId a -> (DiscordId a, DiscordId a)
quotRem :: DiscordId a -> DiscordId a -> (DiscordId a, DiscordId a)
$cquotRem :: forall a. DiscordId a -> DiscordId a -> (DiscordId a, DiscordId a)
mod :: DiscordId a -> DiscordId a -> DiscordId a
$cmod :: forall a. DiscordId a -> DiscordId a -> DiscordId a
div :: DiscordId a -> DiscordId a -> DiscordId a
$cdiv :: forall a. DiscordId a -> DiscordId a -> DiscordId a
rem :: DiscordId a -> DiscordId a -> DiscordId a
$crem :: forall a. DiscordId a -> DiscordId a -> DiscordId a
quot :: DiscordId a -> DiscordId a -> DiscordId a
$cquot :: forall a. DiscordId a -> DiscordId a -> DiscordId a
Integral, Int -> DiscordId a
DiscordId a -> Int
DiscordId a -> [DiscordId a]
DiscordId a -> DiscordId a
DiscordId a -> DiscordId a -> [DiscordId a]
DiscordId a -> DiscordId a -> DiscordId a -> [DiscordId a]
forall a. Int -> DiscordId a
forall a. DiscordId a -> Int
forall a. DiscordId a -> [DiscordId a]
forall a. DiscordId a -> DiscordId a
forall a. DiscordId a -> DiscordId a -> [DiscordId a]
forall a.
DiscordId a -> DiscordId a -> DiscordId a -> [DiscordId a]
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 :: DiscordId a -> DiscordId a -> DiscordId a -> [DiscordId a]
$cenumFromThenTo :: forall a.
DiscordId a -> DiscordId a -> DiscordId a -> [DiscordId a]
enumFromTo :: DiscordId a -> DiscordId a -> [DiscordId a]
$cenumFromTo :: forall a. DiscordId a -> DiscordId a -> [DiscordId a]
enumFromThen :: DiscordId a -> DiscordId a -> [DiscordId a]
$cenumFromThen :: forall a. DiscordId a -> DiscordId a -> [DiscordId a]
enumFrom :: DiscordId a -> [DiscordId a]
$cenumFrom :: forall a. DiscordId a -> [DiscordId a]
fromEnum :: DiscordId a -> Int
$cfromEnum :: forall a. DiscordId a -> Int
toEnum :: Int -> DiscordId a
$ctoEnum :: forall a. Int -> DiscordId a
pred :: DiscordId a -> DiscordId a
$cpred :: forall a. DiscordId a -> DiscordId a
succ :: DiscordId a -> DiscordId a
$csucc :: forall a. DiscordId a -> DiscordId a
Enum, DiscordId a -> Rational
forall a. Num (DiscordId a)
forall a. Ord (DiscordId a)
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
forall a. DiscordId a -> Rational
toRational :: DiscordId a -> Rational
$ctoRational :: forall a. DiscordId a -> Rational
Real, DiscordId a
Int -> DiscordId a
DiscordId a -> Bool
DiscordId a -> Int
DiscordId a -> Maybe Int
DiscordId a -> DiscordId a
DiscordId a -> Int -> Bool
DiscordId a -> Int -> DiscordId a
DiscordId a -> DiscordId a -> DiscordId a
forall {a}. Eq (DiscordId a)
forall a. DiscordId a
forall a.
Eq a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> a
-> (Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> Bool)
-> (a -> Maybe Int)
-> (a -> Int)
-> (a -> Bool)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int)
-> Bits a
forall a. Int -> DiscordId a
forall a. DiscordId a -> Bool
forall a. DiscordId a -> Int
forall a. DiscordId a -> Maybe Int
forall a. DiscordId a -> DiscordId a
forall a. DiscordId a -> Int -> Bool
forall a. DiscordId a -> Int -> DiscordId a
forall a. DiscordId a -> DiscordId a -> DiscordId a
popCount :: DiscordId a -> Int
$cpopCount :: forall a. DiscordId a -> Int
rotateR :: DiscordId a -> Int -> DiscordId a
$crotateR :: forall a. DiscordId a -> Int -> DiscordId a
rotateL :: DiscordId a -> Int -> DiscordId a
$crotateL :: forall a. DiscordId a -> Int -> DiscordId a
unsafeShiftR :: DiscordId a -> Int -> DiscordId a
$cunsafeShiftR :: forall a. DiscordId a -> Int -> DiscordId a
shiftR :: DiscordId a -> Int -> DiscordId a
$cshiftR :: forall a. DiscordId a -> Int -> DiscordId a
unsafeShiftL :: DiscordId a -> Int -> DiscordId a
$cunsafeShiftL :: forall a. DiscordId a -> Int -> DiscordId a
shiftL :: DiscordId a -> Int -> DiscordId a
$cshiftL :: forall a. DiscordId a -> Int -> DiscordId a
isSigned :: DiscordId a -> Bool
$cisSigned :: forall a. DiscordId a -> Bool
bitSize :: DiscordId a -> Int
$cbitSize :: forall a. DiscordId a -> Int
bitSizeMaybe :: DiscordId a -> Maybe Int
$cbitSizeMaybe :: forall a. DiscordId a -> Maybe Int
testBit :: DiscordId a -> Int -> Bool
$ctestBit :: forall a. DiscordId a -> Int -> Bool
complementBit :: DiscordId a -> Int -> DiscordId a
$ccomplementBit :: forall a. DiscordId a -> Int -> DiscordId a
clearBit :: DiscordId a -> Int -> DiscordId a
$cclearBit :: forall a. DiscordId a -> Int -> DiscordId a
setBit :: DiscordId a -> Int -> DiscordId a
$csetBit :: forall a. DiscordId a -> Int -> DiscordId a
bit :: Int -> DiscordId a
$cbit :: forall a. Int -> DiscordId a
zeroBits :: DiscordId a
$czeroBits :: forall a. DiscordId a
rotate :: DiscordId a -> Int -> DiscordId a
$crotate :: forall a. DiscordId a -> Int -> DiscordId a
shift :: DiscordId a -> Int -> DiscordId a
$cshift :: forall a. DiscordId a -> Int -> DiscordId a
complement :: DiscordId a -> DiscordId a
$ccomplement :: forall a. DiscordId a -> DiscordId a
xor :: DiscordId a -> DiscordId a -> DiscordId a
$cxor :: forall a. DiscordId a -> DiscordId a -> DiscordId a
.|. :: DiscordId a -> DiscordId a -> DiscordId a
$c.|. :: forall a. DiscordId a -> DiscordId a -> DiscordId a
.&. :: DiscordId a -> DiscordId a -> DiscordId a
$c.&. :: forall a. DiscordId a -> DiscordId a -> DiscordId a
Bits)

instance Show (DiscordId a) where
  show :: DiscordId a -> String
show = forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. DiscordId a -> Snowflake
unId

instance Read (DiscordId a) where
  readsPrec :: Int -> ReadS (DiscordId a)
readsPrec Int
p = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first forall a. Snowflake -> DiscordId a
DiscordId) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Read a => Int -> ReadS a
readsPrec Int
p

instance ToJSON (DiscordId a) where
  toJSON :: DiscordId a -> Value
toJSON = forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. DiscordId a -> Snowflake
unId

instance FromJSON (DiscordId a) where
  parseJSON :: Value -> Parser (DiscordId a)
parseJSON = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Snowflake -> DiscordId a
DiscordId forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. FromJSON a => Value -> Parser a
parseJSON

instance ToHttpApiData (DiscordId a) where
  toUrlPiece :: DiscordId a -> Text
toUrlPiece = String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show

data ChannelIdType
type ChannelId = DiscordId ChannelIdType

data StageIdType
type StageId = DiscordId StageIdType

data GuildIdType
type GuildId = DiscordId GuildIdType

data MessageIdType
type MessageId = DiscordId MessageIdType

data AttachmentIdType
type AttachmentId = DiscordId AttachmentIdType

data EmojiIdType
type EmojiId = DiscordId EmojiIdType

data StickerIdType
type StickerId = DiscordId StickerIdType

data UserIdType
type UserId = DiscordId UserIdType

data RoleIdType
type RoleId = DiscordId RoleIdType

data IntegrationIdType
type IntegrationId = DiscordId IntegrationIdType

data WebhookIdType
type WebhookId = DiscordId WebhookIdType

data ParentIdType
type ParentId = DiscordId ParentIdType

data ApplicationIdType
type ApplicationId = DiscordId ApplicationIdType

data ApplicationCommandIdType
type ApplicationCommandId = DiscordId ApplicationCommandIdType

data InteractionIdType
type InteractionId = DiscordId InteractionIdType

data ScheduledEventIdType
type ScheduledEventId = DiscordId ScheduledEventIdType

data ScheduledEventEntityIdType
type ScheduledEventEntityId = DiscordId ScheduledEventEntityIdType

newtype DiscordToken a = DiscordToken { forall a. DiscordToken a -> Text
unToken :: T.Text }
  deriving (DiscordToken a -> DiscordToken a -> Bool
DiscordToken a -> DiscordToken a -> Ordering
DiscordToken a -> DiscordToken a -> DiscordToken a
forall {a}. Eq (DiscordToken a)
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. DiscordToken a -> DiscordToken a -> Bool
forall a. DiscordToken a -> DiscordToken a -> Ordering
forall a. DiscordToken a -> DiscordToken a -> DiscordToken a
min :: DiscordToken a -> DiscordToken a -> DiscordToken a
$cmin :: forall a. DiscordToken a -> DiscordToken a -> DiscordToken a
max :: DiscordToken a -> DiscordToken a -> DiscordToken a
$cmax :: forall a. DiscordToken a -> DiscordToken a -> DiscordToken a
>= :: DiscordToken a -> DiscordToken a -> Bool
$c>= :: forall a. DiscordToken a -> DiscordToken a -> Bool
> :: DiscordToken a -> DiscordToken a -> Bool
$c> :: forall a. DiscordToken a -> DiscordToken a -> Bool
<= :: DiscordToken a -> DiscordToken a -> Bool
$c<= :: forall a. DiscordToken a -> DiscordToken a -> Bool
< :: DiscordToken a -> DiscordToken a -> Bool
$c< :: forall a. DiscordToken a -> DiscordToken a -> Bool
compare :: DiscordToken a -> DiscordToken a -> Ordering
$ccompare :: forall a. DiscordToken a -> DiscordToken a -> Ordering
Ord, DiscordToken a -> DiscordToken a -> Bool
forall a. DiscordToken a -> DiscordToken a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DiscordToken a -> DiscordToken a -> Bool
$c/= :: forall a. DiscordToken a -> DiscordToken a -> Bool
== :: DiscordToken a -> DiscordToken a -> Bool
$c== :: forall a. DiscordToken a -> DiscordToken a -> Bool
Eq)

instance Show (DiscordToken a) where
  show :: DiscordToken a -> String
show = forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. DiscordToken a -> Text
unToken

instance Read (DiscordToken a) where
  readsPrec :: Int -> ReadS (DiscordToken a)
readsPrec Int
p = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first forall a. Text -> DiscordToken a
DiscordToken) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Read a => Int -> ReadS a
readsPrec Int
p

instance ToJSON (DiscordToken a) where
  toJSON :: DiscordToken a -> Value
toJSON = forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. DiscordToken a -> Text
unToken

instance FromJSON (DiscordToken a) where
  parseJSON :: Value -> Parser (DiscordToken a)
parseJSON = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Text -> DiscordToken a
DiscordToken forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. FromJSON a => Value -> Parser a
parseJSON

instance ToHttpApiData (DiscordToken a) where
  toUrlPiece :: DiscordToken a -> Text
toUrlPiece = forall a. DiscordToken a -> Text
unToken

type InteractionToken = DiscordToken InteractionIdType

type WebhookToken = DiscordToken WebhookIdType

type Shard = (Int, Int)

-- | Gets a creation date from a snowflake.
snowflakeCreationDate :: Snowflake -> UTCTime
snowflakeCreationDate :: Snowflake -> UTCTime
snowflakeCreationDate Snowflake
x = POSIXTime -> UTCTime
posixSecondsToUTCTime forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Real a, Fractional b) => a -> b
realToFrac
  forall a b. (a -> b) -> a -> b
$ Snowflake
1420070400 forall a. Num a => a -> a -> a
+ forall a. Integral a => a -> a -> a
quot (forall a. Bits a => a -> Int -> a
shiftR Snowflake
x Int
22) Snowflake
1000

-- | Default timestamp
epochTime :: UTCTime
epochTime :: UTCTime
epochTime = POSIXTime -> UTCTime
posixSecondsToUTCTime POSIXTime
0

{-

InternalDiscordEnum is a hack-y typeclass, but it's the best solution overall.
The best we can do is prevent the end-user from seeing this.

typeclass Bounded (minBound + maxBound) could replace discordTypeStartValue, but
it can't derive instances for types like DiscordColor, which have simple sum types involved.

typeclass Enum (toEnum + fromEnum) requires defining both A->Int and Int->A.
If we handle both at once (with an inline map), it's no longer typesafe.

External packages exist, but bloat our dependencies

-}
class Data a => InternalDiscordEnum a where
  discordTypeStartValue :: a
  fromDiscordType :: a -> Int
  discordTypeTable :: [(Int, a)]
  discordTypeTable =  forall a b. (a -> b) -> [a] -> [b]
map (\a
d -> (forall a. InternalDiscordEnum a => a -> Int
fromDiscordType a
d, a
d)) (forall b. Data b => b -> [b]
makeTable forall a. InternalDiscordEnum a => a
discordTypeStartValue)
    where
      makeTable :: Data b => b -> [b]
      makeTable :: forall b. Data b => b -> [b]
makeTable b
t = forall a b. (a -> b) -> [a] -> [b]
map forall a. Data a => Constr -> a
fromConstr (DataType -> [Constr]
dataTypeConstrs forall a b. (a -> b) -> a -> b
$ forall a. Data a => a -> DataType
dataTypeOf b
t)

  discordTypeParseJSON :: String -> Value -> Parser a
  discordTypeParseJSON String
name =
    forall a. String -> (Scientific -> Parser a) -> Value -> Parser a
withScientific
      String
name
      ( \Scientific
i -> do
          case forall {a} {a}. (RealFrac a, Integral a) => a -> Maybe a
maybeInt Scientific
i forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` forall a. InternalDiscordEnum a => [(Int, a)]
discordTypeTable) of
            Maybe a
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"could not parse type: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Scientific
i
            Just a
d -> forall (m :: * -> *) a. Monad m => a -> m a
return a
d
      )
    where
      maybeInt :: a -> Maybe a
maybeInt a
i
        | forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (RealFrac a, Integral b) => a -> b
round a
i) forall a. Eq a => a -> a -> Bool
== a
i = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a b. (RealFrac a, Integral b) => a -> b
round a
i
        | Bool
otherwise = forall a. Maybe a
Nothing

-- Aeson 2.0 uses KeyMaps with a defined Key type for its objects. Aeson up to
-- 1.5 uses HashMaps with Text for the key. Both types have an IsString instance.
-- To keep our version bounds as loose as possible while the Haskell ecosystem
-- (and thus our users) switch over to Aeson 2.0, we use some CPP to define a
-- AesonKey as an alias.
#if MIN_VERSION_aeson(2, 0, 0)
type AesonKey = Key.Key
#else
type AesonKey = T.Text
#endif


(.==) :: ToJSON a => AesonKey -> a -> Maybe Pair
AesonKey
k .== :: forall a. ToJSON a => AesonKey -> a -> Maybe Pair
.== a
v = forall a. a -> Maybe a
Just (AesonKey
k forall kv v. (KeyValue kv, ToJSON v) => AesonKey -> v -> kv
.= a
v)

(.=?) :: ToJSON a => AesonKey -> Maybe a -> Maybe Pair
AesonKey
k .=? :: forall a. ToJSON a => AesonKey -> Maybe a -> Maybe Pair
.=? (Just a
v) = forall a. a -> Maybe a
Just (AesonKey
k forall kv v. (KeyValue kv, ToJSON v) => AesonKey -> v -> kv
.= a
v)
AesonKey
_ .=? Maybe a
Nothing = forall a. Maybe a
Nothing

objectFromMaybes :: [Maybe Pair] -> Value
objectFromMaybes :: [Maybe Pair] -> Value
objectFromMaybes = [Pair] -> Value
object forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [Maybe a] -> [a]
catMaybes


-- | @Base64Image mime data@ represents the base64 encoding of an image (as
-- @data@), together with a tag of its mime type (@mime@).  The constructor is
-- only for Internal use, and its public export is hidden in Discord.Types.
--
-- Public creation of this datatype should be done using the relevant smart
-- constructors for Emoji, Sticker, or Avatar.
data Base64Image a = Base64Image T.Text T.Text
  deriving (Int -> Base64Image a -> ShowS
forall a. Int -> Base64Image a -> ShowS
forall a. [Base64Image a] -> ShowS
forall a. Base64Image a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Base64Image a] -> ShowS
$cshowList :: forall a. [Base64Image a] -> ShowS
show :: Base64Image a -> String
$cshow :: forall a. Base64Image a -> String
showsPrec :: Int -> Base64Image a -> ShowS
$cshowsPrec :: forall a. Int -> Base64Image a -> ShowS
Show, ReadPrec [Base64Image a]
ReadPrec (Base64Image a)
ReadS [Base64Image a]
forall a. ReadPrec [Base64Image a]
forall a. ReadPrec (Base64Image a)
forall a. Int -> ReadS (Base64Image a)
forall a. ReadS [Base64Image a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Base64Image a]
$creadListPrec :: forall a. ReadPrec [Base64Image a]
readPrec :: ReadPrec (Base64Image a)
$creadPrec :: forall a. ReadPrec (Base64Image a)
readList :: ReadS [Base64Image a]
$creadList :: forall a. ReadS [Base64Image a]
readsPrec :: Int -> ReadS (Base64Image a)
$creadsPrec :: forall a. Int -> ReadS (Base64Image a)
Read, Base64Image a -> Base64Image a -> Bool
forall a. Base64Image a -> Base64Image a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Base64Image a -> Base64Image a -> Bool
$c/= :: forall a. Base64Image a -> Base64Image a -> Bool
== :: Base64Image a -> Base64Image a -> Bool
$c== :: forall a. Base64Image a -> Base64Image a -> Bool
Eq, Base64Image a -> Base64Image a -> Bool
Base64Image a -> Base64Image a -> Ordering
forall a. Eq (Base64Image a)
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Base64Image a -> Base64Image a -> Bool
forall a. Base64Image a -> Base64Image a -> Ordering
forall a. Base64Image a -> Base64Image a -> Base64Image a
min :: Base64Image a -> Base64Image a -> Base64Image a
$cmin :: forall a. Base64Image a -> Base64Image a -> Base64Image a
max :: Base64Image a -> Base64Image a -> Base64Image a
$cmax :: forall a. Base64Image a -> Base64Image a -> Base64Image a
>= :: Base64Image a -> Base64Image a -> Bool
$c>= :: forall a. Base64Image a -> Base64Image a -> Bool
> :: Base64Image a -> Base64Image a -> Bool
$c> :: forall a. Base64Image a -> Base64Image a -> Bool
<= :: Base64Image a -> Base64Image a -> Bool
$c<= :: forall a. Base64Image a -> Base64Image a -> Bool
< :: Base64Image a -> Base64Image a -> Bool
$c< :: forall a. Base64Image a -> Base64Image a -> Bool
compare :: Base64Image a -> Base64Image a -> Ordering
$ccompare :: forall a. Base64Image a -> Base64Image a -> Ordering
Ord)

-- | The ToJSON instance for Base64Image creates a string representation of the
-- image's base-64 data, suited for using as JSON values.
--
-- The format is: @data:%MIME%;base64,%DATA%@.
instance ToJSON (Base64Image a) where
  toJSON :: Base64Image a -> Value
toJSON (Base64Image Text
mime Text
im) = Text -> Value
String forall a b. (a -> b) -> a -> b
$ Text
"data:" forall a. Semigroup a => a -> a -> a
<> Text
mime forall a. Semigroup a => a -> a -> a
<> Text
";base64," forall a. Semigroup a => a -> a -> a
<> Text
im

-- | @getMimeType bs@ returns a possible mimetype for the given bytestring,
-- based on the first few magic bytes. It may return any of PNG/JPEG/GIF or WEBP
-- mimetypes, or Nothing if none are matched.
--
-- Reference: https://en.wikipedia.org/wiki/List_of_file_signatures
--
-- Although Discord's official documentation does not state WEBP as a supported
-- format, it has been accepted for both emojis and user avatars no problem
-- when tested manually.
--
-- /Inspired by discord.py's implementation./
getMimeType :: B.ByteString -> Maybe T.Text
getMimeType :: ByteString -> Maybe Text
getMimeType ByteString
bs
  | Int -> ByteString -> ByteString
B.take Int
8 ByteString
bs forall a. Eq a => a -> a -> Bool
== ByteString
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"
  = forall a. a -> Maybe a
Just Text
"image/png"
  | Int -> ByteString -> ByteString
B.take Int
3 ByteString
bs forall a. Eq a => a -> a -> Bool
== ByteString
"\xff\xd8\xff" Bool -> Bool -> Bool
|| Int -> ByteString -> ByteString
B.take Int
4 (Int -> ByteString -> ByteString
B.drop Int
6 ByteString
bs) forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ByteString
"JFIF", ByteString
"Exif"]
  = forall a. a -> Maybe a
Just Text
"image/jpeg"
  | Int -> ByteString -> ByteString
B.take Int
6 ByteString
bs forall a. Eq a => a -> a -> Bool
== ByteString
"\x47\x49\x46\x38\x37\x61" Bool -> Bool -> Bool
|| Int -> ByteString -> ByteString
B.take Int
6 ByteString
bs forall a. Eq a => a -> a -> Bool
== ByteString
"\x47\x49\x46\x38\x39\x61"
  = forall a. a -> Maybe a
Just Text
"image/gif"
  | Int -> ByteString -> ByteString
B.take Int
4 ByteString
bs forall a. Eq a => a -> a -> Bool
== ByteString
"RIFF" Bool -> Bool -> Bool
&& Int -> ByteString -> ByteString
B.take Int
4 (Int -> ByteString -> ByteString
B.drop Int
8 ByteString
bs) forall a. Eq a => a -> a -> Bool
== ByteString
"WEBP"
  = forall a. a -> Maybe a
Just Text
"image/webp"
  | Bool
otherwise = forall a. Maybe a
Nothing

-- | The different channel types. Used for application commands and components.
--
-- https://discord.com/developers/docs/resources/channel#channel-object-channel-types
data ChannelTypeOption
  = -- | A text channel in a server.
    ChannelTypeOptionGuildText
  | -- | A direct message between users.
    ChannelTypeOptionDM
  | -- | A voice channel in a server.
    ChannelTypeOptionGuildVoice
  | -- | A direct message between multiple users.
    ChannelTypeOptionGroupDM
  | -- | An organizational category that contains up to 50 channels.
    ChannelTypeOptionGuildCategory
  | -- | A channel that users can follow and crosspost into their own server.
    ChannelTypeOptionGuildNews
  | -- | A channel in which game developers can sell their game on discord.
    ChannelTypeOptionGuildStore
  | -- | A temporary sub-channel within a guild_news channel.
    ChannelTypeOptionGuildNewsThread
  | -- | A temporary sub-channel within a guild_text channel.
    ChannelTypeOptionGuildPublicThread
  | -- | A temporary sub-channel within a GUILD_TEXT channel that is only
    -- viewable by those invited and those with the MANAGE_THREADS permission
    ChannelTypeOptionGuildPrivateThread
  | -- | A voice channel for hosting events with an audience.
    ChannelTypeOptionGuildStageVoice
  deriving (Int -> ChannelTypeOption -> ShowS
[ChannelTypeOption] -> ShowS
ChannelTypeOption -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ChannelTypeOption] -> ShowS
$cshowList :: [ChannelTypeOption] -> ShowS
show :: ChannelTypeOption -> String
$cshow :: ChannelTypeOption -> String
showsPrec :: Int -> ChannelTypeOption -> ShowS
$cshowsPrec :: Int -> ChannelTypeOption -> ShowS
Show, ReadPrec [ChannelTypeOption]
ReadPrec ChannelTypeOption
Int -> ReadS ChannelTypeOption
ReadS [ChannelTypeOption]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [ChannelTypeOption]
$creadListPrec :: ReadPrec [ChannelTypeOption]
readPrec :: ReadPrec ChannelTypeOption
$creadPrec :: ReadPrec ChannelTypeOption
readList :: ReadS [ChannelTypeOption]
$creadList :: ReadS [ChannelTypeOption]
readsPrec :: Int -> ReadS ChannelTypeOption
$creadsPrec :: Int -> ReadS ChannelTypeOption
Read, Typeable ChannelTypeOption
ChannelTypeOption -> DataType
ChannelTypeOption -> Constr
(forall b. Data b => b -> b)
-> ChannelTypeOption -> ChannelTypeOption
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u.
Int -> (forall d. Data d => d -> u) -> ChannelTypeOption -> u
forall u. (forall d. Data d => d -> u) -> ChannelTypeOption -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ChannelTypeOption -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ChannelTypeOption -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> ChannelTypeOption -> m ChannelTypeOption
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> ChannelTypeOption -> m ChannelTypeOption
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ChannelTypeOption
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ChannelTypeOption -> c ChannelTypeOption
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ChannelTypeOption)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c ChannelTypeOption)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> ChannelTypeOption -> m ChannelTypeOption
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> ChannelTypeOption -> m ChannelTypeOption
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> ChannelTypeOption -> m ChannelTypeOption
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> ChannelTypeOption -> m ChannelTypeOption
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> ChannelTypeOption -> m ChannelTypeOption
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> ChannelTypeOption -> m ChannelTypeOption
gmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> ChannelTypeOption -> u
$cgmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> ChannelTypeOption -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> ChannelTypeOption -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> ChannelTypeOption -> [u]
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ChannelTypeOption -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ChannelTypeOption -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ChannelTypeOption -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ChannelTypeOption -> r
gmapT :: (forall b. Data b => b -> b)
-> ChannelTypeOption -> ChannelTypeOption
$cgmapT :: (forall b. Data b => b -> b)
-> ChannelTypeOption -> ChannelTypeOption
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c ChannelTypeOption)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c ChannelTypeOption)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ChannelTypeOption)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ChannelTypeOption)
dataTypeOf :: ChannelTypeOption -> DataType
$cdataTypeOf :: ChannelTypeOption -> DataType
toConstr :: ChannelTypeOption -> Constr
$ctoConstr :: ChannelTypeOption -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ChannelTypeOption
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ChannelTypeOption
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ChannelTypeOption -> c ChannelTypeOption
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ChannelTypeOption -> c ChannelTypeOption
Data, ChannelTypeOption -> ChannelTypeOption -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ChannelTypeOption -> ChannelTypeOption -> Bool
$c/= :: ChannelTypeOption -> ChannelTypeOption -> Bool
== :: ChannelTypeOption -> ChannelTypeOption -> Bool
$c== :: ChannelTypeOption -> ChannelTypeOption -> Bool
Eq, Eq ChannelTypeOption
ChannelTypeOption -> ChannelTypeOption -> Bool
ChannelTypeOption -> ChannelTypeOption -> Ordering
ChannelTypeOption -> ChannelTypeOption -> ChannelTypeOption
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ChannelTypeOption -> ChannelTypeOption -> ChannelTypeOption
$cmin :: ChannelTypeOption -> ChannelTypeOption -> ChannelTypeOption
max :: ChannelTypeOption -> ChannelTypeOption -> ChannelTypeOption
$cmax :: ChannelTypeOption -> ChannelTypeOption -> ChannelTypeOption
>= :: ChannelTypeOption -> ChannelTypeOption -> Bool
$c>= :: ChannelTypeOption -> ChannelTypeOption -> Bool
> :: ChannelTypeOption -> ChannelTypeOption -> Bool
$c> :: ChannelTypeOption -> ChannelTypeOption -> Bool
<= :: ChannelTypeOption -> ChannelTypeOption -> Bool
$c<= :: ChannelTypeOption -> ChannelTypeOption -> Bool
< :: ChannelTypeOption -> ChannelTypeOption -> Bool
$c< :: ChannelTypeOption -> ChannelTypeOption -> Bool
compare :: ChannelTypeOption -> ChannelTypeOption -> Ordering
$ccompare :: ChannelTypeOption -> ChannelTypeOption -> Ordering
Ord)

instance InternalDiscordEnum ChannelTypeOption where
  discordTypeStartValue :: ChannelTypeOption
discordTypeStartValue = ChannelTypeOption
ChannelTypeOptionGuildText
  fromDiscordType :: ChannelTypeOption -> Int
fromDiscordType ChannelTypeOption
ChannelTypeOptionGuildText = Int
0
  fromDiscordType ChannelTypeOption
ChannelTypeOptionDM = Int
1
  fromDiscordType ChannelTypeOption
ChannelTypeOptionGuildVoice = Int
2
  fromDiscordType ChannelTypeOption
ChannelTypeOptionGroupDM = Int
3
  fromDiscordType ChannelTypeOption
ChannelTypeOptionGuildCategory = Int
4
  fromDiscordType ChannelTypeOption
ChannelTypeOptionGuildNews = Int
5
  fromDiscordType ChannelTypeOption
ChannelTypeOptionGuildStore = Int
6
  fromDiscordType ChannelTypeOption
ChannelTypeOptionGuildNewsThread = Int
10
  fromDiscordType ChannelTypeOption
ChannelTypeOptionGuildPublicThread = Int
11
  fromDiscordType ChannelTypeOption
ChannelTypeOptionGuildPrivateThread = Int
12
  fromDiscordType ChannelTypeOption
ChannelTypeOptionGuildStageVoice = Int
13

instance ToJSON ChannelTypeOption where
  toJSON :: ChannelTypeOption -> Value
toJSON = forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. InternalDiscordEnum a => a -> Int
fromDiscordType

instance FromJSON ChannelTypeOption where
  parseJSON :: Value -> Parser ChannelTypeOption
parseJSON = forall a. InternalDiscordEnum a => String -> Value -> Parser a
discordTypeParseJSON String
"ChannelTypeOption"