dfx 0.50.1 → 0.51.1
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 -95
- package/Cache/prelude.js.map +1 -1
- package/Cache.d.ts +33 -32
- package/Cache.d.ts.map +1 -1
- package/Cache.js +137 -57
- package/Cache.js.map +1 -1
- package/DiscordConfig.d.ts +26 -20
- package/DiscordConfig.d.ts.map +1 -1
- package/DiscordConfig.js +43 -26
- 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 -29
- 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 -15
- package/DiscordGateway/Shard/heartbeats.js.map +1 -1
- package/DiscordGateway/Shard/identify.d.ts +11 -8
- package/DiscordGateway/Shard/identify.d.ts.map +1 -1
- package/DiscordGateway/Shard/identify.js +41 -21
- 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 +20 -8
- 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 -81
- 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 -51
- 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 +102 -71
- package/DiscordGateway/WS.js.map +1 -1
- package/DiscordGateway.d.ts +19 -13
- package/DiscordGateway.d.ts.map +1 -1
- package/DiscordGateway.js +45 -31
- 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 +6 -4
- 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 -123
- 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 +23 -22
- package/Helpers/interactions.d.ts.map +1 -1
- package/Helpers/interactions.js +75 -40
- 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 +87 -55
- 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 -36
- 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 -42
- 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 +22 -17
- package/Interactions/webhook.d.ts.map +1 -1
- package/Interactions/webhook.js +74 -39
- 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 -24
- 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 +42 -50
- package/src/Cache/driver.ts +27 -15
- package/src/Cache/memory.ts +13 -9
- package/src/Cache/memoryTTL.ts +69 -53
- package/src/Cache/prelude.ts +113 -91
- package/src/Cache.ts +86 -61
- package/src/DiscordConfig.ts +34 -19
- package/src/DiscordGateway/DiscordWS.ts +28 -25
- package/src/DiscordGateway/Shard/heartbeats.ts +52 -27
- package/src/DiscordGateway/Shard/identify.ts +29 -23
- package/src/DiscordGateway/Shard/invalidSession.ts +9 -7
- package/src/DiscordGateway/Shard/sendEvents.ts +1 -1
- package/src/DiscordGateway/Shard/utils.ts +36 -9
- package/src/DiscordGateway/Shard.ts +129 -104
- package/src/DiscordGateway/ShardStore.ts +12 -5
- package/src/DiscordGateway/Sharder.ts +98 -77
- package/src/DiscordGateway/WS.ts +87 -58
- package/src/DiscordGateway.ts +59 -18
- package/src/DiscordREST/types.ts +5 -5
- package/src/DiscordREST/utils.ts +13 -8
- package/src/DiscordREST.ts +160 -131
- package/src/Helpers/intents.ts +1 -0
- package/src/Helpers/interactions.ts +76 -65
- 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 +67 -37
- package/src/Interactions/definitions.ts +32 -24
- package/src/Interactions/gateway.ts +80 -46
- package/src/Interactions/handlers.ts +68 -48
- package/src/Interactions/index.ts +6 -5
- package/src/Interactions/utils.ts +32 -21
- package/src/Interactions/webhook.ts +90 -51
- package/src/Log.ts +5 -1
- 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 -23
- 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,172 +28,194 @@ 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
|
-
Effect.
|
|
49
|
+
Effect.all(
|
|
44
50
|
log.info("DiscordREST", "addBadRoute", route),
|
|
45
|
-
|
|
46
|
-
store.incrementCounter(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
])
|
|
52
|
-
const isBadRoute = (route: string) => badRoutesRef.get.map(s => s.has(route))
|
|
51
|
+
Ref.update(badRoutesRef, HashSet.add(route)),
|
|
52
|
+
store.incrementCounter("dfx.rest.invalid", tenMinutes, 10000),
|
|
53
|
+
{ discard: true, concurrency: "unbounded" },
|
|
54
|
+
)
|
|
55
|
+
const isBadRoute = (route: string) =>
|
|
56
|
+
Effect.map(Ref.get(badRoutesRef), HashSet.has(route))
|
|
53
57
|
const removeBadRoute = (route: string) =>
|
|
54
|
-
|
|
58
|
+
Ref.update(badRoutesRef, HashSet.remove(route))
|
|
55
59
|
|
|
56
60
|
const invalidRateLimit = (route: string) =>
|
|
57
|
-
isBadRoute(route).
|
|
58
|
-
invalid
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
+
)
|
|
62
69
|
|
|
63
70
|
// Request rate limiting
|
|
64
71
|
const requestRateLimit = (path: string, request: Http.Request) =>
|
|
65
|
-
Do(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
+
)
|
|
82
90
|
|
|
83
91
|
// Update rate limit buckets
|
|
84
92
|
const updateBuckets = (request: Http.Request, response: Http.Response) =>
|
|
85
|
-
Do(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
+
}
|
|
110
118
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"User-Agent": `DiscordBot (https://github.com/tim-smart/dfx, ${Pkg.version})`,
|
|
119
|
+
return Effect.all(effectsToRun, {
|
|
120
|
+
concurrency: "unbounded",
|
|
121
|
+
discard: true,
|
|
122
|
+
})
|
|
116
123
|
}),
|
|
124
|
+
Effect.ignore,
|
|
117
125
|
)
|
|
118
|
-
|
|
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 =>
|
|
119
140
|
error._tag === "StatusCodeError"
|
|
120
|
-
? error.response.json
|
|
121
|
-
.mapError(_ => new DiscordRESTError(_))
|
|
122
|
-
.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
|
+
)
|
|
123
147
|
: Effect.fail(new DiscordRESTError(error)),
|
|
124
|
-
)
|
|
148
|
+
),
|
|
149
|
+
)
|
|
125
150
|
|
|
126
151
|
const executor = <A = unknown>(
|
|
127
152
|
request: Http.Request,
|
|
128
|
-
): Effect<never, DiscordRESTError, ResponseWithData<A>> =>
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const response = e.error.response
|
|
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
|
+
}
|
|
144
168
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
169
|
+
const response = e.error.response
|
|
170
|
+
|
|
171
|
+
switch (e.error.status) {
|
|
172
|
+
case 403:
|
|
173
|
+
return Effect.zipRight(
|
|
174
|
+
Effect.all(
|
|
175
|
+
[
|
|
176
|
+
log.info("DiscordREST", "403", request.url),
|
|
177
|
+
addBadRoute(routeFromConfig(request.url, request.method)),
|
|
178
|
+
updateBuckets(request, response),
|
|
179
|
+
],
|
|
180
|
+
{ concurrency: "unbounded", discard: true },
|
|
181
|
+
),
|
|
182
|
+
Effect.fail(e),
|
|
154
183
|
)
|
|
155
|
-
return $(Effect.fail(e))
|
|
156
|
-
})
|
|
157
184
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
Effect.allParDiscard([
|
|
185
|
+
case 429:
|
|
186
|
+
return Effect.zipRight(
|
|
187
|
+
Effect.all(
|
|
162
188
|
log.info("DiscordREST", "429", request.url),
|
|
163
189
|
addBadRoute(routeFromConfig(request.url, request.method)),
|
|
164
190
|
updateBuckets(request, response),
|
|
165
191
|
Effect.sleep(
|
|
166
|
-
retryAfter(response.headers)
|
|
192
|
+
Option.getOrElse(retryAfter(response.headers), () =>
|
|
167
193
|
Duration.seconds(5),
|
|
168
194
|
),
|
|
169
195
|
),
|
|
170
|
-
|
|
196
|
+
{ concurrency: "unbounded", discard: true },
|
|
197
|
+
),
|
|
198
|
+
executor<A>(request),
|
|
171
199
|
)
|
|
172
|
-
|
|
173
|
-
})
|
|
174
|
-
}
|
|
200
|
+
}
|
|
175
201
|
|
|
176
|
-
|
|
177
|
-
|
|
202
|
+
return Effect.fail(e)
|
|
203
|
+
}),
|
|
204
|
+
)
|
|
178
205
|
|
|
179
206
|
const routes = Discord.createRoutes<Partial<Http.MakeOptions>>(
|
|
180
207
|
<R, P>({
|
|
181
208
|
method,
|
|
182
|
-
url,
|
|
183
|
-
params,
|
|
184
209
|
options = {},
|
|
210
|
+
params,
|
|
211
|
+
url,
|
|
185
212
|
}: Discord.Route<P, Partial<Http.MakeOptions>>): RestResponse<R> => {
|
|
186
213
|
const hasBody = method !== "GET" && method !== "DELETE"
|
|
187
214
|
let request = Http.make(method as any)(url, options)
|
|
188
215
|
|
|
189
216
|
if (!hasBody) {
|
|
190
217
|
if (params) {
|
|
191
|
-
request =
|
|
218
|
+
request = Http.appendParams(request, params as any)
|
|
192
219
|
}
|
|
193
220
|
} else if (
|
|
194
221
|
params &&
|
|
@@ -197,7 +224,7 @@ const make = Do($ => {
|
|
|
197
224
|
) {
|
|
198
225
|
request.body.value.value.append("payload_json", JSON.stringify(params))
|
|
199
226
|
} else if (params) {
|
|
200
|
-
request =
|
|
227
|
+
request = Http.jsonBody(request, params)
|
|
201
228
|
}
|
|
202
229
|
|
|
203
230
|
return executor(request)
|
|
@@ -214,9 +241,11 @@ export interface DiscordREST
|
|
|
214
241
|
extends Discord.Endpoints<Partial<Http.MakeOptions>> {
|
|
215
242
|
readonly executor: <A = unknown>(
|
|
216
243
|
request: Http.Request,
|
|
217
|
-
) => Effect<never, DiscordRESTError, ResponseWithData<A>>
|
|
244
|
+
) => Effect.Effect<never, DiscordRESTError, ResponseWithData<A>>
|
|
218
245
|
}
|
|
219
246
|
|
|
220
247
|
export const DiscordREST = Tag<DiscordREST>()
|
|
221
|
-
export const LiveDiscordREST =
|
|
222
|
-
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) =>
|
|
@@ -29,14 +32,16 @@ export const findSubCommand =
|
|
|
29
32
|
/**
|
|
30
33
|
* If the sub-command exists return `true`, else `false`.
|
|
31
34
|
*/
|
|
32
|
-
export const isSubCommand =
|
|
33
|
-
|
|
35
|
+
export const isSubCommand =
|
|
36
|
+
(name: string) => (_: Discord.ApplicationCommandDatum) =>
|
|
37
|
+
Option.isSome(findSubCommand(name)(_))
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
|
-
*
|
|
40
|
+
* Option get the options for a sub-command
|
|
37
41
|
*/
|
|
38
|
-
export const subCommandOptions =
|
|
39
|
-
|
|
42
|
+
export const subCommandOptions =
|
|
43
|
+
(name: string) => (_: Discord.ApplicationCommandDatum) =>
|
|
44
|
+
Option.flatMapNullable(findSubCommand(name)(_), o => o.options)
|
|
40
45
|
|
|
41
46
|
/**
|
|
42
47
|
* A lens for accessing nested options in a interaction.
|
|
@@ -47,13 +52,15 @@ export const optionsWithNested = (
|
|
|
47
52
|
const optsFromOption = (
|
|
48
53
|
opt: Discord.ApplicationCommandInteractionDataOption,
|
|
49
54
|
): Discord.ApplicationCommandInteractionDataOption[] =>
|
|
50
|
-
|
|
51
|
-
.map(opts => [...opts, ...opts.flatMap(optsFromOption)])
|
|
52
|
-
.match(() => [], identity)
|
|
55
|
+
Option.fromNullable(opt.options).pipe(
|
|
56
|
+
Option.map(opts => [...opts, ...opts.flatMap(optsFromOption)]),
|
|
57
|
+
Option.match({ onNone: () => [], onSome: identity }),
|
|
58
|
+
)
|
|
53
59
|
|
|
54
|
-
return
|
|
55
|
-
.map(opts => [...opts, ...opts.flatMap(optsFromOption)])
|
|
56
|
-
.getOrElse(() => [])
|
|
60
|
+
return Option.fromNullable(data.options).pipe(
|
|
61
|
+
Option.map(opts => [...opts, ...opts.flatMap(optsFromOption)]),
|
|
62
|
+
Option.getOrElse(() => []),
|
|
63
|
+
)
|
|
57
64
|
}
|
|
58
65
|
|
|
59
66
|
/**
|
|
@@ -63,43 +70,44 @@ export const transformOptions = (
|
|
|
63
70
|
options: Discord.ApplicationCommandInteractionDataOption[],
|
|
64
71
|
) =>
|
|
65
72
|
options.reduce(
|
|
66
|
-
(map, option) =>
|
|
73
|
+
(map, option) => HashMap.set(map, option.name, option.value),
|
|
67
74
|
HashMap.empty<string, string | undefined>(),
|
|
68
75
|
)
|
|
69
76
|
|
|
70
77
|
/**
|
|
71
78
|
* Return the interaction options as a name / value map.
|
|
72
79
|
*/
|
|
73
|
-
export const optionsMap =
|
|
80
|
+
export const optionsMap = (
|
|
81
|
+
data: Pick<Discord.ApplicationCommandDatum, "options">,
|
|
82
|
+
) => transformOptions(optionsWithNested(data))
|
|
74
83
|
|
|
75
84
|
/**
|
|
76
85
|
* Try find a matching option from the interaction.
|
|
77
86
|
*/
|
|
78
|
-
export const getOption =
|
|
79
|
-
|
|
80
|
-
optionsWithNested,
|
|
81
|
-
Arr.findFirst(o => o.name === name),
|
|
82
|
-
)
|
|
87
|
+
export const getOption =
|
|
88
|
+
(name: string) => (data: Pick<Discord.ApplicationCommandDatum, "options">) =>
|
|
89
|
+
Arr.findFirst(optionsWithNested(data), o => o.name === name)
|
|
83
90
|
|
|
84
91
|
/**
|
|
85
92
|
* Try find a matching option from the interaction.
|
|
86
93
|
*/
|
|
87
|
-
export const focusedOption =
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
)
|
|
94
|
+
export const focusedOption = (
|
|
95
|
+
data: Pick<Discord.ApplicationCommandDatum, "options">,
|
|
96
|
+
) => Arr.findFirst(optionsWithNested(data), o => o.focused === true)
|
|
91
97
|
|
|
92
98
|
/**
|
|
93
99
|
* Try find a matching option value from the interaction.
|
|
94
100
|
*/
|
|
95
|
-
export const optionValue =
|
|
96
|
-
|
|
101
|
+
export const optionValue =
|
|
102
|
+
(name: string) => (data: Pick<Discord.ApplicationCommandDatum, "options">) =>
|
|
103
|
+
Option.flatMapNullable(getOption(name)(data), o => o.value)
|
|
97
104
|
|
|
98
105
|
/**
|
|
99
106
|
* Try extract resolved data
|
|
100
107
|
*/
|
|
101
108
|
export const resolved = (data: Discord.Interaction) =>
|
|
102
|
-
|
|
109
|
+
Option.flatMapNullable(
|
|
110
|
+
Option.fromNullable(data.data),
|
|
103
111
|
a => (a as Discord.ApplicationCommandDatum).resolved,
|
|
104
112
|
)
|
|
105
113
|
|
|
@@ -111,19 +119,20 @@ export const resolveOptionValue =
|
|
|
111
119
|
name: string,
|
|
112
120
|
f: (id: Discord.Snowflake, data: Discord.ResolvedDatum) => T | undefined,
|
|
113
121
|
) =>
|
|
114
|
-
(a: Discord.Interaction):
|
|
115
|
-
Do(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
|
|
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),
|
|
121
130
|
({ value }) => value as Discord.Snowflake,
|
|
122
131
|
),
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
132
|
+
),
|
|
133
|
+
Option.bind("r", () => resolved(a)),
|
|
134
|
+
Option.flatMapNullable(({ id, r }) => f(id, r)),
|
|
135
|
+
)
|
|
127
136
|
|
|
128
137
|
/**
|
|
129
138
|
* Try find matching option values from the interaction.
|
|
@@ -132,18 +141,19 @@ export const resolveValues =
|
|
|
132
141
|
<T>(
|
|
133
142
|
f: (id: Discord.Snowflake, data: Discord.ResolvedDatum) => T | undefined,
|
|
134
143
|
) =>
|
|
135
|
-
(a: Discord.Interaction):
|
|
136
|
-
Do(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
a.data as Discord.MessageComponentDatum,
|
|
140
|
-
|
|
141
|
-
|
|
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) {
|
|
@@ -166,41 +176,42 @@ export const components = (
|
|
|
166
176
|
/**
|
|
167
177
|
* A lens for accessing the components in a interaction.
|
|
168
178
|
*/
|
|
169
|
-
export const componentsWithValue =
|
|
170
|
-
components,
|
|
171
|
-
Arr.filter(c => "value" in c && c.value !== undefined),
|
|
172
|
-
)
|
|
179
|
+
export const componentsWithValue = (data: Discord.ModalSubmitDatum) =>
|
|
180
|
+
Arr.filter(components(data), c => "value" in c && c.value !== undefined)
|
|
173
181
|
|
|
174
182
|
/**
|
|
175
183
|
* Return the interaction components as an id / value map.
|
|
176
184
|
*/
|
|
177
185
|
export const transformComponents = (options: Discord.Component[]) =>
|
|
178
186
|
(options as Discord.TextInput[]).reduce(
|
|
179
|
-
(map, c) => (c.custom_id ?
|
|
187
|
+
(map, c) => (c.custom_id ? HashMap.set(map, c.custom_id, c.value) : map),
|
|
180
188
|
HashMap.empty<string, string | undefined>(),
|
|
181
189
|
)
|
|
182
190
|
|
|
183
191
|
/**
|
|
184
192
|
* Return the interaction components as an id / value map.
|
|
185
193
|
*/
|
|
186
|
-
export const componentsMap =
|
|
194
|
+
export const componentsMap = (data: Discord.ModalSubmitDatum) =>
|
|
195
|
+
transformComponents(components(data))
|
|
187
196
|
|
|
188
197
|
/**
|
|
189
198
|
* Try find a matching component from the interaction.
|
|
190
199
|
*/
|
|
191
|
-
export const getComponent = (id: string) =>
|
|
192
|
-
|
|
193
|
-
components,
|
|
194
|
-
|
|
200
|
+
export const getComponent = (id: string) => (data: Discord.ModalSubmitDatum) =>
|
|
201
|
+
Arr.findFirst(
|
|
202
|
+
components(data),
|
|
203
|
+
o => (o as Discord.TextInput).custom_id === id,
|
|
195
204
|
)
|
|
196
205
|
|
|
197
206
|
/**
|
|
198
207
|
* Try find a matching component value from the interaction.
|
|
199
208
|
*/
|
|
200
|
-
export const componentValue =
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
209
|
+
export const componentValue =
|
|
210
|
+
(id: string) => (data: Discord.ModalSubmitDatum) =>
|
|
211
|
+
Option.flatMapNullable(
|
|
212
|
+
getComponent(id)(data),
|
|
213
|
+
o => (o as Discord.TextInput).value,
|
|
214
|
+
)
|
|
204
215
|
|
|
205
216
|
export type InteractionResponse =
|
|
206
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 => {
|