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

-- | Provides base types and utility functions needed for modules in Discord.Internal.Types
module Discord.Internal.Types.Prelude where

import Data.Bits
import Data.Word

import Data.Aeson.Types
import Data.Time.Clock
import qualified Data.Text as T
import Data.Time.Clock.POSIX

import Data.Bifunctor (first)
import Text.Read (readMaybe)
import Data.Data (Data (dataTypeOf), dataTypeConstrs, fromConstr)

-- | Authorization token for the Discord API
newtype Auth = Auth T.Text
  deriving (Int -> Auth -> ShowS
[Auth] -> ShowS
Auth -> String
(Int -> Auth -> ShowS)
-> (Auth -> String) -> ([Auth] -> ShowS) -> Show Auth
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]
(Int -> ReadS Auth)
-> ReadS [Auth] -> ReadPrec Auth -> ReadPrec [Auth] -> Read 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
(Auth -> Auth -> Bool) -> (Auth -> Auth -> Bool) -> Eq Auth
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
Eq Auth
-> (Auth -> Auth -> Ordering)
-> (Auth -> Auth -> Bool)
-> (Auth -> Auth -> Bool)
-> (Auth -> Auth -> Bool)
-> (Auth -> Auth -> Bool)
-> (Auth -> Auth -> Auth)
-> (Auth -> Auth -> Auth)
-> Ord 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
$cp1Ord :: Eq Auth
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 Text -> Text -> Text
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
Eq Snowflake
-> (Snowflake -> Snowflake -> Ordering)
-> (Snowflake -> Snowflake -> Bool)
-> (Snowflake -> Snowflake -> Bool)
-> (Snowflake -> Snowflake -> Bool)
-> (Snowflake -> Snowflake -> Bool)
-> (Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake -> Snowflake)
-> Ord 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
$cp1Ord :: Eq Snowflake
Ord, Snowflake -> Snowflake -> Bool
(Snowflake -> Snowflake -> Bool)
-> (Snowflake -> Snowflake -> Bool) -> Eq Snowflake
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
(Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake)
-> (Snowflake -> Snowflake)
-> (Snowflake -> Snowflake)
-> (Integer -> Snowflake)
-> Num 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
Real Snowflake
-> Enum Snowflake
-> (Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake -> (Snowflake, Snowflake))
-> (Snowflake -> Snowflake -> (Snowflake, Snowflake))
-> (Snowflake -> Integer)
-> Integral 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
$cp2Integral :: Enum Snowflake
$cp1Integral :: Real Snowflake
Integral, Int -> Snowflake
Snowflake -> Int
Snowflake -> [Snowflake]
Snowflake -> Snowflake
Snowflake -> Snowflake -> [Snowflake]
Snowflake -> Snowflake -> Snowflake -> [Snowflake]
(Snowflake -> Snowflake)
-> (Snowflake -> Snowflake)
-> (Int -> Snowflake)
-> (Snowflake -> Int)
-> (Snowflake -> [Snowflake])
-> (Snowflake -> Snowflake -> [Snowflake])
-> (Snowflake -> Snowflake -> [Snowflake])
-> (Snowflake -> Snowflake -> Snowflake -> [Snowflake])
-> Enum 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
Num Snowflake
-> Ord Snowflake -> (Snowflake -> Rational) -> Real Snowflake
Snowflake -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: Snowflake -> Rational
$ctoRational :: Snowflake -> Rational
$cp2Real :: Ord Snowflake
$cp1Real :: Num Snowflake
Real, Eq Snowflake
Snowflake
Eq Snowflake
-> (Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake -> Snowflake)
-> (Snowflake -> Snowflake)
-> (Snowflake -> Int -> Snowflake)
-> (Snowflake -> Int -> Snowflake)
-> Snowflake
-> (Int -> Snowflake)
-> (Snowflake -> Int -> Snowflake)
-> (Snowflake -> Int -> Snowflake)
-> (Snowflake -> Int -> Snowflake)
-> (Snowflake -> Int -> Bool)
-> (Snowflake -> Maybe Int)
-> (Snowflake -> Int)
-> (Snowflake -> Bool)
-> (Snowflake -> Int -> Snowflake)
-> (Snowflake -> Int -> Snowflake)
-> (Snowflake -> Int -> Snowflake)
-> (Snowflake -> Int -> Snowflake)
-> (Snowflake -> Int -> Snowflake)
-> (Snowflake -> Int -> Snowflake)
-> (Snowflake -> Int)
-> Bits 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
$cp1Bits :: Eq Snowflake
Bits)

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

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

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

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

