blob: 4b7d8251b7c4b75c78e818e893be4bd295ccc890 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
-- | Utility and base types and functions for the Discord Rest API
module Discord.Internal.Rest.Prelude where
import Prelude hiding (log)
import Control.Exception.Safe (throwIO)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.String (IsString(fromString))
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Network.HTTP.Req as R
import Web.Internal.HttpApiData (ToHttpApiData)
import Discord.Internal.Types
import Paths_discord_haskell (version)
import Data.Version (showVersion)
-- | The api version to use.
apiVersion :: T.Text
apiVersion = "10"
-- | The base url (Req) for API requests
baseUrl :: R.Url 'R.Https
baseUrl = R.https "discord.com" R./: "api" R./: apiVersion'
where apiVersion' = "v" <> apiVersion
-- | Discord requires HTTP headers for authentication.
authHeader :: Auth -> R.Option 'R.Https
authHeader auth =
R.header "Authorization" (TE.encodeUtf8 (authToken auth))
<> R.header "User-Agent" agent
where
-- | https://discord.com/developers/docs/reference#user-agent
-- Second place where the library version is noted
agent = fromString $ "DiscordBot (https://github.com/discord-haskell/discord-haskell, " <> showVersion version <> ")"
-- Possibly append to an URL
infixl 5 /?
(/?) :: ToHttpApiData a => R.Url scheme -> Maybe a -> R.Url scheme
(/?) url Nothing = url
(/?) url (Just part) = url R./~ part
-- | A compiled HTTP request ready to execute
data JsonRequest where
Delete :: R.Url 'R.Https -> R.Option 'R.Https -> JsonRequest
Get :: R.Url 'R.Https -> R.Option 'R.Https -> JsonRequest
Put :: R.HttpBody a => R.Url 'R.Https -> a -> R.Option 'R.Https -> JsonRequest
Patch :: R.HttpBody a => R.Url 'R.Https -> RestIO a -> R.Option 'R.Https -> JsonRequest
Post :: R.HttpBody a => R.Url 'R.Https -> RestIO a -> R.Option 'R.Https -> JsonRequest
class Request a where
-- | used for putting a request into a rate limit bucket
-- https://discord.com/developers/docs/topics/rate-limits#rate-limits
majorRoute :: a -> String
-- | build a JSON http request
jsonRequest :: a -> JsonRequest
-- | Same Monad as IO. Overwrite Req settings
newtype RestIO a = RestIO { restIOtoIO :: IO a }
deriving (Functor, Applicative, Monad, MonadIO)
instance R.MonadHttp RestIO where
-- | Throw actual exceptions
handleHttpException = liftIO . throwIO
-- | Don't throw exceptions on http error codes like 404
getHttpConfig = pure $ R.defaultHttpConfig { R.httpConfigCheckResponse = \_ _ _ -> Nothing }
|