module Network.Discord.Rest.Prelude where
import Control.Concurrent (threadDelay)
import Control.Monad (when)
import Control.Exception (throwIO)
import Control.Monad.IO.Class
import Data.Default
import Data.Hashable
import Data.Monoid ((<>))
import Data.Time.Clock.POSIX
import Network.HTTP.Req (Option, Scheme(..), (=:), MonadHttp(..))
import System.Log.Logger
import Network.Discord.Types
baseURL :: String
baseURL = "https://discordapp.com/api/v6"
class (MonadIO m, DiscordAuth m) => DiscordRest m where
getRateLimit :: DoFetch f a => f a -> m (Maybe Int)
setRateLimit :: DoFetch f a => f a -> Int -> m ()
waitRateLimit :: DoFetch f a => f a -> m ()
waitRateLimit endpoint = do
rl <- getRateLimit endpoint
case rl of
Nothing -> return ()
Just l -> do
now <- liftIO (fmap round getPOSIXTime :: IO Int)
when (l > now) . liftIO $ do
infoM "Discord-hs.Rest" "Hit rate limit, backing off"
threadDelay $ 1000000 * (l now)
infoM "Discord-hs.Rest" "Done waiting"
return ()
instance (MonadIO m, DiscordRest m) => MonadHttp m where
handleHttpException = liftIO . throwIO
class Hashable (a b) => DoFetch (a :: * -> *) b | a b -> b where
doFetch :: DiscordRest m => a b -> m b
data Range = Range { after :: Snowflake, before :: Snowflake, limit :: Int}
instance Default Range where
def = Range 0 18446744073709551615 100
toQueryString :: Range -> Option 'Https
toQueryString (Range a b l)
= "after" =: show a
<> "before" =: show b
<> "limit" =: show l