newtype DiscordId a = DiscordId { DiscordId a -> Snowflake
unId :: Snowflake }
  deriving (Eq (DiscordId a)
Eq (DiscordId a)
-> (DiscordId a -> DiscordId a -> Ordering)
-> (DiscordId a -> DiscordId a -> Bool)
-> (DiscordId a -> DiscordId a -> Bool)
-> (DiscordId a -> DiscordId a -> Bool)
-> (DiscordId a -> DiscordId a -> Bool)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> Ord (DiscordId a)
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
$cp1Ord :: forall a. Eq (DiscordId a)
Ord, DiscordId a -> DiscordId a -> Bool
(DiscordId a -> DiscordId a -> Bool)
-> (DiscordId a -> DiscordId a -> Bool) -> Eq (DiscordId a)
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
(DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a)
-> (Integer -> DiscordId a)
-> Num (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, Enum (DiscordId a)
Real (DiscordId a)
Real (DiscordId a)
-> Enum (DiscordId a)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a -> (DiscordId a, DiscordId a))
-> (DiscordId a -> DiscordId a -> (DiscordId a, DiscordId a))
-> (DiscordId a -> Integer)
-> Integral (DiscordId a)
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
$cp2Integral :: forall a. Enum (DiscordId a)
$cp1Integral :: forall a. Real (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]
(DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a)
-> (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 -> [DiscordId a])
-> Enum (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, Num (DiscordId a)
Ord (DiscordId a)
Num (DiscordId a)
-> Ord (DiscordId a)
-> (DiscordId a -> Rational)
-> Real (DiscordId a)
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
$cp2Real :: forall a. Ord (DiscordId a)
$cp1Real :: forall a. Num (DiscordId a)
Real, Eq (DiscordId a)
DiscordId a
Eq (DiscordId a)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a -> DiscordId a)
-> (DiscordId a -> DiscordId a)
-> (DiscordId a -> Int -> DiscordId a)
-> (DiscordId a -> Int -> DiscordId a)
-> DiscordId a
-> (Int -> DiscordId a)
-> (DiscordId a -> Int -> DiscordId a)
-> (DiscordId a -> Int -> DiscordId a)
-> (DiscordId a -> Int -> DiscordId a)
-> (DiscordId a -> Int -> Bool)
-> (DiscordId a -> Maybe Int)
-> (DiscordId a -> Int)
-> (DiscordId a -> Bool)
-> (DiscordId a -> Int -> DiscordId a)
-> (DiscordId a -> Int -> DiscordId a)
-> (DiscordId a -> Int -> DiscordId a)
-> (DiscordId a -> Int -> DiscordId a)
-> (DiscordId a -> Int -> DiscordId a)
-> (DiscordId a -> Int -> DiscordId a)
-> (DiscordId a -> Int)
-> Bits (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
$cp1Bits :: forall a. Eq (DiscordId a)
Bits)

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

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

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

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

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 OverwriteIdType
type OverwriteId = DiscordId OverwriteIdType

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 InteractionToken = InteractionToken T.Text
  deriving (Int -> InteractionToken -> ShowS
[InteractionToken] -> ShowS
InteractionToken -> String
(Int -> InteractionToken -> ShowS)
-> (InteractionToken -> String)
-> ([InteractionToken] -> ShowS)
-> Show InteractionToken
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, ReadPrec [InteractionToken]
ReadPrec InteractionToken
Int -> ReadS InteractionToken
ReadS [InteractionToken]
(Int -> ReadS InteractionToken)
-> ReadS [InteractionToken]
-> ReadPrec InteractionToken
-> ReadPrec [InteractionToken]
-> Read InteractionToken
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [InteractionToken]
$creadListPrec :: ReadPrec [InteractionToken]
readPrec :: ReadPrec InteractionToken
$creadPrec :: ReadPrec InteractionToken
readList :: ReadS [InteractionToken]
$creadList :: ReadS [InteractionToken]
readsPrec :: Int -> ReadS InteractionToken
$creadsPrec :: Int -> ReadS InteractionToken
Read, InteractionToken -> InteractionToken -> Bool
(InteractionToken -> InteractionToken -> Bool)
-> (InteractionToken -> InteractionToken -> Bool)
-> Eq InteractionToken
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: InteractionToken -> InteractionToken -> Bool
$c/= :: InteractionToken -> InteractionToken -> Bool
== :: InteractionToken -> InteractionToken -> Bool
$c== :: InteractionToken -> InteractionToken -> Bool
Eq, Eq InteractionToken
Eq InteractionToken
-> (InteractionToken -> InteractionToken -> Ordering)
-> (InteractionToken -> InteractionToken -> Bool)
-> (InteractionToken -> InteractionToken -> Bool)
-> (InteractionToken -> InteractionToken -> Bool)
-> (InteractionToken -> InteractionToken -> Bool)
-> (InteractionToken -> InteractionToken -> InteractionToken)
-> (InteractionToken -> InteractionToken -> InteractionToken)
-> Ord InteractionToken
InteractionToken -> InteractionToken -> Bool
InteractionToken -> InteractionToken -> Ordering
InteractionToken -> InteractionToken -> InteractionToken
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 :: InteractionToken -> InteractionToken -> InteractionToken
$cmin :: InteractionToken -> InteractionToken -> InteractionToken
max :: InteractionToken -> InteractionToken -> InteractionToken
$cmax :: InteractionToken -> InteractionToken -> InteractionToken
>= :: InteractionToken -> InteractionToken -> Bool
$c>= :: InteractionToken -> InteractionToken -> Bool
> :: InteractionToken -> InteractionToken -> Bool
$c> :: InteractionToken -> InteractionToken -> Bool
<= :: InteractionToken -> InteractionToken -> Bool
$c<= :: InteractionToken -> InteractionToken -> Bool
< :: InteractionToken -> InteractionToken -> Bool
$c< :: InteractionToken -> InteractionToken -> Bool
compare :: InteractionToken -> InteractionToken -> Ordering
$ccompare :: InteractionToken -> InteractionToken -> Ordering
$cp1Ord :: Eq InteractionToken
Ord)

instance ToJSON InteractionToken where
  toJSON :: InteractionToken -> Value
toJSON (InteractionToken Text
token) = Text -> Value
String Text
token

instance FromJSON InteractionToken where
  parseJSON :: Value -> Parser InteractionToken
parseJSON = String
-> (Text -> Parser InteractionToken)
-> Value
-> Parser InteractionToken
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"InteractionToken" (InteractionToken -> Parser InteractionToken
forall (f :: * -> *) a. Applicative f => a -> f a
pure (InteractionToken -> Parser InteractionToken)
-> (Text -> InteractionToken) -> Text -> Parser InteractionToken
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> InteractionToken
InteractionToken)

type Shard = (Int, Int)

-- | Gets a creation date from a snowflake.
snowflakeCreationDate :: Snowflake -> UTCTime
snowflakeCreationDate :: Snowflake -> UTCTime
snowflakeCreationDate Snowflake
x = POSIXTime -> UTCTime
posixSecondsToUTCTime (POSIXTime -> UTCTime)
-> (Snowflake -> POSIXTime) -> Snowflake -> UTCTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Snowflake -> POSIXTime
forall a b. (Real a, Fractional b) => a -> b
realToFrac
  (Snowflake -> UTCTime) -> Snowflake -> UTCTime
forall a b. (a -> b) -> a -> b
$ Snowflake
1420070400 Snowflake -> Snowflake -> Snowflake
forall a. Num a => a -> a -> a
+ Snowflake -> Snowflake -> Snowflake
forall a. Integral a => a -> a -> a
quot (Snowflake -> Int -> Snowflake
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 =  (a -> (Int, a)) -> [a] -> [(Int, a)]
forall a b. (a -> b) -> [a] -> [b]
map (\a
d -> (a -> Int
forall a. InternalDiscordEnum a => a -> Int
fromDiscordType a
d, a
d)) (a -> [a]
forall b. Data b => b -> [b]
makeTable a
forall a. InternalDiscordEnum a => a
discordTypeStartValue)
    where
      makeTable :: Data b => b -> [b]
      makeTable :: b -> [b]
makeTable b
t = (Constr -> b) -> [Constr] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map Constr -> b
forall a. Data a => Constr -> a
fromConstr (DataType -> [Constr]
dataTypeConstrs (DataType -> [Constr]) -> DataType -> [Constr]
forall a b. (a -> b) -> a -> b
$ b -> DataType
forall a. Data a => a -> DataType
dataTypeOf b
t)

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

toMaybeJSON :: (ToJSON a) => a -> Maybe Value
toMaybeJSON :: a -> Maybe Value
toMaybeJSON = Value -> Maybe Value
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> Maybe Value) -> (a -> Value) -> a -> Maybe Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Value
forall a. ToJSON a => a -> Value
toJSON