@shivaedev/discord 0.0.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/LICENSE +21 -0
- package/README.md +58 -1
- package/dist/DiscordConfig.d.ts +7 -0
- package/dist/DiscordConfig.d.ts.map +1 -0
- package/dist/DiscordConfig.js +5 -0
- package/dist/DiscordConfig.js.map +1 -0
- package/dist/DiscordGateway.d.ts +9 -0
- package/dist/DiscordGateway.d.ts.map +1 -0
- package/dist/DiscordGateway.js +13 -0
- package/dist/DiscordGateway.js.map +1 -0
- package/dist/DiscordRest.d.ts +8 -0
- package/dist/DiscordRest.d.ts.map +1 -0
- package/dist/DiscordRest.js +12 -0
- package/dist/DiscordRest.js.map +1 -0
- package/dist/DiscordToken.d.ts +6 -0
- package/dist/DiscordToken.d.ts.map +1 -0
- package/dist/DiscordToken.js +4 -0
- package/dist/DiscordToken.js.map +1 -0
- package/dist/GatewayTransport.d.ts +9 -0
- package/dist/GatewayTransport.d.ts.map +1 -0
- package/dist/GatewayTransport.js +4 -0
- package/dist/GatewayTransport.js.map +1 -0
- package/dist/adapters/restStatus.d.ts +3 -0
- package/dist/adapters/restStatus.d.ts.map +1 -0
- package/dist/adapters/restStatus.js +8 -0
- package/dist/adapters/restStatus.js.map +1 -0
- package/dist/adapters/routeKey.d.ts +5 -0
- package/dist/adapters/routeKey.d.ts.map +1 -0
- package/dist/adapters/routeKey.js +16 -0
- package/dist/adapters/routeKey.js.map +1 -0
- package/dist/adapters/webSocketLayer.d.ts +4 -0
- package/dist/adapters/webSocketLayer.d.ts.map +1 -0
- package/dist/adapters/webSocketLayer.js +7 -0
- package/dist/adapters/webSocketLayer.js.map +1 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +14 -0
- package/dist/errors.js.map +1 -0
- package/dist/gatewayConnection.d.ts +6 -0
- package/dist/gatewayConnection.d.ts.map +1 -0
- package/dist/gatewayConnection.js +85 -0
- package/dist/gatewayConnection.js.map +1 -0
- package/dist/gatewayProtocol.d.ts +41 -0
- package/dist/gatewayProtocol.d.ts.map +1 -0
- package/dist/gatewayProtocol.js +21 -0
- package/dist/gatewayProtocol.js.map +1 -0
- package/dist/rateLimits.d.ts +8 -0
- package/dist/rateLimits.d.ts.map +1 -0
- package/dist/rateLimits.js +36 -0
- package/dist/rateLimits.js.map +1 -0
- package/dist/request.d.ts +4 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +6 -0
- package/dist/request.js.map +1 -0
- package/dist/restClient.d.ts +11 -0
- package/dist/restClient.d.ts.map +1 -0
- package/dist/restClient.js +51 -0
- package/dist/restClient.js.map +1 -0
- package/dist/runGateway.d.ts +6 -0
- package/dist/runGateway.d.ts.map +1 -0
- package/dist/runGateway.js +29 -0
- package/dist/runGateway.js.map +1 -0
- package/package.json +63 -4
- package/src/DiscordConfig.ts +9 -0
- package/src/DiscordGateway.ts +13 -0
- package/src/DiscordRest.ts +12 -0
- package/src/DiscordToken.ts +3 -0
- package/src/GatewayTransport.ts +9 -0
- package/src/adapters/restStatus.ts +9 -0
- package/src/adapters/routeKey.ts +15 -0
- package/src/adapters/webSocketLayer.ts +7 -0
- package/src/errors.ts +13 -0
- package/src/gatewayConnection.ts +89 -0
- package/src/gatewayProtocol.ts +42 -0
- package/src/rateLimits.ts +39 -0
- package/src/request.ts +7 -0
- package/src/restClient.ts +64 -0
- package/src/runGateway.ts +32 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0 - 2026-11-04
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Provides independent Effect bot REST and gateway services, typed failures, bucket and global rate-limit waits, and scoped reconnect/resume lifecycles.
|
|
8
|
+
|
|
9
|
+
### Breaking
|
|
10
|
+
|
|
11
|
+
- TypeScript source exports now use `@shivaedev/source` instead of `source`. Replace `source` with `@shivaedev/source` in Node `--conditions`, TypeScript `customConditions`, and Vite/Vitest `resolve.conditions`. Bare `source` selects built JavaScript; no compatibility alias is provided.
|
|
12
|
+
|
|
13
|
+
## 0.1.0 - 2026-11-04
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Introduce a publishable package for Discord integrations with no API yet.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ShivaeDev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,60 @@
|
|
|
1
1
|
# @shivaedev/discord
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Discord bot REST calls and gateway sessions for Effect applications. Keep tokens, failures and connection lifetimes in Effect instead of carrying a second asynchronous runtime in each app.
|
|
4
|
+
|
|
5
|
+
## Talk to Discord from your application
|
|
6
|
+
|
|
7
|
+
Send a message through the bot REST client and decode its response with your schema. The client waits when Discord rate limits the request.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Schema } from "effect";
|
|
11
|
+
import { request } from "@shivaedev/discord/request.ts";
|
|
12
|
+
|
|
13
|
+
const posted = request("POST", "/channels/123/messages", Schema.Struct({ id: Schema.String }), { content: "The release is ready." });
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Use the clients
|
|
17
|
+
|
|
18
|
+
REST and gateway are independent services sharing a redacted `DiscordToken`. Provide only the service your application uses. Application channel choices, message rendering, permissions and event handlers stay in the application.
|
|
19
|
+
|
|
20
|
+
### Bot REST
|
|
21
|
+
|
|
22
|
+
Provide `DiscordRest.layer`, a native `HttpClient` and the token:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { Layer, Redacted } from "effect";
|
|
26
|
+
import { FetchHttpClient } from "effect/http";
|
|
27
|
+
import { DiscordRest } from "@shivaedev/discord/DiscordRest.ts";
|
|
28
|
+
import { DiscordToken } from "@shivaedev/discord/DiscordToken.ts";
|
|
29
|
+
|
|
30
|
+
const restLayer = DiscordRest.layer.pipe(
|
|
31
|
+
Layer.provide(FetchHttpClient.layer),
|
|
32
|
+
Layer.provide(Layer.succeed(DiscordToken)(Redacted.make("bot-token"))),
|
|
33
|
+
);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`request(method, path, schema, body?)` reads the service and decodes the result. `DiscordRest.request(method, path, body?)` returns decoded JSON as `unknown`; a 204 response returns `undefined`. Paths start with `/` and are relative to Discord's API v10 base. Request bodies use native HTTP JSON encoding, and response reads use `@shivaedev/http` with a 1 MiB limit.
|
|
37
|
+
|
|
38
|
+
One service instance serializes calls for its bot. It tracks Discord's bucket ids, major channel/guild identifiers, remaining count and relative reset time. An exhausted bucket delays the next matching call. A 429 reads Discord's `retry_after` seconds and `global` flag, releases the response, waits on Effect's clock and retries up to three times. Exhaustion fails with `DiscordRateLimited`, carrying the final delay in seconds. Transport failures become `DiscordTransportError`; other HTTP statuses retain `@shivaedev/http`'s typed failures. Schema decoding failures remain in the error channel.
|
|
39
|
+
|
|
40
|
+
### Gateway sessions
|
|
41
|
+
|
|
42
|
+
Provide `DiscordGateway.layer`, the same token, `DiscordConfig` with your intents and `webSocketLayer` from `adapters/webSocketLayer.ts`. `DiscordConfig` defaults to Discord's API and gateway endpoints with zero intents; overriding it supplies all three fields: `apiUrl`, `gatewayUrl` and `intents`.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { Effect } from "effect";
|
|
46
|
+
import { DiscordGateway } from "@shivaedev/discord/DiscordGateway.ts";
|
|
47
|
+
|
|
48
|
+
const listen = Effect.gen(function* () {
|
|
49
|
+
const gateway = yield* DiscordGateway;
|
|
50
|
+
yield* gateway.run((event) => Effect.log(event.type, event.data));
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`run(handler)` owns a scoped connection until interrupted or failed. Dispatches expose `type`, `sequence` and `data`; applications decode event data with their schemas. A dropped connection waits one second, reconnects to the resume URL and sends the retained session id and last sequence. An invalid session starts a fresh identify. Fatal token and configuration closes fail with `DiscordGatewayClosed`, carrying the close code. Interruption releases the socket. Malformed gateway envelopes fail with `DiscordGatewayProtocolError`.
|
|
55
|
+
|
|
56
|
+
### Story kits and installation
|
|
57
|
+
|
|
58
|
+
The stateful provider fake is shipped by `@shivaedev/test-kits/discord/fake.ts`, outside the runtime package. Acquire `fakeDiscord()` in a scope: `server` is a loopback HTTP provider with message creation, editing, history and deletion; `gateway.transport` supplies the native socket boundary. Its controls can dispatch events, drop connections or invalidate sessions. Resume replays events emitted while disconnected. Compose it into your application's story kit and keep the real Discord services running.
|
|
59
|
+
|
|
60
|
+
Install `@shivaedev/discord` and `effect`. The built-in socket adapter uses the runtime's global WebSocket. This client runs a single gateway session; sharding and application-specific MCP tools belong to their consumers.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscordConfig.d.ts","sourceRoot":"","sources":["../src/DiscordConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,eAAO,MAAM,aAAa;qBACR,MAAM;yBACF,MAAM;sBACT,MAAM;EAGvB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
export const DiscordConfig = Context.Reference("@shivaedev/discord/DiscordConfig", {
|
|
3
|
+
defaultValue: () => ({ apiUrl: "https://discord.com/api/v10", gatewayUrl: "wss://gateway.discord.gg", intents: 0 }),
|
|
4
|
+
});
|
|
5
|
+
//# sourceMappingURL=DiscordConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscordConfig.js","sourceRoot":"","sources":["../src/DiscordConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,SAAS,CAI3C,kCAAkC,EAAE;IACtC,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,6BAA6B,EAAE,UAAU,EAAE,0BAA0B,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;CACnH,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { DiscordToken } from "#DiscordToken.ts";
|
|
3
|
+
import { GatewayTransport } from "#GatewayTransport.ts";
|
|
4
|
+
export declare const DiscordGateway: import("effect/Context").Service<"@shivaedev/discord/DiscordGateway", Readonly<{
|
|
5
|
+
readonly run: (dispatch: (event: import("./gatewayProtocol.ts").GatewayDispatch) => Effect.Effect<void>) => Effect.Effect<never, import("./errors.ts").DiscordGatewayClosed | import("./errors.ts").DiscordGatewayProtocolError, never>;
|
|
6
|
+
}>> & {
|
|
7
|
+
readonly layer: import("effect/Layer").Layer<"@shivaedev/discord/DiscordGateway", never, DiscordToken | GatewayTransport>;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=DiscordGateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscordGateway.d.ts","sourceRoot":"","sources":["../src/DiscordGateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,eAAO,MAAM,cAAc;;;;CAKzB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { defineService } from "@shivaedev/service/defineService.ts";
|
|
3
|
+
import { DiscordConfig } from "#DiscordConfig.ts";
|
|
4
|
+
import { DiscordToken } from "#DiscordToken.ts";
|
|
5
|
+
import { GatewayTransport } from "#GatewayTransport.ts";
|
|
6
|
+
import { runGateway } from "#runGateway.ts";
|
|
7
|
+
export const DiscordGateway = defineService({
|
|
8
|
+
id: "@shivaedev/discord/DiscordGateway",
|
|
9
|
+
initialize: Effect.void,
|
|
10
|
+
methods: () => ({ run: runGateway }),
|
|
11
|
+
requires: [DiscordConfig, DiscordToken, GatewayTransport],
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=DiscordGateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscordGateway.js","sourceRoot":"","sources":["../src/DiscordGateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC;IAC3C,EAAE,EAAE,mCAAmC;IACvC,UAAU,EAAE,MAAM,CAAC,IAAI;IACvB,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;IACpC,QAAQ,EAAE,CAAC,aAAa,EAAE,YAAY,EAAE,gBAAgB,CAAC;CACzD,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { HttpClient } from "effect/http";
|
|
2
|
+
import { DiscordToken } from "#DiscordToken.ts";
|
|
3
|
+
export declare const DiscordRest: import("effect/Context").Service<"@shivaedev/discord/DiscordRest", Readonly<{
|
|
4
|
+
readonly request: (method: import("effect/http/HttpMethod").HttpMethod, path: string, body?: unknown) => import("effect/Effect").Effect<unknown, import("./errors.ts").DiscordRateLimited | import("./errors.ts").DiscordTransportError | import("effect/http/HttpBody").HttpBodyError | import("@shivaedev/http/errors.ts").InvalidBodyLimit | import("@shivaedev/http/errors.ts").RemoteGone | import("@shivaedev/http/errors.ts").RemoteHttpError | import("@shivaedev/http/errors.ts").RemoteNotFound | import("@shivaedev/http/errors.ts").RemoteRateLimited | import("@shivaedev/http/errors.ts").RemoteUnauthorized | import("@shivaedev/http/errors.ts").ResponseBodyTooLarge | import("effect/Schema").SchemaError, never>;
|
|
5
|
+
}>> & {
|
|
6
|
+
readonly layer: import("effect/Layer").Layer<"@shivaedev/discord/DiscordRest", never, DiscordToken | HttpClient.HttpClient>;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=DiscordRest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscordRest.d.ts","sourceRoot":"","sources":["../src/DiscordRest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,eAAO,MAAM,WAAW;;;;CAKtB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { HttpClient } from "effect/http";
|
|
2
|
+
import { defineService } from "@shivaedev/service/defineService.ts";
|
|
3
|
+
import { DiscordConfig } from "#DiscordConfig.ts";
|
|
4
|
+
import { DiscordToken } from "#DiscordToken.ts";
|
|
5
|
+
import { initializeRest, restRequest } from "#restClient.ts";
|
|
6
|
+
export const DiscordRest = defineService({
|
|
7
|
+
id: "@shivaedev/discord/DiscordRest",
|
|
8
|
+
initialize: initializeRest,
|
|
9
|
+
methods: (state) => ({ request: restRequest(state) }),
|
|
10
|
+
requires: [HttpClient.HttpClient, DiscordToken, DiscordConfig],
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=DiscordRest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscordRest.js","sourceRoot":"","sources":["../src/DiscordRest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7D,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;IACxC,EAAE,EAAE,gCAAgC;IACpC,UAAU,EAAE,cAAc;IAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;IACrD,QAAQ,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,YAAY,EAAE,aAAa,CAAC;CAC9D,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Context, type Redacted } from "effect";
|
|
2
|
+
declare const DiscordToken_base: Context.ServiceClass<DiscordToken, "@shivaedev/discord/DiscordToken", Redacted.Redacted<string>>;
|
|
3
|
+
export declare class DiscordToken extends DiscordToken_base {
|
|
4
|
+
}
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=DiscordToken.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscordToken.d.ts","sourceRoot":"","sources":["../src/DiscordToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;;AAEhD,qBAAa,YAAa,SAAQ,iBAA6F;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscordToken.js","sourceRoot":"","sources":["../src/DiscordToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAiB,MAAM,QAAQ,CAAC;AAEhD,MAAM,OAAO,YAAa,SAAQ,OAAO,CAAC,OAAO,EAA2C,CAAC,iCAAiC,CAAC;CAAG"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Context, type Effect } from "effect";
|
|
2
|
+
import type { Socket } from "effect/socket";
|
|
3
|
+
declare const GatewayTransport_base: Context.ServiceClass<GatewayTransport, "@shivaedev/discord/GatewayTransport", {
|
|
4
|
+
readonly open: (url: string) => Effect.Effect<Socket.Socket>;
|
|
5
|
+
}>;
|
|
6
|
+
export declare class GatewayTransport extends GatewayTransport_base {
|
|
7
|
+
}
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=GatewayTransport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GatewayTransport.d.ts","sourceRoot":"","sources":["../src/GatewayTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;mBAK3B,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;;AAH9D,qBAAa,gBAAiB,SAAQ,qBAKI;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GatewayTransport.js","sourceRoot":"","sources":["../src/GatewayTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;AAG9C,MAAM,OAAO,gBAAiB,SAAQ,OAAO,CAAC,OAAO,EAKlD,CAAC,qCAAqC,CAAC;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restStatus.d.ts","sourceRoot":"","sources":["../../src/adapters/restStatus.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,iBAE3C;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,iBAErC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as HttpStatus from "effect/http/HttpStatus";
|
|
2
|
+
export function isRateLimited(status) {
|
|
3
|
+
return status === HttpStatus.fromLiteral("TooManyRequests");
|
|
4
|
+
}
|
|
5
|
+
export function isEmpty(status) {
|
|
6
|
+
return status === HttpStatus.fromLiteral("NoContent");
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=restStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restStatus.js","sourceRoot":"","sources":["../../src/adapters/restStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AAErD,MAAM,UAAU,aAAa,CAAC,MAAc;IAC3C,OAAO,MAAM,KAAK,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,MAAc;IACrC,OAAO,MAAM,KAAK,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routeKey.d.ts","sourceRoot":"","sources":["../../src/adapters/routeKey.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;;;EAcpD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function routeKey(method, path) {
|
|
2
|
+
const parts = path.split("?")[0]?.split("/") ?? [];
|
|
3
|
+
let major = "";
|
|
4
|
+
if (parts[1] === "channels" || parts[1] === "guilds") {
|
|
5
|
+
major = parts[2] ?? "";
|
|
6
|
+
}
|
|
7
|
+
if (parts[1] === "webhooks") {
|
|
8
|
+
major = `${parts[2]}/${parts[3]}`;
|
|
9
|
+
}
|
|
10
|
+
const normalized = parts.map((part, index) => (/^\d+$/u.test(part) && index !== 2 ? ":id" : part));
|
|
11
|
+
if (parts[1] === "channels" || parts[1] === "guilds" || parts[1] === "webhooks") {
|
|
12
|
+
normalized[2] = ":major";
|
|
13
|
+
}
|
|
14
|
+
return { major, route: `${method} ${normalized.join("/")}` };
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=routeKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routeKey.js","sourceRoot":"","sources":["../../src/adapters/routeKey.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,IAAY;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IACnD,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;QACtD,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;IACD,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;QAC7B,KAAK,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACnC,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACnG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;QACjF,UAAU,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;IAC1B,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webSocketLayer.d.ts","sourceRoot":"","sources":["../../src/adapters/webSocketLayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,eAAO,MAAM,cAAc,6CAEzB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Effect, Layer } from "effect";
|
|
2
|
+
import { Socket } from "effect/socket";
|
|
3
|
+
import { GatewayTransport } from "#GatewayTransport.ts";
|
|
4
|
+
export const webSocketLayer = Layer.succeed(GatewayTransport)({
|
|
5
|
+
open: (url) => Socket.makeWebSocket(url).pipe(Effect.provide(Socket.layerWebSocketConstructorGlobal)),
|
|
6
|
+
});
|
|
7
|
+
//# sourceMappingURL=webSocketLayer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webSocketLayer.js","sourceRoot":"","sources":["../../src/adapters/webSocketLayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7D,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,+BAA+B,CAAC,CAAC;CACrG,CAAC,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
declare const DiscordTransportError_base: Schema.Class<DiscordTransportError, Schema.TaggedStruct<"DiscordTransportError", {}>, import("effect/Cause").YieldableError>;
|
|
3
|
+
export declare class DiscordTransportError extends DiscordTransportError_base {
|
|
4
|
+
}
|
|
5
|
+
declare const DiscordRateLimited_base: Schema.Class<DiscordRateLimited, Schema.TaggedStruct<"DiscordRateLimited", {
|
|
6
|
+
readonly retryAfter: Schema.Number;
|
|
7
|
+
}>, import("effect/Cause").YieldableError>;
|
|
8
|
+
export declare class DiscordRateLimited extends DiscordRateLimited_base {
|
|
9
|
+
}
|
|
10
|
+
declare const DiscordGatewayClosed_base: Schema.Class<DiscordGatewayClosed, Schema.TaggedStruct<"DiscordGatewayClosed", {
|
|
11
|
+
readonly code: Schema.Number;
|
|
12
|
+
}>, import("effect/Cause").YieldableError>;
|
|
13
|
+
export declare class DiscordGatewayClosed extends DiscordGatewayClosed_base {
|
|
14
|
+
}
|
|
15
|
+
declare const DiscordGatewayProtocolError_base: Schema.Class<DiscordGatewayProtocolError, Schema.TaggedStruct<"DiscordGatewayProtocolError", {}>, import("effect/Cause").YieldableError>;
|
|
16
|
+
export declare class DiscordGatewayProtocolError extends DiscordGatewayProtocolError_base {
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;;AAEhC,qBAAa,qBAAsB,SAAQ,0BAAwE;CAAG;;;;AAEtH,qBAAa,kBAAmB,SAAQ,uBAEtC;CAAG;;;;AAEL,qBAAa,oBAAqB,SAAQ,yBAExC;CAAG;;AAEL,qBAAa,2BAA4B,SAAQ,gCAAoF;CAAG"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
export class DiscordTransportError extends Schema.TaggedError()("DiscordTransportError", {}) {
|
|
3
|
+
}
|
|
4
|
+
export class DiscordRateLimited extends Schema.TaggedError()("DiscordRateLimited", {
|
|
5
|
+
retryAfter: Schema.Number,
|
|
6
|
+
}) {
|
|
7
|
+
}
|
|
8
|
+
export class DiscordGatewayClosed extends Schema.TaggedError()("DiscordGatewayClosed", {
|
|
9
|
+
code: Schema.Number,
|
|
10
|
+
}) {
|
|
11
|
+
}
|
|
12
|
+
export class DiscordGatewayProtocolError extends Schema.TaggedError()("DiscordGatewayProtocolError", {}) {
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,OAAO,qBAAsB,SAAQ,MAAM,CAAC,WAAW,EAAyB,CAAC,uBAAuB,EAAE,EAAE,CAAC;CAAG;AAEtH,MAAM,OAAO,kBAAmB,SAAQ,MAAM,CAAC,WAAW,EAAsB,CAAC,oBAAoB,EAAE;IACtG,UAAU,EAAE,MAAM,CAAC,MAAM;CACzB,CAAC;CAAG;AAEL,MAAM,OAAO,oBAAqB,SAAQ,MAAM,CAAC,WAAW,EAAwB,CAAC,sBAAsB,EAAE;IAC5G,IAAI,EAAE,MAAM,CAAC,MAAM;CACnB,CAAC;CAAG;AAEL,MAAM,OAAO,2BAA4B,SAAQ,MAAM,CAAC,WAAW,EAA+B,CAAC,6BAA6B,EAAE,EAAE,CAAC;CAAG"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Socket } from "effect/socket";
|
|
3
|
+
import { DiscordToken } from "#DiscordToken.ts";
|
|
4
|
+
import { type GatewayDispatch, type GatewaySession } from "#gatewayProtocol.ts";
|
|
5
|
+
export declare function gatewayConnection(session: GatewaySession, dispatch: (event: GatewayDispatch) => Effect.Effect<void>): Effect.Effect<never, import("./errors.ts").DiscordGatewayProtocolError | Socket.SocketError, DiscordToken | Socket.Socket>;
|
|
6
|
+
//# sourceMappingURL=gatewayConnection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gatewayConnection.d.ts","sourceRoot":"","sources":["../src/gatewayConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAoB,MAAM,QAAQ,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAA2B,KAAK,eAAe,EAAqB,KAAK,cAAc,EAA2B,MAAM,qBAAqB,CAAC;AAErJ,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,8HAkFnH"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Deferred, Effect, Redacted, Schema } from "effect";
|
|
2
|
+
import { Socket } from "effect/socket";
|
|
3
|
+
import { DiscordConfig } from "#DiscordConfig.ts";
|
|
4
|
+
import { DiscordToken } from "#DiscordToken.ts";
|
|
5
|
+
import { decodeData, decodeFrame, Hello, Ready, reconnect } from "#gatewayProtocol.ts";
|
|
6
|
+
export function gatewayConnection(session, dispatch) {
|
|
7
|
+
return Effect.gen(function* () {
|
|
8
|
+
const socket = yield* Socket.Socket;
|
|
9
|
+
const token = yield* DiscordToken;
|
|
10
|
+
const { intents } = yield* DiscordConfig;
|
|
11
|
+
const reader = yield* socket.reader;
|
|
12
|
+
const writer = yield* socket.writer;
|
|
13
|
+
const failed = yield* Deferred.make();
|
|
14
|
+
let acknowledged = true;
|
|
15
|
+
const send = Effect.fnUntraced(function* (op, d) {
|
|
16
|
+
const frame = yield* Schema.encodeEffect(Schema.fromJsonString(Schema.Unknown))({ d, op }).pipe(Effect.orDie);
|
|
17
|
+
yield* writer.write(frame);
|
|
18
|
+
});
|
|
19
|
+
const startHeartbeat = Effect.fnUntraced(function* (interval) {
|
|
20
|
+
const pulse = Effect.gen(function* () {
|
|
21
|
+
while (true) {
|
|
22
|
+
yield* Effect.sleep(interval);
|
|
23
|
+
if (!acknowledged) {
|
|
24
|
+
return yield* reconnect();
|
|
25
|
+
}
|
|
26
|
+
acknowledged = false;
|
|
27
|
+
yield* send(1, session.sequence);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
yield* pulse.pipe(Effect.catch((error) => Deferred.fail(failed, error)), Effect.forkScoped);
|
|
31
|
+
});
|
|
32
|
+
const hello = Effect.fnUntraced(function* (data) {
|
|
33
|
+
const { heartbeatInterval } = yield* decodeData(Hello, data);
|
|
34
|
+
const payload = session.sessionId === undefined
|
|
35
|
+
? { intents, properties: { browser: "platform", device: "platform", os: "linux" }, token: Redacted.value(token) }
|
|
36
|
+
: { seq: session.sequence, "session_id": session.sessionId, token: Redacted.value(token) };
|
|
37
|
+
yield* send(session.sessionId === undefined ? 2 : 6, payload);
|
|
38
|
+
yield* startHeartbeat(heartbeatInterval);
|
|
39
|
+
});
|
|
40
|
+
const deliver = Effect.fnUntraced(function* (frame) {
|
|
41
|
+
if (frame.t === "READY") {
|
|
42
|
+
const ready = yield* decodeData(Ready, frame.d);
|
|
43
|
+
session.sessionId = ready.sessionId;
|
|
44
|
+
session.resumeUrl = ready.resumeUrl;
|
|
45
|
+
}
|
|
46
|
+
if (frame.t !== undefined && frame.t !== null && frame.s !== undefined && frame.s !== null) {
|
|
47
|
+
yield* dispatch({ data: frame.d, sequence: frame.s, type: frame.t });
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
const handle = Effect.fnUntraced(function* (frame) {
|
|
51
|
+
if (frame.s !== undefined && frame.s !== null) {
|
|
52
|
+
session.sequence = frame.s;
|
|
53
|
+
}
|
|
54
|
+
switch (frame.op) {
|
|
55
|
+
case 10:
|
|
56
|
+
return yield* hello(frame.d);
|
|
57
|
+
case 11:
|
|
58
|
+
acknowledged = true;
|
|
59
|
+
return;
|
|
60
|
+
case 1:
|
|
61
|
+
return yield* send(1, session.sequence);
|
|
62
|
+
case 7:
|
|
63
|
+
return yield* reconnect();
|
|
64
|
+
case 9:
|
|
65
|
+
if (frame.d !== true) {
|
|
66
|
+
session.sessionId = undefined;
|
|
67
|
+
session.resumeUrl = undefined;
|
|
68
|
+
session.sequence = null;
|
|
69
|
+
}
|
|
70
|
+
return yield* reconnect();
|
|
71
|
+
case 0:
|
|
72
|
+
return yield* deliver(frame);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
const consume = Effect.gen(function* () {
|
|
76
|
+
while (true) {
|
|
77
|
+
for (const raw of yield* reader.pull) {
|
|
78
|
+
yield* handle(yield* decodeFrame(raw));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
return yield* Effect.raceFirst(consume, Deferred.await(failed));
|
|
83
|
+
}).pipe(Effect.scoped);
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=gatewayConnection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gatewayConnection.js","sourceRoot":"","sources":["../src/gatewayConnection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { Socket } from "effect/socket";
|
|
3
|
+
import { DiscordGatewayProtocolError } from "#errors.ts";
|
|
4
|
+
export declare const GatewayFrame: Schema.Struct<{
|
|
5
|
+
readonly d: Schema.Unknown;
|
|
6
|
+
readonly op: Schema.Number;
|
|
7
|
+
readonly s: Schema.optional<Schema.NullOr<Schema.Number>>;
|
|
8
|
+
readonly t: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
9
|
+
}>;
|
|
10
|
+
export type GatewayFrame = typeof GatewayFrame.Type;
|
|
11
|
+
export interface GatewayDispatch {
|
|
12
|
+
readonly data: unknown;
|
|
13
|
+
readonly sequence: number;
|
|
14
|
+
readonly type: string;
|
|
15
|
+
}
|
|
16
|
+
export interface GatewaySession {
|
|
17
|
+
resumeUrl: string | undefined;
|
|
18
|
+
sequence: number | null;
|
|
19
|
+
sessionId: string | undefined;
|
|
20
|
+
}
|
|
21
|
+
export declare function decodeFrame(frame: string | Uint8Array): Effect.Effect<{
|
|
22
|
+
readonly d: unknown;
|
|
23
|
+
readonly op: number;
|
|
24
|
+
readonly s?: number | null | undefined;
|
|
25
|
+
readonly t?: string | null | undefined;
|
|
26
|
+
}, DiscordGatewayProtocolError, never>;
|
|
27
|
+
export declare const Hello: Schema.encodeKeys<Schema.Struct<{
|
|
28
|
+
readonly heartbeatInterval: Schema.Number;
|
|
29
|
+
}>, {
|
|
30
|
+
readonly heartbeatInterval: "heartbeat_interval";
|
|
31
|
+
}>;
|
|
32
|
+
export declare const Ready: Schema.encodeKeys<Schema.Struct<{
|
|
33
|
+
readonly resumeUrl: Schema.String;
|
|
34
|
+
readonly sessionId: Schema.String;
|
|
35
|
+
}>, {
|
|
36
|
+
readonly resumeUrl: "resume_gateway_url";
|
|
37
|
+
readonly sessionId: "session_id";
|
|
38
|
+
}>;
|
|
39
|
+
export declare function decodeData<TSchema extends Schema.ConstraintDecoder<unknown>>(schema: TSchema, data: unknown): Effect.Effect<TSchema["Type"], DiscordGatewayProtocolError, TSchema["DecodingServices"]>;
|
|
40
|
+
export declare function reconnect(): Effect.Effect<never, Socket.SocketError, never>;
|
|
41
|
+
//# sourceMappingURL=gatewayProtocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gatewayProtocol.d.ts","sourceRoot":"","sources":["../src/gatewayProtocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAEzD,eAAO,MAAM,YAAY;;;;;EAKvB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;;;;;uCAIrD;AAED,eAAO,MAAM,KAAK;;;;EAA2H,CAAC;AAC9I,eAAO,MAAM,KAAK;;;;;;EAEjB,CAAC;AAEF,wBAAgB,UAAU,CAAC,OAAO,SAAS,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,4FAE3G;AAED,wBAAgB,SAAS,oDAExB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { Socket } from "effect/socket";
|
|
3
|
+
import { DiscordGatewayProtocolError } from "#errors.ts";
|
|
4
|
+
export const GatewayFrame = Schema.Struct({
|
|
5
|
+
d: Schema.Unknown,
|
|
6
|
+
op: Schema.Number,
|
|
7
|
+
s: Schema.optional(Schema.NullOr(Schema.Number)),
|
|
8
|
+
t: Schema.optional(Schema.NullOr(Schema.String)),
|
|
9
|
+
});
|
|
10
|
+
export function decodeFrame(frame) {
|
|
11
|
+
return Schema.decodeUnknownEffect(Schema.fromJsonString(GatewayFrame))(typeof frame === "string" ? frame : new TextDecoder().decode(frame)).pipe(Effect.mapError(() => new DiscordGatewayProtocolError({})));
|
|
12
|
+
}
|
|
13
|
+
export const Hello = Schema.Struct({ heartbeatInterval: Schema.Number }).pipe(Schema.encodeKeys({ heartbeatInterval: "heartbeat_interval" }));
|
|
14
|
+
export const Ready = Schema.Struct({ resumeUrl: Schema.String, sessionId: Schema.String }).pipe(Schema.encodeKeys({ resumeUrl: "resume_gateway_url", sessionId: "session_id" }));
|
|
15
|
+
export function decodeData(schema, data) {
|
|
16
|
+
return Schema.decodeUnknownEffect(schema)(data).pipe(Effect.mapError(() => new DiscordGatewayProtocolError({})));
|
|
17
|
+
}
|
|
18
|
+
export function reconnect() {
|
|
19
|
+
return Effect.fail(new Socket.SocketError({ reason: new Socket.SocketCloseError({ code: 4000 }) }));
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=gatewayProtocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gatewayProtocol.js","sourceRoot":"","sources":["../src/gatewayProtocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC,CAAC,EAAE,MAAM,CAAC,OAAO;IACjB,EAAE,EAAE,MAAM,CAAC,MAAM;IACjB,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAChD,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;CAChD,CAAC,CAAC;AAeH,MAAM,UAAU,WAAW,CAAC,KAA0B;IACrD,OAAO,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAC/I,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,2BAA2B,CAAC,EAAE,CAAC,CAAC,CAC1D,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC;AAC9I,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAC9F,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAC/E,CAAC;AAEF,MAAM,UAAU,UAAU,CAAoD,MAAe,EAAE,IAAa;IAC3G,OAAO,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,2BAA2B,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAClH,CAAC;AAED,MAAM,UAAU,SAAS;IACxB,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACrG,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { Headers } from "effect/http";
|
|
3
|
+
export declare function rateLimits(): {
|
|
4
|
+
observe: (route: string, major: string, headers: Headers.Headers) => Effect.Effect<void, never, never>;
|
|
5
|
+
refuse: (route: string, major: string, seconds: number, global: boolean) => Effect.Effect<void, never, never>;
|
|
6
|
+
wait: (route: string, major: string) => Effect.Effect<void, never, never>;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=rateLimits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rateLimits.d.ts","sourceRoot":"","sources":["../src/rateLimits.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,wBAAgB,UAAU;IAQxB,OAAO,UAAU,MAAM,SAAS,MAAM,WAAW,OAAO,CAAC,OAAO;IAUhE,MAAM,UAAU,MAAM,SAAS,MAAM,WAAW,MAAM,UAAU,OAAO;IASvE,IAAI,UAAU,MAAM,SAAS,MAAM;EAQpC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Clock, Effect } from "effect";
|
|
2
|
+
export function rateLimits() {
|
|
3
|
+
const routes = new Map();
|
|
4
|
+
const blocked = new Map();
|
|
5
|
+
let globalReset = 0;
|
|
6
|
+
function key(route, major) {
|
|
7
|
+
return `${routes.get(route) ?? route}:${major}`;
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
observe: (route, major, headers) => Effect.gen(function* () {
|
|
11
|
+
const bucket = headers["x-ratelimit-bucket"];
|
|
12
|
+
if (bucket !== undefined) {
|
|
13
|
+
routes.set(route, bucket);
|
|
14
|
+
}
|
|
15
|
+
if (headers["x-ratelimit-remaining"] === "0") {
|
|
16
|
+
blocked.set(key(route, major), (yield* Clock.currentTimeMillis) + Number(headers["x-ratelimit-reset-after"] ?? 0) * 1000);
|
|
17
|
+
}
|
|
18
|
+
}),
|
|
19
|
+
refuse: (route, major, seconds, global) => Effect.gen(function* () {
|
|
20
|
+
const reset = (yield* Clock.currentTimeMillis) + seconds * 1000;
|
|
21
|
+
if (global) {
|
|
22
|
+
globalReset = Math.max(globalReset, reset);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
blocked.set(key(route, major), reset);
|
|
26
|
+
}
|
|
27
|
+
}),
|
|
28
|
+
wait: (route, major) => Effect.gen(function* () {
|
|
29
|
+
const delay = Math.max(globalReset, blocked.get(key(route, major)) ?? 0) - (yield* Clock.currentTimeMillis);
|
|
30
|
+
if (delay > 0) {
|
|
31
|
+
yield* Effect.sleep(delay);
|
|
32
|
+
}
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=rateLimits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rateLimits.js","sourceRoot":"","sources":["../src/rateLimits.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGvC,MAAM,UAAU,UAAU;IACzB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,SAAS,GAAG,CAAC,KAAa,EAAE,KAAa;QACxC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;IACjD,CAAC;IACD,OAAO;QACN,OAAO,EAAE,CAAC,KAAa,EAAE,KAAa,EAAE,OAAwB,EAAE,EAAE,CACnE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnB,MAAM,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;YAC7C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC3B,CAAC;YACD,IAAI,OAAO,CAAC,uBAAuB,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;YAC3H,CAAC;QACF,CAAC,CAAC;QACH,MAAM,EAAE,CAAC,KAAa,EAAE,KAAa,EAAE,OAAe,EAAE,MAAe,EAAE,EAAE,CAC1E,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnB,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;YAChE,IAAI,MAAM,EAAE,CAAC;gBACZ,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACP,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;YACvC,CAAC;QACF,CAAC,CAAC;QACH,IAAI,EAAE,CAAC,KAAa,EAAE,KAAa,EAAE,EAAE,CACtC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YAC5G,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACf,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5B,CAAC;QACF,CAAC,CAAC;KACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import type { HttpMethod } from "effect/http/HttpMethod";
|
|
3
|
+
export declare function request<TSchema extends Schema.ConstraintDecoder<unknown>>(method: HttpMethod, path: string, schema: TSchema, body?: unknown): Effect.Effect<TSchema["Type"], import("./errors.ts").DiscordRateLimited | import("./errors.ts").DiscordTransportError | import("effect/http/HttpBody").HttpBodyError | import("@shivaedev/http/errors.ts").InvalidBodyLimit | import("@shivaedev/http/errors.ts").RemoteGone | import("@shivaedev/http/errors.ts").RemoteHttpError | import("@shivaedev/http/errors.ts").RemoteNotFound | import("@shivaedev/http/errors.ts").RemoteRateLimited | import("@shivaedev/http/errors.ts").RemoteUnauthorized | import("@shivaedev/http/errors.ts").ResponseBodyTooLarge | Schema.SchemaError, "@shivaedev/discord/DiscordRest" | TSchema["DecodingServices"]>;
|
|
4
|
+
//# sourceMappingURL=request.d.ts.map
|