packages feed

calamity 0.1.28.3 → 0.1.28.4

raw patch · 7 files changed

+103/−58 lines, 7 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Calamity.HTTP.Internal.Route: instance Calamity.HTTP.Internal.Route.RouteFragmentable Calamity.HTTP.Internal.Route.S ids
- Calamity.HTTP.Internal.Route: instance Data.Hashable.Class.Hashable Calamity.HTTP.Internal.Route.Route
- Calamity.HTTP.Internal.Route: instance Data.Typeable.Internal.Typeable a => Calamity.HTTP.Internal.Route.RouteFragmentable (Calamity.HTTP.Internal.Route.ID a) ids
- Calamity.HTTP.Internal.Route: instance GHC.Classes.Eq Calamity.HTTP.Internal.Route.Route
- Calamity.HTTP.Internal.Types: [$sel:lock:Bucket] :: Bucket -> Lock
- Calamity.HTTP.Internal.Types: data Bucket
+ Calamity.HTTP.Internal.Route: PS :: PS (s :: Symbol)
+ Calamity.HTTP.Internal.Route: data PS (s :: Symbol)
+ Calamity.HTTP.Internal.Route: giveParam :: forall (s :: Symbol) reqs. KnownSymbol s => Text -> RouteBuilder reqs -> RouteBuilder ('( 'PSRequirement s, 'Satisfied) : reqs)
+ Calamity.HTTP.Internal.Route: instance Calamity.HTTP.Internal.Route.RouteFragmentable Calamity.HTTP.Internal.Route.S reqs
+ Calamity.HTTP.Internal.Route: instance Data.Typeable.Internal.Typeable a => Calamity.HTTP.Internal.Route.RouteFragmentable (Calamity.HTTP.Internal.Route.ID a) reqs
+ Calamity.HTTP.Internal.Route: instance GHC.TypeLits.KnownSymbol s => Calamity.HTTP.Internal.Route.RouteFragmentable (Calamity.HTTP.Internal.Route.PS s) reqs
+ Calamity.HTTP.Internal.Route: routeKey :: Route -> RouteKey
+ Calamity.HTTP.Internal.Route: type RouteKey = (Text, Maybe (Snowflake Channel), Maybe (Snowflake Guild))
+ Calamity.HTTP.Internal.Types: newtype Bucket
- Calamity.Cache.Eff: delDM :: forall r_a9tNC. MemberWithError CacheEff r_a9tNC => Snowflake DMChannel -> Sem r_a9tNC ()
+ Calamity.Cache.Eff: delDM :: forall r_a9tTw. MemberWithError CacheEff r_a9tTw => Snowflake DMChannel -> Sem r_a9tTw ()
- Calamity.Cache.Eff: delGuild :: forall r_a9tNv. MemberWithError CacheEff r_a9tNv => Snowflake Guild -> Sem r_a9tNv ()
+ Calamity.Cache.Eff: delGuild :: forall r_a9tTp. MemberWithError CacheEff r_a9tTp => Snowflake Guild -> Sem r_a9tTp ()
- Calamity.Cache.Eff: delMessage :: forall r_a9tNX. MemberWithError CacheEff r_a9tNX => Snowflake Message -> Sem r_a9tNX ()
+ Calamity.Cache.Eff: delMessage :: forall r_a9tTR. MemberWithError CacheEff r_a9tTR => Snowflake Message -> Sem r_a9tTR ()
- Calamity.Cache.Eff: delUnavailableGuild :: forall r_a9tNQ. MemberWithError CacheEff r_a9tNQ => Snowflake Guild -> Sem r_a9tNQ ()
+ Calamity.Cache.Eff: delUnavailableGuild :: forall r_a9tTK. MemberWithError CacheEff r_a9tTK => Snowflake Guild -> Sem r_a9tTK ()
- Calamity.Cache.Eff: delUser :: forall r_a9tNJ. MemberWithError CacheEff r_a9tNJ => Snowflake User -> Sem r_a9tNJ ()
+ Calamity.Cache.Eff: delUser :: forall r_a9tTD. MemberWithError CacheEff r_a9tTD => Snowflake User -> Sem r_a9tTD ()
- Calamity.Cache.Eff: getBotUser :: forall r_a9tNn. MemberWithError CacheEff r_a9tNn => Sem r_a9tNn (Maybe User)
+ Calamity.Cache.Eff: getBotUser :: forall r_a9tTh. MemberWithError CacheEff r_a9tTh => Sem r_a9tTh (Maybe User)
- Calamity.Cache.Eff: getDM :: forall r_a9tNz. MemberWithError CacheEff r_a9tNz => Snowflake DMChannel -> Sem r_a9tNz (Maybe DMChannel)
+ Calamity.Cache.Eff: getDM :: forall r_a9tTt. MemberWithError CacheEff r_a9tTt => Snowflake DMChannel -> Sem r_a9tTt (Maybe DMChannel)
- Calamity.Cache.Eff: getDMs :: forall r_a9tNB. MemberWithError CacheEff r_a9tNB => Sem r_a9tNB [DMChannel]
+ Calamity.Cache.Eff: getDMs :: forall r_a9tTv. MemberWithError CacheEff r_a9tTv => Sem r_a9tTv [DMChannel]
- Calamity.Cache.Eff: getGuild :: forall r_a9tNq. MemberWithError CacheEff r_a9tNq => Snowflake Guild -> Sem r_a9tNq (Maybe Guild)
+ Calamity.Cache.Eff: getGuild :: forall r_a9tTk. MemberWithError CacheEff r_a9tTk => Snowflake Guild -> Sem r_a9tTk (Maybe Guild)
- Calamity.Cache.Eff: getGuildChannel :: forall r_a9tNs. MemberWithError CacheEff r_a9tNs => Snowflake GuildChannel -> Sem r_a9tNs (Maybe GuildChannel)
+ Calamity.Cache.Eff: getGuildChannel :: forall r_a9tTm. MemberWithError CacheEff r_a9tTm => Snowflake GuildChannel -> Sem r_a9tTm (Maybe GuildChannel)
- Calamity.Cache.Eff: getGuilds :: forall r_a9tNu. MemberWithError CacheEff r_a9tNu => Sem r_a9tNu [Guild]
+ Calamity.Cache.Eff: getGuilds :: forall r_a9tTo. MemberWithError CacheEff r_a9tTo => Sem r_a9tTo [Guild]
- Calamity.Cache.Eff: getMessage :: forall r_a9tNU. MemberWithError CacheEff r_a9tNU => Snowflake Message -> Sem r_a9tNU (Maybe Message)
+ Calamity.Cache.Eff: getMessage :: forall r_a9tTO. MemberWithError CacheEff r_a9tTO => Snowflake Message -> Sem r_a9tTO (Maybe Message)
- Calamity.Cache.Eff: getMessages :: forall r_a9tNW. MemberWithError CacheEff r_a9tNW => Sem r_a9tNW [Message]
+ Calamity.Cache.Eff: getMessages :: forall r_a9tTQ. MemberWithError CacheEff r_a9tTQ => Sem r_a9tTQ [Message]
- Calamity.Cache.Eff: getUnavailableGuilds :: forall r_a9tNP. MemberWithError CacheEff r_a9tNP => Sem r_a9tNP [Snowflake Guild]
+ Calamity.Cache.Eff: getUnavailableGuilds :: forall r_a9tTJ. MemberWithError CacheEff r_a9tTJ => Sem r_a9tTJ [Snowflake Guild]
- Calamity.Cache.Eff: getUser :: forall r_a9tNG. MemberWithError CacheEff r_a9tNG => Snowflake User -> Sem r_a9tNG (Maybe User)
+ Calamity.Cache.Eff: getUser :: forall r_a9tTA. MemberWithError CacheEff r_a9tTA => Snowflake User -> Sem r_a9tTA (Maybe User)
- Calamity.Cache.Eff: getUsers :: forall r_a9tNI. MemberWithError CacheEff r_a9tNI => Sem r_a9tNI [User]
+ Calamity.Cache.Eff: getUsers :: forall r_a9tTC. MemberWithError CacheEff r_a9tTC => Sem r_a9tTC [User]
- Calamity.Cache.Eff: isUnavailableGuild :: forall r_a9tNN. MemberWithError CacheEff r_a9tNN => Snowflake Guild -> Sem r_a9tNN Bool
+ Calamity.Cache.Eff: isUnavailableGuild :: forall r_a9tTH. MemberWithError CacheEff r_a9tTH => Snowflake Guild -> Sem r_a9tTH Bool
- Calamity.Cache.Eff: setBotUser :: forall r_a9tNl. MemberWithError CacheEff r_a9tNl => User -> Sem r_a9tNl ()
+ Calamity.Cache.Eff: setBotUser :: forall r_a9tTf. MemberWithError CacheEff r_a9tTf => User -> Sem r_a9tTf ()
- Calamity.Cache.Eff: setDM :: forall r_a9tNx. MemberWithError CacheEff r_a9tNx => DMChannel -> Sem r_a9tNx ()
+ Calamity.Cache.Eff: setDM :: forall r_a9tTr. MemberWithError CacheEff r_a9tTr => DMChannel -> Sem r_a9tTr ()
- Calamity.Cache.Eff: setGuild :: forall r_a9tNo. MemberWithError CacheEff r_a9tNo => Guild -> Sem r_a9tNo ()
+ Calamity.Cache.Eff: setGuild :: forall r_a9tTi. MemberWithError CacheEff r_a9tTi => Guild -> Sem r_a9tTi ()
- Calamity.Cache.Eff: setMessage :: forall r_a9tNS. MemberWithError CacheEff r_a9tNS => Message -> Sem r_a9tNS ()
+ Calamity.Cache.Eff: setMessage :: forall r_a9tTM. MemberWithError CacheEff r_a9tTM => Message -> Sem r_a9tTM ()
- Calamity.Cache.Eff: setUnavailableGuild :: forall r_a9tNL. MemberWithError CacheEff r_a9tNL => Snowflake Guild -> Sem r_a9tNL ()
+ Calamity.Cache.Eff: setUnavailableGuild :: forall r_a9tTF. MemberWithError CacheEff r_a9tTF => Snowflake Guild -> Sem r_a9tTF ()
- Calamity.Cache.Eff: setUser :: forall r_a9tNE. MemberWithError CacheEff r_a9tNE => User -> Sem r_a9tNE ()
+ Calamity.Cache.Eff: setUser :: forall r_a9tTy. MemberWithError CacheEff r_a9tTy => User -> Sem r_a9tTy ()
- Calamity.HTTP.Internal.Route: (//) :: RouteFragmentable a ids => RouteBuilder ids -> a -> ConsRes a ids
+ Calamity.HTTP.Internal.Route: (//) :: RouteFragmentable a reqs => RouteBuilder reqs -> a -> ConsRes a reqs
- Calamity.HTTP.Internal.Route: buildRoute :: forall (ids :: [(Type, RouteRequirement)]). EnsureFulfilled ids => RouteBuilder ids -> Route
+ Calamity.HTTP.Internal.Route: buildRoute :: forall (reqs :: [(RequirementType, RouteRequirement)]). EnsureFulfilled reqs => RouteBuilder reqs -> Route
- Calamity.HTTP.Internal.Route: class Typeable a => RouteFragmentable a ids where {
+ Calamity.HTTP.Internal.Route: class Typeable a => RouteFragmentable a reqs where {
- Calamity.HTTP.Internal.Route: data RouteBuilder (idState :: [(Type, RouteRequirement)])
+ Calamity.HTTP.Internal.Route: data RouteBuilder (reqstate :: [(RequirementType, RouteRequirement)])
- Calamity.HTTP.Internal.Route: giveID :: forall k ids. Typeable k => Snowflake k -> RouteBuilder ids -> RouteBuilder ('(k, 'Satisfied) : ids)
+ Calamity.HTTP.Internal.Route: giveID :: forall t reqs. Typeable t => Snowflake t -> RouteBuilder reqs -> RouteBuilder ('( 'IDRequirement t, 'Satisfied) : reqs)
- Calamity.HTTP.Internal.Route: type family ConsRes a ids;
+ Calamity.HTTP.Internal.Route: type family ConsRes a reqs;
- Calamity.HTTP.Internal.Types: Bucket :: Lock -> TVar BucketState -> Bucket
+ Calamity.HTTP.Internal.Types: Bucket :: TVar BucketState -> Bucket
- Calamity.HTTP.Internal.Types: RateLimitState :: Map Route ByteString -> Map ByteString Bucket -> Event -> RateLimitState
+ Calamity.HTTP.Internal.Types: RateLimitState :: Map RouteKey ByteString -> Map ByteString Bucket -> Event -> RateLimitState
- Calamity.HTTP.Internal.Types: [$sel:bucketKeys:RateLimitState] :: RateLimitState -> Map Route ByteString
+ Calamity.HTTP.Internal.Types: [$sel:bucketKeys:RateLimitState] :: RateLimitState -> Map RouteKey ByteString

Files

Calamity/HTTP/Channel.hs view
@@ -235,21 +235,25 @@       & giveID mid       & buildRoute   route (CreateReaction (getID -> cid) (getID @Message -> mid) emoji) =-    baseRoute cid // S "messages" // ID @Message // S "reactions" // S (renderEmoji emoji) // S "@me"+    baseRoute cid // S "messages" // ID @Message // S "reactions" // PS @"emoji" // S "@me"       & giveID mid+      & giveParam @"emoji" (renderEmoji emoji)       & buildRoute   route (DeleteOwnReaction (getID -> cid) (getID @Message -> mid) emoji) =-    baseRoute cid // S "messages" // ID @Message // S "reactions" // S (renderEmoji emoji) // S "@me"+    baseRoute cid // S "messages" // ID @Message // S "reactions" // PS @"emoji" // S "@me"       & giveID mid+      & giveParam @"emoji" (renderEmoji emoji)       & buildRoute   route (DeleteUserReaction (getID -> cid) (getID @Message -> mid) emoji (getID @User -> uid)) =-    baseRoute cid // S "messages" // ID @Message // S "reactions" // S (renderEmoji emoji) // ID @User+    baseRoute cid // S "messages" // ID @Message // S "reactions" // PS @"emoji" // ID @User       & giveID mid       & giveID uid+      & giveParam @"emoji" (renderEmoji emoji)       & buildRoute   route (GetReactions (getID -> cid) (getID @Message -> mid) emoji _) =-    baseRoute cid // S "messages" // ID @Message // S "reactions" // S (renderEmoji emoji)+    baseRoute cid // S "messages" // ID @Message // S "reactions" // PS @"emoji"       & giveID mid+      & giveParam @"emoji" (renderEmoji emoji)       & buildRoute   route (DeleteAllReactions (getID -> cid) (getID @Message -> mid)) =     baseRoute cid // S "messages" // ID @Message // S "reactions"
Calamity/HTTP/Internal/Ratelimit.hs view
@@ -14,7 +14,6 @@ import Control.Concurrent.Event (Event) import qualified Control.Concurrent.Event as E import Control.Concurrent.STM-import qualified Control.Concurrent.STM.Lock as L import Control.Lens import Control.Monad @@ -47,9 +46,9 @@  data Ratelimit   = KnownRatelimit Bucket-  | UnknownRatelimit Route+  | UnknownRatelimit RouteKey -getRateLimit :: RateLimitState -> Route -> STM Ratelimit+getRateLimit :: RateLimitState -> RouteKey -> STM Ratelimit getRateLimit s h = do   bucketKey <- SC.lookup h $ bucketKeys s   bucket <- join <$> sequenceA (flip SC.lookup (buckets s) <$> bucketKey)@@ -62,7 +61,7 @@ {- | Knowing the bucket for a route, and the ratelimit info, map the route to  the bucket key and retrieve the bucket -}-updateBucket :: RateLimitState -> Route -> B.ByteString -> BucketState -> STM Bucket+updateBucket :: RateLimitState -> RouteKey -> B.ByteString -> BucketState -> STM Bucket updateBucket s h b bucketState = do   bucketKey <- SC.lookup h $ bucketKeys s   case bucketKey of@@ -77,12 +76,10 @@         Nothing -> Prelude.error "Not possible"     Nothing -> do       -- the bucket key wasn't known, make a new bucket and insert it-      lock <- L.new-      bs <- newTVar bucketState-      let bucket = Bucket lock bs-      SC.insert bucket b $ buckets s+      bs <- Bucket <$> newTVar bucketState+      SC.insert bs b $ buckets s       SC.insert b h $ bucketKeys s-      pure bucket+      pure bs  where   mergeStates :: BucketState -> BucketState -> BucketState   mergeStates old new =@@ -321,7 +318,7 @@ doSingleRequest rlstate route gl r = do   P.embed $ E.wait (globalLock rlstate) -  rl <- P.embed . atomically $ getRateLimit rlstate route+  rl <- P.embed . atomically $ getRateLimit rlstate (routeKey route)    case rl of     KnownRatelimit bucket ->@@ -339,7 +336,7 @@           _ -> pure ()         case rlHeaders of           Just (bs, bk) ->-            void $ updateBucket rlstate route bk bs+            void $ updateBucket rlstate (routeKey route) bk bs           Nothing -> pure ()       pure $ RGood v     Ratelimited unlockWhen False (Just (bs, bk)) -> do@@ -350,7 +347,7 @@           KnownRatelimit bucket ->             modifyTVar' (bucket ^. #state) (#ongoing -~ 1)           _ -> pure ()-        void $ updateBucket rlstate route bk bs+        void $ updateBucket rlstate (routeKey route) bk bs        P.embed $ do         threadDelayUntil unlockWhen@@ -376,7 +373,7 @@             _ -> pure ()           case bs of             Just (bs', bk) ->-              void $ updateBucket rlstate route bk bs'+              void $ updateBucket rlstate (routeKey route) bk bs'             Nothing ->               pure () 
Calamity/HTTP/Internal/Route.hs view
@@ -5,11 +5,15 @@ module Calamity.HTTP.Internal.Route     ( mkRouteBuilder     , giveID+    , giveParam     , buildRoute+    , routeKey+    , RouteKey     , RouteBuilder     , RouteRequirement     , Route(path)     , S(..)+    , PS(..)     , ID(..)     , RouteFragmentable(..) ) where @@ -31,14 +35,24 @@ import           GHC.Generics                 hiding ( S )  import           TextShow+import GHC.TypeLits (Symbol, KnownSymbol, symbolVal)  data RouteFragment   = S' Text+    -- ^ Static string fragment+  | PS' String+    -- ^ Parameterised string fragment   | ID' TypeRep+    -- ^ ID fragment   deriving ( Generic, Show, Eq ) +-- | A static string fragment of a route newtype S = S Text +-- | A parameterised string fragment of a route+data PS (s :: Symbol) = PS++-- | An id fragment of a route data ID a = ID  instance Hashable RouteFragment@@ -49,23 +63,37 @@   | Satisfied   deriving ( Generic, Show, Eq ) -data RouteBuilder (idState :: [(Type, RouteRequirement)]) = UnsafeMkRouteBuilder+data RequirementType+  = IDRequirement Type+  | PSRequirement Symbol++data RouteBuilder (reqstate :: [(RequirementType, RouteRequirement)]) = UnsafeMkRouteBuilder   { route :: [RouteFragment]   , ids   :: [(TypeRep, Word64)]+  , params :: [(String, Text)]   }  mkRouteBuilder :: RouteBuilder '[]-mkRouteBuilder = UnsafeMkRouteBuilder [] []+mkRouteBuilder = UnsafeMkRouteBuilder [] [] []  giveID-  :: forall k ids-   . Typeable k-  => Snowflake k-  -> RouteBuilder ids-  -> RouteBuilder ('(k, 'Satisfied) ': ids)-giveID (Snowflake id) (UnsafeMkRouteBuilder route ids) =-  UnsafeMkRouteBuilder route ((typeRep (Proxy @k), id) : ids)+  :: forall t reqs+   . Typeable t+  => Snowflake t+  -> RouteBuilder reqs+  -> RouteBuilder ('( 'IDRequirement t, 'Satisfied) ': reqs)+giveID (Snowflake id) (UnsafeMkRouteBuilder route ids params) =+  UnsafeMkRouteBuilder route ((typeRep $ Proxy @t, id) : ids) params +giveParam+  :: forall (s :: Symbol) reqs+   . KnownSymbol s+  => Text+  -> RouteBuilder reqs+  -> RouteBuilder ('( 'PSRequirement s, 'Satisfied) ': reqs)+giveParam value (UnsafeMkRouteBuilder route ids params) =+  UnsafeMkRouteBuilder route ids ((symbolVal $ Proxy @s, value) : params)+ type family (&&) (a :: Bool) (b :: Bool) :: Bool where   'True && 'True = 'True   _     && _     = 'False@@ -80,17 +108,17 @@   IsElem k (k : _)  = 'True   IsElem k (_ : xs) = IsElem k xs -type family EnsureFulfilled (ids :: [(k, RouteRequirement)]) :: Constraint where-  EnsureFulfilled ids = EnsureFulfilledInner ids '[] 'True+type family EnsureFulfilled (reqs :: [(RequirementType, RouteRequirement)]) :: Constraint where+  EnsureFulfilled reqs = EnsureFulfilledInner reqs '[] 'True -type family EnsureFulfilledInner (ids :: [(k, RouteRequirement)]) (seen :: [k]) (ok :: Bool) :: Constraint where+type family EnsureFulfilledInner (reqs :: [(RequirementType, RouteRequirement)]) (seen :: [RequirementType]) (ok :: Bool) :: Constraint where   EnsureFulfilledInner '[]                      _    'True = ()   EnsureFulfilledInner ('(k, 'NotNeeded) ': xs) seen ok    = EnsureFulfilledInner xs (k ': seen) ok   EnsureFulfilledInner ('(k, 'Satisfied) ': xs) seen ok    = EnsureFulfilledInner xs (k ': seen) ok   EnsureFulfilledInner ('(k, 'Required)  ': xs) seen ok    = EnsureFulfilledInner xs (k ': seen) (IsElem k seen && ok) -type family AddRequired k (ids :: [(Type, RouteRequirement)]) :: [(Type, RouteRequirement)] where-  AddRequired k ids = '(k, AddRequiredInner (Lookup k ids)) ': ids+type family AddRequired k (reqs :: [(RequirementType, RouteRequirement)]) :: [(RequirementType, RouteRequirement)] where+  AddRequired k reqs = '(k, AddRequiredInner (Lookup k reqs)) ': reqs  type family AddRequiredInner (k :: Maybe RouteRequirement) :: RouteRequirement where   AddRequiredInner ('Just 'Required)  = 'Required@@ -98,23 +126,30 @@   AddRequiredInner ('Just 'NotNeeded) = 'Required   AddRequiredInner 'Nothing           = 'Required -class Typeable a => RouteFragmentable a ids where-  type ConsRes a ids+class Typeable a => RouteFragmentable a reqs where+  type ConsRes a reqs -  (//) :: RouteBuilder ids -> a -> ConsRes a ids+  (//) :: RouteBuilder reqs -> a -> ConsRes a reqs -instance RouteFragmentable S ids where-  type ConsRes S ids = RouteBuilder ids+instance RouteFragmentable S reqs where+  type ConsRes S reqs = RouteBuilder reqs -  (UnsafeMkRouteBuilder r ids) // (S t) =-    UnsafeMkRouteBuilder (r <> [S' t]) ids+  (UnsafeMkRouteBuilder r ids params) // (S t) =+    UnsafeMkRouteBuilder (r <> [S' t]) ids params -instance Typeable a => RouteFragmentable (ID (a :: Type)) (ids :: [(Type, RouteRequirement)]) where-  type ConsRes (ID a) ids = RouteBuilder (AddRequired a ids)+instance Typeable a => RouteFragmentable (ID (a :: Type)) (reqs :: [(RequirementType, RouteRequirement)]) where+  type ConsRes (ID a) reqs = RouteBuilder (AddRequired ('IDRequirement a) reqs) -  (UnsafeMkRouteBuilder r ids) // ID =-    UnsafeMkRouteBuilder (r <> [ID' (typeRep (Proxy @a))]) ids+  (UnsafeMkRouteBuilder r ids params) // ID =+    UnsafeMkRouteBuilder (r <> [ID' $ typeRep $ Proxy @a]) ids params +instance KnownSymbol s => RouteFragmentable (PS s) (reqs :: [(RequirementType, RouteRequirement)]) where+  type ConsRes (PS s) reqs = RouteBuilder (AddRequired ('PSRequirement s) reqs)++  (UnsafeMkRouteBuilder r ids params) // PS =+    UnsafeMkRouteBuilder (r <> [PS' $ symbolVal $ Proxy @s]) ids params++ infixl 5 //  data Route = Route@@ -122,27 +157,31 @@   , key       :: Text   , channelID :: Maybe (Snowflake Channel)   , guildID   :: Maybe (Snowflake Guild)-  } deriving (Generic, Show, Eq)+  } deriving (Generic, Show) -instance Hashable Route where-  hashWithSalt s (Route _ ident c g) = hashWithSalt s (ident, c, g)+type RouteKey = (Text, Maybe (Snowflake Channel), Maybe (Snowflake Guild)) +routeKey :: Route -> RouteKey+routeKey Route {key, channelID, guildID} = (key, channelID, guildID)+ baseURL :: Url 'Https baseURL = https "discord.com" /: "api" /: "v8"  buildRoute-  :: forall (ids :: [(Type, RouteRequirement)])-   . EnsureFulfilled ids-  => RouteBuilder ids+  :: forall (reqs :: [(RequirementType, RouteRequirement)])+   . EnsureFulfilled reqs+  => RouteBuilder reqs   -> Route-buildRoute (UnsafeMkRouteBuilder route ids) = Route+buildRoute (UnsafeMkRouteBuilder route ids params) = Route   (foldl' (/:) baseURL $ map goR route)   (T.concat (map goIdent route))   (Snowflake <$> lookup (typeRep (Proxy @Channel)) ids)   (Snowflake <$> lookup (typeRep (Proxy @Guild)) ids)  where   goR (S'  t) = t+  goR (PS' t) = fromJust $ lookup t params   goR (ID' t) = showt . fromJust $ lookup t ids    goIdent (S'  t) = t+  goIdent (PS' s) = T.pack s   goIdent (ID' t) = showt t
Calamity/HTTP/Internal/Types.hs view
@@ -12,7 +12,6 @@ import           Calamity.Internal.AesonThings  import           Control.Concurrent.Event      ( Event )-import           Control.Concurrent.STM.Lock   ( Lock ) import           Control.Concurrent.STM.TVar   ( TVar )  import Data.Time@@ -49,14 +48,13 @@   }   deriving ( Generic, Show ) -data Bucket = Bucket-  { lock :: Lock-  , state :: TVar BucketState+newtype Bucket = Bucket+  { state :: TVar BucketState   }   deriving ( Generic )  data RateLimitState = RateLimitState-  { bucketKeys :: SC.Map Route B.ByteString+  { bucketKeys :: SC.Map RouteKey B.ByteString   , buckets    :: SC.Map B.ByteString Bucket   , globalLock :: Event   }
Calamity/HTTP/Invite.hs view
@@ -22,10 +22,12 @@   type Result (InviteRequest a) = a    route (GetInvite c) =-    baseRoute // S c+    baseRoute // PS @"invite"+      & giveParam @"invite" c       & buildRoute   route (DeleteInvite c) =-    baseRoute // S c+    baseRoute // PS @"invite"+      & giveParam @"invite" c       & buildRoute    action (GetInvite _) = getWithP ("with_counts" =: True)
ChangeLog.md view
@@ -1,5 +1,10 @@ # Changelog for Calamity +## 0.1.28.4+++ Rework the route handling so that the bucket keys for emoji routes work+  properly+ ## 0.1.28.3  + Fix HTTP responses from discord that don't have ratelimit info being treated
calamity.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 3ef864682cfb94fce9b938cf2c9b2cf32ac1170e904fb5fd492abf28259a6c81+-- hash: ab4efef98213c2235c6f8062573bbfac890f01cc09133f83530d5e4388dbcccd  name:           calamity-version:        0.1.28.3+version:        0.1.28.4 synopsis:       A library for writing discord bots in haskell description:    Please see the README on GitHub at <https://github.com/simmsb/calamity#readme> category:       Network, Web