Route index
The file
The index is the routes/index.json file of the repository: plain JSON any language can read. An entry looks like this:
{
"method": "PATCH",
"path": "/channels/{channel_id}",
"name": "Update channel",
"source": "discord",
"auth": ["bot"],
"major": "channel_id",
"global": true,
"model": "unknown",
"coverage": "exercised",
"notes": ["Changing a channel's name or topic sits behind a sub-limit of its own, ..."]
}
major: the parameter that gives each value its own counter:channel_id,guild_id,webhook_id, orwebhook_id+webhook_token. Empty when every call shares one counter.global:falsefor routes exempt from the bot's global limit.model:token_bucket,fixed_window, orunknownuntil a run has seen it.family: routes Discord counts together, in a single bucket.source:discordfor Discord's OpenAPI specification,userdoccersfor routes only Discord Userdoccers documents, such asPOST /guilds/{guild_id}/members-search.coverage: whether the engine exercises the route, and if not, why (innotes).notes: sub-limits and other special cases.
From Go
The routes package matches a request to its route:
import "github.com/FCAgreatgoals/bucketmap/routes"
r, ok := routes.Match("PATCH", "/api/v10/channels/123/messages/456")
// r.Path "/channels/{channel_id}/messages/{message_id}"
// r.MajorValue(path) "123"
Its documentation is on pkg.go.dev.
Two ways a bucket refills
X-RateLimit-Reset-After is the time until the bucket is full again, which means two different things depending on the bucket:
- Fixed window (
fixed_window): the bucket refills all at once, when the window ends. From one request to the next,now + Reset-Afterstays put, andReset-Aftershrinks as the bucket drains. - Token bucket (
token_bucket): the bucket refills one request at a time. From one request to the next,now + Reset-Aftermoves forward by one request's worth, andReset-Aftergrows as the bucket drains.
Two back-to-back requests on the same bucket are enough to tell them apart, far below any limit. The engine sends a few such pairs on purpose.
Keeping the index current
The repository's index workflow rebuilds the index every week from the latest sources, and fails when they describe a route the index does not know yet. To rebuild it by hand:
git clone --depth 1 https://github.com/discord/discord-api-spec /tmp/spec
git clone --depth 1 https://github.com/discord-userdoccers/discord-userdoccers /tmp/userdoccers
bucketmap index -spec /tmp/spec/specs/openapi.json -userdoccers /tmp/userdoccers/pages
bucketmap index options: -spec (Discord's openapi.json), -userdoccers (the pages directory of Discord Userdoccers), -annotations (routes/annotations.json by default) and -out (routes/index.json by default).
What the sources do not say lives in routes/annotations.json: bucket models, families, notes, and why a route is left out. The build fails on any route that is neither exercised nor explained.