dfx 0.51.0 → 0.51.2
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/Cache/driver.d.ts +17 -16
- package/Cache/driver.d.ts.map +1 -1
- package/Cache/driver.js +10 -2
- package/Cache/driver.js.map +1 -1
- package/Cache/memory.d.ts +3 -3
- package/Cache/memory.d.ts.map +1 -1
- package/Cache/memory.js +55 -45
- package/Cache/memory.js.map +1 -1
- package/Cache/memoryTTL.d.ts +7 -6
- package/Cache/memoryTTL.d.ts.map +1 -1
- package/Cache/memoryTTL.js +126 -118
- package/Cache/memoryTTL.js.map +1 -1
- package/Cache/prelude.d.ts +53 -47
- package/Cache/prelude.d.ts.map +1 -1
- package/Cache/prelude.js +125 -96
- package/Cache/prelude.js.map +1 -1
- package/Cache.d.ts +33 -32
- package/Cache.d.ts.map +1 -1
- package/Cache.js +137 -65
- package/Cache.js.map +1 -1
- package/DiscordConfig.d.ts +26 -20
- package/DiscordConfig.d.ts.map +1 -1
- package/DiscordConfig.js +43 -25
- package/DiscordConfig.js.map +1 -1
- package/DiscordGateway/DiscordWS.d.ts +17 -14
- package/DiscordGateway/DiscordWS.d.ts.map +1 -1
- package/DiscordGateway/DiscordWS.js +49 -30
- package/DiscordGateway/DiscordWS.js.map +1 -1
- package/DiscordGateway/Shard/heartbeats.d.ts +7 -3
- package/DiscordGateway/Shard/heartbeats.d.ts.map +1 -1
- package/DiscordGateway/Shard/heartbeats.js +28 -18
- package/DiscordGateway/Shard/heartbeats.js.map +1 -1
- package/DiscordGateway/Shard/identify.d.ts +10 -8
- package/DiscordGateway/Shard/identify.d.ts.map +1 -1
- package/DiscordGateway/Shard/identify.js +41 -24
- package/DiscordGateway/Shard/identify.js.map +1 -1
- package/DiscordGateway/Shard/invalidSession.d.ts +6 -3
- package/DiscordGateway/Shard/invalidSession.d.ts.map +1 -1
- package/DiscordGateway/Shard/invalidSession.js +14 -5
- package/DiscordGateway/Shard/invalidSession.js.map +1 -1
- package/DiscordGateway/Shard/sendEvents.d.ts +1 -1
- package/DiscordGateway/Shard/sendEvents.d.ts.map +1 -1
- package/DiscordGateway/Shard/sendEvents.js +30 -18
- package/DiscordGateway/Shard/sendEvents.js.map +1 -1
- package/DiscordGateway/Shard/utils.d.ts +7 -3
- package/DiscordGateway/Shard/utils.d.ts.map +1 -1
- package/DiscordGateway/Shard/utils.js +19 -9
- package/DiscordGateway/Shard/utils.js.map +1 -1
- package/DiscordGateway/Shard.d.ts +15 -10
- package/DiscordGateway/Shard.d.ts.map +1 -1
- package/DiscordGateway/Shard.js +109 -87
- package/DiscordGateway/Shard.js.map +1 -1
- package/DiscordGateway/ShardStore.d.ts +9 -6
- package/DiscordGateway/ShardStore.d.ts.map +1 -1
- package/DiscordGateway/ShardStore.js +30 -18
- package/DiscordGateway/ShardStore.js.map +1 -1
- package/DiscordGateway/Sharder.d.ts +17 -11
- package/DiscordGateway/Sharder.d.ts.map +1 -1
- package/DiscordGateway/Sharder.js +82 -52
- package/DiscordGateway/Sharder.js.map +1 -1
- package/DiscordGateway/WS.d.ts +13 -10
- package/DiscordGateway/WS.d.ts.map +1 -1
- package/DiscordGateway/WS.js +100 -74
- package/DiscordGateway/WS.js.map +1 -1
- package/DiscordGateway.d.ts +19 -13
- package/DiscordGateway.d.ts.map +1 -1
- package/DiscordGateway.js +45 -32
- package/DiscordGateway.js.map +1 -1
- package/DiscordREST/types.d.ts +5 -5
- package/DiscordREST/types.d.ts.map +1 -1
- package/DiscordREST/types.js +5 -1
- package/DiscordREST/types.js.map +1 -1
- package/DiscordREST/utils.d.ts +3 -2
- package/DiscordREST/utils.d.ts.map +1 -1
- package/DiscordREST/utils.js +27 -17
- package/DiscordREST/utils.js.map +1 -1
- package/DiscordREST.d.ts +11 -8
- package/DiscordREST.d.ts.map +1 -1
- package/DiscordREST.js +141 -127
- package/DiscordREST.js.map +1 -1
- package/Helpers/flags.js +31 -19
- package/Helpers/flags.js.map +1 -1
- package/Helpers/intents.d.ts.map +1 -1
- package/Helpers/intents.js +22 -10
- package/Helpers/intents.js.map +1 -1
- package/Helpers/interactions.d.ts +22 -21
- package/Helpers/interactions.d.ts.map +1 -1
- package/Helpers/interactions.js +75 -39
- package/Helpers/interactions.js.map +1 -1
- package/Helpers/members.d.ts +3 -3
- package/Helpers/members.d.ts.map +1 -1
- package/Helpers/members.js +10 -3
- package/Helpers/members.js.map +1 -1
- package/Helpers/permissions.d.ts +5 -4
- package/Helpers/permissions.d.ts.map +1 -1
- package/Helpers/permissions.js +69 -52
- package/Helpers/permissions.js.map +1 -1
- package/Helpers/ui.d.ts +1 -1
- package/Helpers/ui.d.ts.map +1 -1
- package/Helpers/ui.js +44 -29
- package/Helpers/ui.js.map +1 -1
- package/Interactions/builder.d.ts +20 -19
- package/Interactions/builder.d.ts.map +1 -1
- package/Interactions/builder.js +66 -63
- package/Interactions/builder.js.map +1 -1
- package/Interactions/context.d.ts +26 -23
- package/Interactions/context.d.ts.map +1 -1
- package/Interactions/context.js +86 -57
- package/Interactions/context.js.map +1 -1
- package/Interactions/definitions.d.ts +33 -30
- package/Interactions/definitions.d.ts.map +1 -1
- package/Interactions/definitions.js +61 -47
- package/Interactions/definitions.js.map +1 -1
- package/Interactions/gateway.d.ts +15 -10
- package/Interactions/gateway.d.ts.map +1 -1
- package/Interactions/gateway.js +55 -42
- package/Interactions/gateway.js.map +1 -1
- package/Interactions/handlers.d.ts +6 -4
- package/Interactions/handlers.d.ts.map +1 -1
- package/Interactions/handlers.js +68 -57
- package/Interactions/handlers.js.map +1 -1
- package/Interactions/index.d.ts +11 -10
- package/Interactions/index.d.ts.map +1 -1
- package/Interactions/index.js +95 -10
- package/Interactions/index.js.map +1 -1
- package/Interactions/utils.d.ts +42 -40
- package/Interactions/utils.d.ts.map +1 -1
- package/Interactions/utils.js +40 -32
- package/Interactions/utils.js.map +1 -1
- package/Interactions/webhook.d.ts +20 -16
- package/Interactions/webhook.d.ts.map +1 -1
- package/Interactions/webhook.js +73 -41
- package/Interactions/webhook.js.map +1 -1
- package/Log.d.ts +8 -5
- package/Log.d.ts.map +1 -1
- package/Log.js +23 -14
- package/Log.js.map +1 -1
- package/RateLimit/memory.d.ts +1 -1
- package/RateLimit/memory.d.ts.map +1 -1
- package/RateLimit/memory.js +46 -33
- package/RateLimit/memory.js.map +1 -1
- package/RateLimit/utils.d.ts +1 -1
- package/RateLimit/utils.d.ts.map +1 -1
- package/RateLimit/utils.js +23 -16
- package/RateLimit/utils.js.map +1 -1
- package/RateLimit.d.ts +18 -14
- package/RateLimit.d.ts.map +1 -1
- package/RateLimit.js +40 -26
- package/RateLimit.js.map +1 -1
- package/gateway.d.ts +20 -13
- package/gateway.d.ts.map +1 -1
- package/gateway.js +72 -25
- package/gateway.js.map +1 -1
- package/index.d.ts +14 -13
- package/index.d.ts.map +1 -1
- package/index.js +71 -13
- package/index.js.map +1 -1
- package/mjs/Cache/driver.mjs +3 -0
- package/mjs/Cache/driver.mjs.map +1 -0
- package/mjs/Cache/memory.mjs +48 -0
- package/mjs/Cache/memory.mjs.map +1 -0
- package/mjs/Cache/memoryTTL.mjs +119 -0
- package/mjs/Cache/memoryTTL.mjs.map +1 -0
- package/mjs/Cache/prelude.mjs +125 -0
- package/mjs/Cache/prelude.mjs.map +1 -0
- package/mjs/Cache.mjs +87 -0
- package/mjs/Cache.mjs.map +1 -0
- package/mjs/DiscordConfig.mjs +34 -0
- package/mjs/DiscordConfig.mjs.map +1 -0
- package/mjs/DiscordGateway/DiscordWS.mjs +39 -0
- package/mjs/DiscordGateway/DiscordWS.mjs.map +1 -0
- package/mjs/DiscordGateway/Shard/heartbeats.mjs +21 -0
- package/mjs/DiscordGateway/Shard/heartbeats.mjs.map +1 -0
- package/mjs/DiscordGateway/Shard/identify.mjs +37 -0
- package/mjs/DiscordGateway/Shard/identify.mjs.map +1 -0
- package/mjs/DiscordGateway/Shard/invalidSession.mjs +6 -0
- package/mjs/DiscordGateway/Shard/invalidSession.mjs.map +1 -0
- package/mjs/DiscordGateway/Shard/sendEvents.mjs +25 -0
- package/mjs/DiscordGateway/Shard/sendEvents.mjs.map +1 -0
- package/mjs/DiscordGateway/Shard/utils.mjs +11 -0
- package/mjs/DiscordGateway/Shard/utils.mjs.map +1 -0
- package/mjs/DiscordGateway/Shard.mjs +99 -0
- package/mjs/DiscordGateway/Shard.mjs.map +1 -0
- package/mjs/DiscordGateway/ShardStore.mjs +24 -0
- package/mjs/DiscordGateway/ShardStore.mjs.map +1 -0
- package/mjs/DiscordGateway/Sharder.mjs +73 -0
- package/mjs/DiscordGateway/Sharder.mjs.map +1 -0
- package/mjs/DiscordGateway/WS.mjs +94 -0
- package/mjs/DiscordGateway/WS.mjs.map +1 -0
- package/mjs/DiscordGateway.mjs +36 -0
- package/mjs/DiscordGateway.mjs.map +1 -0
- package/mjs/DiscordREST/types.mjs +2 -0
- package/mjs/DiscordREST/types.mjs.map +1 -0
- package/mjs/DiscordREST/utils.mjs +19 -0
- package/mjs/DiscordREST/utils.mjs.map +1 -0
- package/mjs/DiscordREST.mjs +129 -0
- package/mjs/DiscordREST.mjs.map +1 -0
- package/mjs/Helpers/flags.mjs +36 -0
- package/mjs/Helpers/flags.mjs.map +1 -0
- package/mjs/Helpers/intents.mjs +27 -0
- package/mjs/Helpers/intents.mjs.map +1 -0
- package/mjs/Helpers/interactions.mjs +104 -0
- package/mjs/Helpers/interactions.mjs.map +1 -0
- package/mjs/Helpers/members.mjs +9 -0
- package/mjs/Helpers/members.mjs.map +1 -0
- package/mjs/Helpers/permissions.mjs +82 -0
- package/mjs/Helpers/permissions.mjs.map +1 -0
- package/mjs/Helpers/ui.mjs +66 -0
- package/mjs/Helpers/ui.mjs.map +1 -0
- package/mjs/Interactions/builder.mjs +62 -0
- package/mjs/Interactions/builder.mjs.map +1 -0
- package/mjs/Interactions/context.mjs +63 -0
- package/mjs/Interactions/context.mjs.map +1 -0
- package/mjs/Interactions/definitions.mjs +51 -0
- package/mjs/Interactions/definitions.mjs.map +1 -0
- package/mjs/Interactions/gateway.mjs +48 -0
- package/mjs/Interactions/gateway.mjs.map +1 -0
- package/mjs/Interactions/handlers.mjs +61 -0
- package/mjs/Interactions/handlers.mjs.map +1 -0
- package/mjs/Interactions/index.mjs +12 -0
- package/mjs/Interactions/index.mjs.map +1 -0
- package/mjs/Interactions/utils.mjs +35 -0
- package/mjs/Interactions/utils.mjs.map +1 -0
- package/mjs/Interactions/webhook.mjs +73 -0
- package/mjs/Interactions/webhook.mjs.map +1 -0
- package/mjs/Log.mjs +15 -0
- package/mjs/Log.mjs.map +1 -0
- package/mjs/RateLimit/memory.mjs +39 -0
- package/mjs/RateLimit/memory.mjs.map +1 -0
- package/mjs/RateLimit/utils.mjs +18 -0
- package/mjs/RateLimit/utils.mjs.map +1 -0
- package/mjs/RateLimit.mjs +29 -0
- package/mjs/RateLimit.mjs.map +1 -0
- package/mjs/gateway.mjs +27 -0
- package/mjs/gateway.mjs.map +1 -0
- package/mjs/index.mjs +15 -0
- package/mjs/index.mjs.map +1 -0
- package/mjs/types.mjs +1211 -0
- package/mjs/types.mjs.map +1 -0
- package/mjs/utils/Effect.mjs +28 -0
- package/mjs/utils/Effect.mjs.map +1 -0
- package/mjs/utils/tsplus.mjs +2 -0
- package/mjs/utils/tsplus.mjs.map +1 -0
- package/mjs/version.mjs +2 -0
- package/mjs/version.mjs.map +1 -0
- package/mjs/webhooks.mjs +30 -0
- package/mjs/webhooks.mjs.map +1 -0
- package/package.json +46 -50
- package/src/Cache/driver.ts +27 -15
- package/src/Cache/memory.ts +9 -5
- package/src/Cache/memoryTTL.ts +69 -53
- package/src/Cache/prelude.ts +113 -91
- package/src/Cache.ts +73 -58
- package/src/DiscordConfig.ts +33 -19
- package/src/DiscordGateway/DiscordWS.ts +28 -25
- package/src/DiscordGateway/Shard/heartbeats.ts +47 -27
- package/src/DiscordGateway/Shard/identify.ts +29 -25
- package/src/DiscordGateway/Shard/invalidSession.ts +9 -7
- package/src/DiscordGateway/Shard/sendEvents.ts +1 -1
- package/src/DiscordGateway/Shard/utils.ts +33 -9
- package/src/DiscordGateway/Shard.ts +119 -99
- package/src/DiscordGateway/ShardStore.ts +12 -5
- package/src/DiscordGateway/Sharder.ts +95 -74
- package/src/DiscordGateway/WS.ts +85 -60
- package/src/DiscordGateway.ts +58 -18
- package/src/DiscordREST/types.ts +5 -5
- package/src/DiscordREST/utils.ts +10 -7
- package/src/DiscordREST.ts +152 -132
- package/src/Helpers/intents.ts +1 -0
- package/src/Helpers/interactions.ts +51 -38
- package/src/Helpers/members.ts +2 -0
- package/src/Helpers/permissions.ts +6 -5
- package/src/Helpers/ui.ts +1 -1
- package/src/Interactions/builder.ts +56 -43
- package/src/Interactions/context.ts +68 -38
- package/src/Interactions/definitions.ts +32 -24
- package/src/Interactions/gateway.ts +72 -47
- package/src/Interactions/handlers.ts +56 -39
- package/src/Interactions/index.ts +6 -5
- package/src/Interactions/utils.ts +32 -21
- package/src/Interactions/webhook.ts +78 -42
- package/src/Log.ts +4 -0
- package/src/RateLimit/memory.ts +10 -4
- package/src/RateLimit/utils.ts +1 -1
- package/src/RateLimit.ts +38 -25
- package/src/gateway.ts +62 -25
- package/src/index.ts +29 -15
- package/src/utils/Effect.ts +69 -0
- package/src/version.ts +1 -0
- package/src/webhooks.ts +47 -20
- package/tsconfig.base.json +48 -0
- package/tsconfig.build.json +10 -0
- package/tsconfig.examples.json +11 -0
- package/tsconfig.json +12 -8
- package/tsconfig.madge.json +12 -0
- package/tsconfig.test.json +10 -0
- package/types.d.ts.map +1 -1
- package/types.js +1216 -1200
- package/types.js.map +1 -1
- package/utils/Effect.d.ts +8 -0
- package/utils/Effect.d.ts.map +1 -0
- package/utils/Effect.js +38 -0
- package/utils/Effect.js.map +1 -0
- package/utils/tsplus.js +5 -1
- package/utils/tsplus.js.map +1 -1
- package/version.d.ts +2 -0
- package/version.d.ts.map +1 -0
- package/version.js +9 -0
- package/version.js.map +1 -0
- package/webhooks.d.ts +14 -9
- package/webhooks.d.ts.map +1 -1
- package/webhooks.js +76 -27
- package/webhooks.js.map +1 -1
- package/_common.d.ts +0 -37
- package/_common.d.ts.map +0 -1
- package/_common.js +0 -8
- package/_common.js.map +0 -1
- package/global.d.ts +0 -18
- package/global.d.ts.map +0 -1
- package/global.js +0 -2
- package/global.js.map +0 -1
- package/src/_common.ts +0 -43
- package/src/global.ts +0 -45
- package/src/package.json +0 -52
- package/src/utils/effect.ts +0 -0
- package/src/utils/hub.ts +0 -47
- package/tsplus.config.json +0 -8
- package/utils/effect.d.ts +0 -2
- package/utils/effect.d.ts.map +0 -1
- package/utils/effect.js +0 -2
- package/utils/effect.js.map +0 -1
- package/utils/hub.d.ts +0 -12
- package/utils/hub.d.ts.map +0 -1
- package/utils/hub.js +0 -26
- package/utils/hub.js.map +0 -1
package/src/DiscordREST.ts
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import * as Http from "@effect-http/client"
|
|
2
|
+
import { Tag } from "@effect/data/Context"
|
|
3
|
+
import * as Duration from "@effect/data/Duration"
|
|
2
4
|
import { millis } from "@effect/data/Duration"
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
+
import { pipe } from "@effect/data/Function"
|
|
6
|
+
import * as HashSet from "@effect/data/HashSet"
|
|
7
|
+
import * as Option from "@effect/data/Option"
|
|
8
|
+
import * as ConfigSecret from "@effect/io/Config/Secret"
|
|
9
|
+
import * as Effect from "@effect/io/Effect"
|
|
10
|
+
import * as Layer from "@effect/io/Layer"
|
|
11
|
+
import * as Ref from "@effect/io/Ref"
|
|
12
|
+
import { DiscordConfig } from "dfx/DiscordConfig"
|
|
13
|
+
import type { ResponseWithData, RestResponse } from "dfx/DiscordREST/types"
|
|
5
14
|
import {
|
|
6
15
|
rateLimitFromHeaders,
|
|
7
16
|
retryAfter,
|
|
8
17
|
routeFromConfig,
|
|
9
|
-
} from "
|
|
10
|
-
import { Log } from "
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
RateLimitStore,
|
|
15
|
-
RateLimiter,
|
|
16
|
-
} from "./RateLimit.js"
|
|
17
|
-
import Pkg from "./package.json" assert { type: "json" }
|
|
18
|
+
} from "dfx/DiscordREST/utils"
|
|
19
|
+
import { Log } from "dfx/Log"
|
|
20
|
+
import { LiveRateLimiter, RateLimitStore, RateLimiter } from "dfx/RateLimit"
|
|
21
|
+
import * as Discord from "dfx/types"
|
|
22
|
+
import { LIB_VERSION } from "dfx/version"
|
|
18
23
|
|
|
19
24
|
export class DiscordRESTError {
|
|
20
25
|
readonly _tag = "DiscordRESTError"
|
|
@@ -23,132 +28,149 @@ export class DiscordRESTError {
|
|
|
23
28
|
|
|
24
29
|
export { ResponseDecodeError } from "@effect-http/client"
|
|
25
30
|
|
|
26
|
-
const make =
|
|
27
|
-
const {
|
|
31
|
+
const make = Effect.gen(function* (_) {
|
|
32
|
+
const { rest, token } = yield* _(DiscordConfig)
|
|
28
33
|
|
|
29
|
-
const http =
|
|
30
|
-
const log =
|
|
31
|
-
const store =
|
|
32
|
-
const { maybeWait } =
|
|
34
|
+
const http = yield* _(Http.HttpRequestExecutor)
|
|
35
|
+
const log = yield* _(Log)
|
|
36
|
+
const store = yield* _(RateLimitStore)
|
|
37
|
+
const { maybeWait } = yield* _(RateLimiter)
|
|
33
38
|
|
|
34
39
|
const globalRateLimit = maybeWait(
|
|
35
40
|
"dfx.rest.global",
|
|
36
|
-
rest.globalRateLimit.window,
|
|
41
|
+
Duration.decode(rest.globalRateLimit.window),
|
|
37
42
|
rest.globalRateLimit.limit,
|
|
38
43
|
)
|
|
39
44
|
|
|
40
45
|
// Invalid route handling (40x)
|
|
41
|
-
const badRoutesRef =
|
|
46
|
+
const badRoutesRef = yield* _(Ref.make(HashSet.empty<string>()))
|
|
47
|
+
const tenMinutes = Duration.toMillis(Duration.minutes(10))
|
|
42
48
|
const addBadRoute = (route: string) =>
|
|
43
49
|
Effect.all(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
store.incrementCounter(
|
|
48
|
-
"dfx.rest.invalid",
|
|
49
|
-
Duration.minutes(10).toMillis,
|
|
50
|
-
10000,
|
|
51
|
-
),
|
|
52
|
-
],
|
|
50
|
+
log.info("DiscordREST", "addBadRoute", route),
|
|
51
|
+
Ref.update(badRoutesRef, HashSet.add(route)),
|
|
52
|
+
store.incrementCounter("dfx.rest.invalid", tenMinutes, 10000),
|
|
53
53
|
{ discard: true, concurrency: "unbounded" },
|
|
54
54
|
)
|
|
55
|
-
const isBadRoute = (route: string) =>
|
|
55
|
+
const isBadRoute = (route: string) =>
|
|
56
|
+
Effect.map(Ref.get(badRoutesRef), HashSet.has(route))
|
|
56
57
|
const removeBadRoute = (route: string) =>
|
|
57
|
-
|
|
58
|
+
Ref.update(badRoutesRef, HashSet.remove(route))
|
|
58
59
|
|
|
59
60
|
const invalidRateLimit = (route: string) =>
|
|
60
|
-
isBadRoute(route).
|
|
61
|
-
invalid
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
isBadRoute(route).pipe(
|
|
62
|
+
Effect.tap(invalid =>
|
|
63
|
+
invalid
|
|
64
|
+
? maybeWait("dfx.rest.invalid", Duration.minutes(10), 10000)
|
|
65
|
+
: Effect.unit,
|
|
66
|
+
),
|
|
67
|
+
Effect.asUnit,
|
|
68
|
+
)
|
|
65
69
|
|
|
66
70
|
// Request rate limiting
|
|
67
71
|
const requestRateLimit = (path: string, request: Http.Request) =>
|
|
68
|
-
Do(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
72
|
+
Effect.Do.pipe(
|
|
73
|
+
Effect.let("route", () => routeFromConfig(path, request.method)),
|
|
74
|
+
Effect.bind("maybeBucket", ({ route }) => store.getBucketForRoute(route)),
|
|
75
|
+
Effect.flatMap(({ maybeBucket, route }) =>
|
|
76
|
+
Option.match(maybeBucket, {
|
|
77
|
+
onNone: () => invalidRateLimit(route),
|
|
78
|
+
onSome: bucket =>
|
|
79
|
+
Effect.zipRight(
|
|
80
|
+
invalidRateLimit(route),
|
|
81
|
+
maybeWait(
|
|
82
|
+
`dfx.rest.${bucket.key}`,
|
|
83
|
+
millis(bucket.resetAfter),
|
|
84
|
+
bucket.limit,
|
|
85
|
+
),
|
|
86
|
+
),
|
|
87
|
+
}),
|
|
88
|
+
),
|
|
89
|
+
)
|
|
85
90
|
|
|
86
91
|
// Update rate limit buckets
|
|
87
92
|
const updateBuckets = (request: Http.Request, response: Http.Response) =>
|
|
88
|
-
Do(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
93
|
+
Effect.Do.pipe(
|
|
94
|
+
Effect.let("route", () => routeFromConfig(request.url, request.method)),
|
|
95
|
+
Effect.bind("rateLimit", () => rateLimitFromHeaders(response.headers)),
|
|
96
|
+
Effect.bind("hasBucket", ({ rateLimit }) =>
|
|
97
|
+
store.hasBucket(rateLimit.bucket),
|
|
98
|
+
),
|
|
99
|
+
Effect.flatMap(({ hasBucket, rateLimit, route }) => {
|
|
100
|
+
const effectsToRun = [
|
|
101
|
+
removeBadRoute(route),
|
|
102
|
+
store.putBucketRoute(route, rateLimit.bucket),
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
if (!hasBucket || rateLimit.limit - 1 === rateLimit.remaining) {
|
|
106
|
+
effectsToRun.push(
|
|
107
|
+
store.removeCounter(`dfx.rest.?.${route}`),
|
|
108
|
+
store.putBucket({
|
|
109
|
+
key: rateLimit.bucket,
|
|
110
|
+
resetAfter: Duration.toMillis(rateLimit.retryAfter),
|
|
111
|
+
limit:
|
|
112
|
+
!hasBucket && rateLimit.remaining > 0
|
|
113
|
+
? rateLimit.remaining
|
|
114
|
+
: rateLimit.limit,
|
|
115
|
+
}),
|
|
116
|
+
)
|
|
117
|
+
}
|
|
113
118
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
"User-Agent": `DiscordBot (https://github.com/tim-smart/dfx, ${Pkg.version})`,
|
|
119
|
+
return Effect.all(effectsToRun, {
|
|
120
|
+
concurrency: "unbounded",
|
|
121
|
+
discard: true,
|
|
122
|
+
})
|
|
119
123
|
}),
|
|
124
|
+
Effect.ignore,
|
|
120
125
|
)
|
|
121
|
-
|
|
126
|
+
|
|
127
|
+
const httpExecutor = pipe(
|
|
128
|
+
http.execute,
|
|
129
|
+
Http.executor.filterStatusOk,
|
|
130
|
+
Http.executor.contramap(req =>
|
|
131
|
+
pipe(
|
|
132
|
+
Http.updateUrl(req, _ => `${rest.baseUrl}${_}`),
|
|
133
|
+
Http.setHeaders({
|
|
134
|
+
Authorization: `Bot ${ConfigSecret.value(token)}`,
|
|
135
|
+
"User-Agent": `DiscordBot (https://github.com/tim-smart/dfx, ${LIB_VERSION})`,
|
|
136
|
+
}),
|
|
137
|
+
),
|
|
138
|
+
),
|
|
139
|
+
Http.executor.catchAll(error =>
|
|
122
140
|
error._tag === "StatusCodeError"
|
|
123
|
-
? error.response.json
|
|
124
|
-
.mapError(_ => new DiscordRESTError(_))
|
|
125
|
-
.flatMap(body =>
|
|
141
|
+
? error.response.json.pipe(
|
|
142
|
+
Effect.mapError(_ => new DiscordRESTError(_)),
|
|
143
|
+
Effect.flatMap(body =>
|
|
144
|
+
Effect.fail(new DiscordRESTError(error, body)),
|
|
145
|
+
),
|
|
146
|
+
)
|
|
126
147
|
: Effect.fail(new DiscordRESTError(error)),
|
|
127
|
-
)
|
|
148
|
+
),
|
|
149
|
+
)
|
|
128
150
|
|
|
129
151
|
const executor = <A = unknown>(
|
|
130
152
|
request: Http.Request,
|
|
131
|
-
): Effect<never, DiscordRESTError, ResponseWithData<A>> =>
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
153
|
+
): Effect.Effect<never, DiscordRESTError, ResponseWithData<A>> =>
|
|
154
|
+
requestRateLimit(request.url, request).pipe(
|
|
155
|
+
Effect.zipLeft(globalRateLimit),
|
|
156
|
+
Effect.zipRight(
|
|
157
|
+
httpExecutor(request) as Effect.Effect<
|
|
158
|
+
never,
|
|
159
|
+
DiscordRESTError,
|
|
160
|
+
ResponseWithData<A>
|
|
161
|
+
>,
|
|
162
|
+
),
|
|
163
|
+
Effect.tap(response => updateBuckets(request, response)),
|
|
164
|
+
Effect.catchTag("DiscordRESTError", e => {
|
|
165
|
+
if (e.error._tag !== "StatusCodeError") {
|
|
166
|
+
return Effect.fail(e)
|
|
167
|
+
}
|
|
145
168
|
|
|
146
|
-
|
|
169
|
+
const response = e.error.response
|
|
147
170
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
$(
|
|
171
|
+
switch (e.error.status) {
|
|
172
|
+
case 403:
|
|
173
|
+
return Effect.zipRight(
|
|
152
174
|
Effect.all(
|
|
153
175
|
[
|
|
154
176
|
log.info("DiscordREST", "403", request.url),
|
|
@@ -157,47 +179,43 @@ const make = Do($ => {
|
|
|
157
179
|
],
|
|
158
180
|
{ concurrency: "unbounded", discard: true },
|
|
159
181
|
),
|
|
182
|
+
Effect.fail(e),
|
|
160
183
|
)
|
|
161
|
-
return $(Effect.fail(e))
|
|
162
|
-
})
|
|
163
184
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
$(
|
|
185
|
+
case 429:
|
|
186
|
+
return Effect.zipRight(
|
|
167
187
|
Effect.all(
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
Duration.seconds(5),
|
|
175
|
-
),
|
|
188
|
+
log.info("DiscordREST", "429", request.url),
|
|
189
|
+
addBadRoute(routeFromConfig(request.url, request.method)),
|
|
190
|
+
updateBuckets(request, response),
|
|
191
|
+
Effect.sleep(
|
|
192
|
+
Option.getOrElse(retryAfter(response.headers), () =>
|
|
193
|
+
Duration.seconds(5),
|
|
176
194
|
),
|
|
177
|
-
|
|
195
|
+
),
|
|
178
196
|
{ concurrency: "unbounded", discard: true },
|
|
179
197
|
),
|
|
198
|
+
executor<A>(request),
|
|
180
199
|
)
|
|
181
|
-
|
|
182
|
-
})
|
|
183
|
-
}
|
|
200
|
+
}
|
|
184
201
|
|
|
185
|
-
|
|
186
|
-
|
|
202
|
+
return Effect.fail(e)
|
|
203
|
+
}),
|
|
204
|
+
)
|
|
187
205
|
|
|
188
206
|
const routes = Discord.createRoutes<Partial<Http.MakeOptions>>(
|
|
189
207
|
<R, P>({
|
|
190
208
|
method,
|
|
191
|
-
url,
|
|
192
|
-
params,
|
|
193
209
|
options = {},
|
|
210
|
+
params,
|
|
211
|
+
url,
|
|
194
212
|
}: Discord.Route<P, Partial<Http.MakeOptions>>): RestResponse<R> => {
|
|
195
213
|
const hasBody = method !== "GET" && method !== "DELETE"
|
|
196
214
|
let request = Http.make(method as any)(url, options)
|
|
197
215
|
|
|
198
216
|
if (!hasBody) {
|
|
199
217
|
if (params) {
|
|
200
|
-
request =
|
|
218
|
+
request = Http.appendParams(request, params as any)
|
|
201
219
|
}
|
|
202
220
|
} else if (
|
|
203
221
|
params &&
|
|
@@ -206,7 +224,7 @@ const make = Do($ => {
|
|
|
206
224
|
) {
|
|
207
225
|
request.body.value.value.append("payload_json", JSON.stringify(params))
|
|
208
226
|
} else if (params) {
|
|
209
|
-
request =
|
|
227
|
+
request = Http.jsonBody(request, params)
|
|
210
228
|
}
|
|
211
229
|
|
|
212
230
|
return executor(request)
|
|
@@ -223,9 +241,11 @@ export interface DiscordREST
|
|
|
223
241
|
extends Discord.Endpoints<Partial<Http.MakeOptions>> {
|
|
224
242
|
readonly executor: <A = unknown>(
|
|
225
243
|
request: Http.Request,
|
|
226
|
-
) => Effect<never, DiscordRESTError, ResponseWithData<A>>
|
|
244
|
+
) => Effect.Effect<never, DiscordRESTError, ResponseWithData<A>>
|
|
227
245
|
}
|
|
228
246
|
|
|
229
247
|
export const DiscordREST = Tag<DiscordREST>()
|
|
230
|
-
export const LiveDiscordREST =
|
|
231
|
-
LiveRateLimiter
|
|
248
|
+
export const LiveDiscordREST = Layer.provide(
|
|
249
|
+
LiveRateLimiter,
|
|
250
|
+
Layer.effect(DiscordREST, make),
|
|
251
|
+
)
|
package/src/Helpers/intents.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Option from "@effect/data/Option"
|
|
2
2
|
import * as Arr from "@effect/data/ReadonlyArray"
|
|
3
|
+
import * as Discord from "dfx/types"
|
|
4
|
+
import { identity, pipe } from "@effect/data/Function"
|
|
5
|
+
import * as HashMap from "@effect/data/HashMap"
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
|
-
*
|
|
8
|
+
* Option find a sub-command within the interaction options.
|
|
6
9
|
*/
|
|
7
10
|
export const allSubCommands = (interaction: Discord.ApplicationCommandDatum) =>
|
|
8
11
|
pipe(
|
|
@@ -13,7 +16,7 @@ export const allSubCommands = (interaction: Discord.ApplicationCommandDatum) =>
|
|
|
13
16
|
)
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
|
-
*
|
|
19
|
+
* Option find a sub-command within the interaction options.
|
|
17
20
|
*/
|
|
18
21
|
export const findSubCommand =
|
|
19
22
|
(name: string) => (interaction: Discord.ApplicationCommandDatum) =>
|
|
@@ -31,14 +34,14 @@ export const findSubCommand =
|
|
|
31
34
|
*/
|
|
32
35
|
export const isSubCommand =
|
|
33
36
|
(name: string) => (_: Discord.ApplicationCommandDatum) =>
|
|
34
|
-
findSubCommand(name)(_)
|
|
37
|
+
Option.isSome(findSubCommand(name)(_))
|
|
35
38
|
|
|
36
39
|
/**
|
|
37
|
-
*
|
|
40
|
+
* Option get the options for a sub-command
|
|
38
41
|
*/
|
|
39
42
|
export const subCommandOptions =
|
|
40
43
|
(name: string) => (_: Discord.ApplicationCommandDatum) =>
|
|
41
|
-
findSubCommand(name)(_)
|
|
44
|
+
Option.flatMapNullable(findSubCommand(name)(_), o => o.options)
|
|
42
45
|
|
|
43
46
|
/**
|
|
44
47
|
* A lens for accessing nested options in a interaction.
|
|
@@ -49,13 +52,15 @@ export const optionsWithNested = (
|
|
|
49
52
|
const optsFromOption = (
|
|
50
53
|
opt: Discord.ApplicationCommandInteractionDataOption,
|
|
51
54
|
): Discord.ApplicationCommandInteractionDataOption[] =>
|
|
52
|
-
|
|
53
|
-
.map(opts => [...opts, ...opts.flatMap(optsFromOption)])
|
|
54
|
-
.match({ onNone: () => [], onSome: identity })
|
|
55
|
+
Option.fromNullable(opt.options).pipe(
|
|
56
|
+
Option.map(opts => [...opts, ...opts.flatMap(optsFromOption)]),
|
|
57
|
+
Option.match({ onNone: () => [], onSome: identity }),
|
|
58
|
+
)
|
|
55
59
|
|
|
56
|
-
return
|
|
57
|
-
.map(opts => [...opts, ...opts.flatMap(optsFromOption)])
|
|
58
|
-
.getOrElse(() => [])
|
|
60
|
+
return Option.fromNullable(data.options).pipe(
|
|
61
|
+
Option.map(opts => [...opts, ...opts.flatMap(optsFromOption)]),
|
|
62
|
+
Option.getOrElse(() => []),
|
|
63
|
+
)
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
/**
|
|
@@ -65,7 +70,7 @@ export const transformOptions = (
|
|
|
65
70
|
options: Discord.ApplicationCommandInteractionDataOption[],
|
|
66
71
|
) =>
|
|
67
72
|
options.reduce(
|
|
68
|
-
(map, option) =>
|
|
73
|
+
(map, option) => HashMap.set(map, option.name, option.value),
|
|
69
74
|
HashMap.empty<string, string | undefined>(),
|
|
70
75
|
)
|
|
71
76
|
|
|
@@ -95,13 +100,14 @@ export const focusedOption = (
|
|
|
95
100
|
*/
|
|
96
101
|
export const optionValue =
|
|
97
102
|
(name: string) => (data: Pick<Discord.ApplicationCommandDatum, "options">) =>
|
|
98
|
-
getOption(name)(data)
|
|
103
|
+
Option.flatMapNullable(getOption(name)(data), o => o.value)
|
|
99
104
|
|
|
100
105
|
/**
|
|
101
106
|
* Try extract resolved data
|
|
102
107
|
*/
|
|
103
108
|
export const resolved = (data: Discord.Interaction) =>
|
|
104
|
-
|
|
109
|
+
Option.flatMapNullable(
|
|
110
|
+
Option.fromNullable(data.data),
|
|
105
111
|
a => (a as Discord.ApplicationCommandDatum).resolved,
|
|
106
112
|
)
|
|
107
113
|
|
|
@@ -113,19 +119,20 @@ export const resolveOptionValue =
|
|
|
113
119
|
name: string,
|
|
114
120
|
f: (id: Discord.Snowflake, data: Discord.ResolvedDatum) => T | undefined,
|
|
115
121
|
) =>
|
|
116
|
-
(a: Discord.Interaction):
|
|
117
|
-
Do(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
(a: Discord.Interaction): Option.Option<T> =>
|
|
123
|
+
Option.Do().pipe(
|
|
124
|
+
Option.bind("data", () =>
|
|
125
|
+
Option.fromNullable(a.data as Discord.ApplicationCommandDatum),
|
|
126
|
+
),
|
|
127
|
+
Option.bind("id", ({ data }) =>
|
|
128
|
+
Option.flatMapNullable(
|
|
129
|
+
getOption(name)(data),
|
|
123
130
|
({ value }) => value as Discord.Snowflake,
|
|
124
131
|
),
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
132
|
+
),
|
|
133
|
+
Option.bind("r", () => resolved(a)),
|
|
134
|
+
Option.flatMapNullable(({ id, r }) => f(id, r)),
|
|
135
|
+
)
|
|
129
136
|
|
|
130
137
|
/**
|
|
131
138
|
* Try find matching option values from the interaction.
|
|
@@ -134,16 +141,19 @@ export const resolveValues =
|
|
|
134
141
|
<T>(
|
|
135
142
|
f: (id: Discord.Snowflake, data: Discord.ResolvedDatum) => T | undefined,
|
|
136
143
|
) =>
|
|
137
|
-
(a: Discord.Interaction):
|
|
138
|
-
Do(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
a.data as Discord.MessageComponentDatum,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
(a: Discord.Interaction): Option.Option<readonly T[]> =>
|
|
145
|
+
Option.Do().pipe(
|
|
146
|
+
Option.bind("values", () =>
|
|
147
|
+
Option.flatMapNullable(
|
|
148
|
+
Option.fromNullable(a.data as Discord.MessageComponentDatum),
|
|
149
|
+
a => a.values as unknown as string[],
|
|
150
|
+
),
|
|
151
|
+
),
|
|
152
|
+
Option.bind("r", () => resolved(a)),
|
|
153
|
+
Option.map(({ values, r }) =>
|
|
154
|
+
Arr.compact(values.map(a => Option.fromNullable(f(a as any, r)))),
|
|
155
|
+
),
|
|
156
|
+
)
|
|
147
157
|
|
|
148
158
|
const extractComponents = (c: Discord.Component): Discord.Component[] => {
|
|
149
159
|
if ("components" in c) {
|
|
@@ -174,7 +184,7 @@ export const componentsWithValue = (data: Discord.ModalSubmitDatum) =>
|
|
|
174
184
|
*/
|
|
175
185
|
export const transformComponents = (options: Discord.Component[]) =>
|
|
176
186
|
(options as Discord.TextInput[]).reduce(
|
|
177
|
-
(map, c) => (c.custom_id ?
|
|
187
|
+
(map, c) => (c.custom_id ? HashMap.set(map, c.custom_id, c.value) : map),
|
|
178
188
|
HashMap.empty<string, string | undefined>(),
|
|
179
189
|
)
|
|
180
190
|
|
|
@@ -198,7 +208,10 @@ export const getComponent = (id: string) => (data: Discord.ModalSubmitDatum) =>
|
|
|
198
208
|
*/
|
|
199
209
|
export const componentValue =
|
|
200
210
|
(id: string) => (data: Discord.ModalSubmitDatum) =>
|
|
201
|
-
|
|
211
|
+
Option.flatMapNullable(
|
|
212
|
+
getComponent(id)(data),
|
|
213
|
+
o => (o as Discord.TextInput).value,
|
|
214
|
+
)
|
|
202
215
|
|
|
203
216
|
export type InteractionResponse =
|
|
204
217
|
| {
|
package/src/Helpers/members.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { pipe } from "@effect/data/Function"
|
|
2
|
+
import * as Effect from "@effect/io/Effect"
|
|
1
3
|
import * as Flags from "dfx/Helpers/flags"
|
|
2
4
|
import * as Members from "dfx/Helpers/members"
|
|
5
|
+
import * as Discord from "dfx/types"
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* A constant of all the permissions
|
|
@@ -109,7 +112,7 @@ export const applyOverwrites =
|
|
|
109
112
|
interface RolesCache<E> {
|
|
110
113
|
getForParent: (
|
|
111
114
|
parentId: string,
|
|
112
|
-
) => Effect<never, E, ReadonlyMap<string, Discord.Role>>
|
|
115
|
+
) => Effect.Effect<never, E, ReadonlyMap<string, Discord.Role>>
|
|
113
116
|
}
|
|
114
117
|
|
|
115
118
|
export const hasInChannel =
|
|
@@ -118,8 +121,7 @@ export const hasInChannel =
|
|
|
118
121
|
channel: Discord.Channel,
|
|
119
122
|
memberOrRole: Discord.GuildMember | Discord.Role,
|
|
120
123
|
) =>
|
|
121
|
-
|
|
122
|
-
const roles = $(rolesCache.getForParent(channel.guild_id!))
|
|
124
|
+
Effect.map(rolesCache.getForParent(channel.guild_id!), roles => {
|
|
123
125
|
const channelPerms = forChannel([...roles.values()])(channel)(
|
|
124
126
|
memberOrRole,
|
|
125
127
|
)
|
|
@@ -129,8 +131,7 @@ export const hasInChannel =
|
|
|
129
131
|
export const hasInGuild =
|
|
130
132
|
<E>(rolesCache: RolesCache<E>, permission: bigint) =>
|
|
131
133
|
(guildId: Discord.Snowflake, member: Discord.GuildMember) =>
|
|
132
|
-
|
|
133
|
-
const roles = $(rolesCache.getForParent(guildId))
|
|
134
|
+
Effect.map(rolesCache.getForParent(guildId), roles => {
|
|
134
135
|
const hasPerm = has(permission)
|
|
135
136
|
|
|
136
137
|
return member.roles.some(id => {
|