dfx 0.61.5 → 0.61.7
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/memoryTTL.d.ts.map +1 -1
- package/Cache/memoryTTL.js.map +1 -1
- package/Cache/prelude.d.ts +3 -3
- package/Cache/prelude.d.ts.map +1 -1
- package/Cache/prelude.js.map +1 -1
- package/Cache.d.ts.map +1 -1
- package/Cache.js.map +1 -1
- package/DiscordGateway/DiscordWS.d.ts +1 -1
- package/DiscordGateway/DiscordWS.d.ts.map +1 -1
- package/DiscordGateway/DiscordWS.js.map +1 -1
- package/DiscordGateway/Shard/heartbeats.d.ts.map +1 -1
- package/DiscordGateway/Shard/heartbeats.js.map +1 -1
- package/DiscordGateway/Shard/sendEvents.js +9 -6
- package/DiscordGateway/Shard/sendEvents.js.map +1 -1
- package/DiscordGateway/Shard/utils.d.ts.map +1 -1
- package/DiscordGateway/Shard/utils.js.map +1 -1
- package/DiscordGateway/Shard.d.ts +2 -2
- package/DiscordGateway/Shard.d.ts.map +1 -1
- package/DiscordGateway/Shard.js +18 -15
- package/DiscordGateway/Shard.js.map +1 -1
- package/DiscordGateway/Sharder.d.ts +2 -2
- package/DiscordGateway/Sharder.d.ts.map +1 -1
- package/DiscordGateway/Sharder.js +9 -9
- package/DiscordGateway/Sharder.js.map +1 -1
- package/DiscordGateway/WS.d.ts +0 -1
- package/DiscordGateway/WS.d.ts.map +1 -1
- package/DiscordGateway/WS.js +9 -14
- package/DiscordGateway/WS.js.map +1 -1
- package/DiscordGateway.d.ts +1 -1
- package/DiscordGateway.d.ts.map +1 -1
- package/DiscordGateway.js +1 -1
- package/DiscordGateway.js.map +1 -1
- package/DiscordREST/utils.d.ts.map +1 -1
- package/DiscordREST/utils.js.map +1 -1
- package/DiscordREST.d.ts +1 -1
- package/DiscordREST.d.ts.map +1 -1
- package/DiscordREST.js.map +1 -1
- package/Helpers/flags.d.ts.map +1 -1
- package/Helpers/flags.js.map +1 -1
- package/Helpers/intents.d.ts.map +1 -1
- package/Helpers/intents.js.map +1 -1
- package/Helpers/interactions.d.ts.map +1 -1
- package/Helpers/interactions.js +3 -2
- package/Helpers/interactions.js.map +1 -1
- package/Helpers/members.d.ts.map +1 -1
- package/Helpers/members.js.map +1 -1
- package/Helpers/permissions.js.map +1 -1
- package/Helpers/ui.js +12 -11
- package/Helpers/ui.js.map +1 -1
- package/Interactions/builder.d.ts.map +1 -1
- package/Interactions/builder.js.map +1 -1
- package/Interactions/context.d.ts.map +1 -1
- package/Interactions/context.js.map +1 -1
- package/Interactions/definitions.d.ts.map +1 -1
- package/Interactions/definitions.js.map +1 -1
- package/Interactions/gateway.d.ts.map +1 -1
- package/Interactions/gateway.js.map +1 -1
- package/Interactions/handlers.d.ts.map +1 -1
- package/Interactions/handlers.js +7 -7
- package/Interactions/handlers.js.map +1 -1
- package/Interactions/index.d.ts.map +1 -1
- package/Interactions/index.js.map +1 -1
- package/Interactions/utils.d.ts.map +1 -1
- package/Interactions/utils.js.map +1 -1
- package/Interactions/webhook.d.ts.map +1 -1
- package/Interactions/webhook.js.map +1 -1
- package/Log.js.map +1 -1
- package/RateLimit.d.ts.map +1 -1
- package/RateLimit.js.map +1 -1
- package/gateway.d.ts +1 -1
- package/mjs/Cache/memoryTTL.mjs.map +1 -1
- package/mjs/Cache/prelude.mjs.map +1 -1
- package/mjs/Cache.mjs.map +1 -1
- package/mjs/DiscordGateway/DiscordWS.mjs.map +1 -1
- package/mjs/DiscordGateway/Shard/heartbeats.mjs.map +1 -1
- package/mjs/DiscordGateway/Shard/sendEvents.mjs +7 -6
- package/mjs/DiscordGateway/Shard/sendEvents.mjs.map +1 -1
- package/mjs/DiscordGateway/Shard/utils.mjs.map +1 -1
- package/mjs/DiscordGateway/Shard.mjs +18 -15
- package/mjs/DiscordGateway/Shard.mjs.map +1 -1
- package/mjs/DiscordGateway/Sharder.mjs +9 -9
- package/mjs/DiscordGateway/Sharder.mjs.map +1 -1
- package/mjs/DiscordGateway/WS.mjs +9 -14
- package/mjs/DiscordGateway/WS.mjs.map +1 -1
- package/mjs/DiscordGateway.mjs +1 -1
- package/mjs/DiscordGateway.mjs.map +1 -1
- package/mjs/DiscordREST/utils.mjs.map +1 -1
- package/mjs/DiscordREST.mjs.map +1 -1
- package/mjs/Helpers/flags.mjs.map +1 -1
- package/mjs/Helpers/intents.mjs.map +1 -1
- package/mjs/Helpers/interactions.mjs +3 -2
- package/mjs/Helpers/interactions.mjs.map +1 -1
- package/mjs/Helpers/members.mjs.map +1 -1
- package/mjs/Helpers/permissions.mjs.map +1 -1
- package/mjs/Helpers/ui.mjs +12 -11
- package/mjs/Helpers/ui.mjs.map +1 -1
- package/mjs/Interactions/builder.mjs.map +1 -1
- package/mjs/Interactions/context.mjs.map +1 -1
- package/mjs/Interactions/definitions.mjs.map +1 -1
- package/mjs/Interactions/gateway.mjs.map +1 -1
- package/mjs/Interactions/handlers.mjs +7 -7
- package/mjs/Interactions/handlers.mjs.map +1 -1
- package/mjs/Interactions/index.mjs.map +1 -1
- package/mjs/Interactions/utils.mjs.map +1 -1
- package/mjs/Interactions/webhook.mjs.map +1 -1
- package/mjs/Log.mjs.map +1 -1
- package/mjs/RateLimit.mjs.map +1 -1
- package/mjs/types.mjs +733 -9
- package/mjs/types.mjs.map +1 -1
- package/mjs/utils/Effect.mjs +4 -4
- package/mjs/utils/Effect.mjs.map +1 -1
- package/mjs/version.mjs +1 -1
- package/mjs/webhooks.mjs.map +1 -1
- package/package.json +2 -2
- package/src/Cache/memoryTTL.ts +4 -6
- package/src/Cache/prelude.ts +13 -15
- package/src/Cache.ts +5 -2
- package/src/DiscordGateway/DiscordWS.ts +6 -5
- package/src/DiscordGateway/Shard/heartbeats.ts +2 -3
- package/src/DiscordGateway/Shard/utils.ts +10 -9
- package/src/DiscordGateway/Shard.ts +38 -38
- package/src/DiscordGateway/Sharder.ts +19 -17
- package/src/DiscordGateway/WS.ts +34 -37
- package/src/DiscordGateway.ts +12 -8
- package/src/DiscordREST/utils.ts +2 -4
- package/src/DiscordREST.ts +24 -26
- package/src/Helpers/flags.ts +4 -2
- package/src/Helpers/intents.ts +4 -3
- package/src/Helpers/interactions.ts +54 -51
- package/src/Helpers/members.ts +2 -2
- package/src/Helpers/permissions.ts +2 -2
- package/src/Interactions/builder.ts +18 -20
- package/src/Interactions/context.ts +31 -18
- package/src/Interactions/definitions.ts +36 -27
- package/src/Interactions/gateway.ts +85 -82
- package/src/Interactions/handlers.ts +35 -34
- package/src/Interactions/index.ts +20 -16
- package/src/Interactions/utils.ts +17 -13
- package/src/Interactions/webhook.ts +15 -19
- package/src/Log.ts +2 -2
- package/src/RateLimit.ts +4 -5
- package/src/types.ts +172 -188
- package/src/utils/Effect.ts +34 -33
- package/src/version.ts +1 -1
- package/src/webhooks.ts +1 -4
- package/types.d.ts +140 -132
- package/types.d.ts.map +1 -1
- package/types.js +784 -10
- package/types.js.map +1 -1
- package/utils/Effect.d.ts.map +1 -1
- package/utils/Effect.js +4 -4
- package/utils/Effect.js.map +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/webhooks.d.ts +1 -1
- package/webhooks.d.ts.map +1 -1
- package/webhooks.js.map +1 -1
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as Chunk from "@effect/data/Chunk"
|
|
2
2
|
import { Tag } from "@effect/data/Context"
|
|
3
3
|
import * as Duration from "@effect/data/Duration"
|
|
4
|
+
import { pipe } from "@effect/data/Function"
|
|
4
5
|
import * as Option from "@effect/data/Option"
|
|
5
6
|
import * as ConfigSecret from "@effect/io/Config/Secret"
|
|
6
7
|
import * as Effect from "@effect/io/Effect"
|
|
@@ -26,7 +27,7 @@ const enum Phase {
|
|
|
26
27
|
Connected,
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
export const make = Effect.gen(function*(_) {
|
|
30
|
+
export const make = Effect.gen(function* (_) {
|
|
30
31
|
const { gateway, token } = yield* _(DiscordConfig)
|
|
31
32
|
const limiter = yield* _(RateLimiter)
|
|
32
33
|
const dws = yield* _(DiscordWS)
|
|
@@ -37,7 +38,7 @@ export const make = Effect.gen(function*(_) {
|
|
|
37
38
|
hub: Hub.Hub<Discord.GatewayPayload<Discord.ReceiveEvent>>,
|
|
38
39
|
sendQueue: Queue.Dequeue<Discord.GatewayPayload<Discord.SendEvent>>,
|
|
39
40
|
) =>
|
|
40
|
-
Effect.gen(function*(_) {
|
|
41
|
+
Effect.gen(function* (_) {
|
|
41
42
|
const outboundQueue = yield* _(Queue.unbounded<Message>())
|
|
42
43
|
const pendingQueue = yield* _(Queue.unbounded<Message>())
|
|
43
44
|
const phase = yield* _(Ref.make(Phase.Connecting))
|
|
@@ -52,67 +53,66 @@ export const make = Effect.gen(function*(_) {
|
|
|
52
53
|
Effect.flatMap(Ref.get(phase), phase =>
|
|
53
54
|
phase === Phase.Connected
|
|
54
55
|
? Queue.offer(outboundQueue, p)
|
|
55
|
-
: Queue.offer(pendingQueue, p)
|
|
56
|
+
: Queue.offer(pendingQueue, p),
|
|
57
|
+
)
|
|
56
58
|
|
|
57
59
|
const heartbeatSend = (p: Message) =>
|
|
58
60
|
Effect.flatMap(Ref.get(phase), phase =>
|
|
59
61
|
phase !== Phase.Connecting
|
|
60
62
|
? Queue.offer(outboundQueue, p)
|
|
61
|
-
: Effect.succeed(false)
|
|
63
|
+
: Effect.succeed(false),
|
|
64
|
+
)
|
|
62
65
|
|
|
63
66
|
const prioritySend = (p: Message) => Queue.offer(outboundQueue, p)
|
|
64
67
|
|
|
65
|
-
const resume =
|
|
68
|
+
const resume = pipe(
|
|
69
|
+
setPhase(Phase.Connected),
|
|
66
70
|
Effect.zipRight(Queue.takeAll(pendingQueue)),
|
|
67
71
|
Effect.tap(_ => Queue.offerAll(outboundQueue, _)),
|
|
68
72
|
Effect.asUnit,
|
|
69
73
|
)
|
|
70
74
|
|
|
71
|
-
const onConnecting =
|
|
75
|
+
const onConnecting = pipe(
|
|
76
|
+
Queue.takeAll(outboundQueue),
|
|
72
77
|
Effect.tap(msgs =>
|
|
73
78
|
Queue.offerAll(
|
|
74
79
|
pendingQueue,
|
|
75
80
|
Chunk.filter(
|
|
76
81
|
msgs,
|
|
77
82
|
msg =>
|
|
78
|
-
msg !== Reconnect
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
msg !== Reconnect &&
|
|
84
|
+
msg.op !== Discord.GatewayOpcode.IDENTIFY &&
|
|
85
|
+
msg.op !== Discord.GatewayOpcode.RESUME &&
|
|
86
|
+
msg.op !== Discord.GatewayOpcode.HEARTBEAT,
|
|
82
87
|
),
|
|
83
|
-
)
|
|
88
|
+
),
|
|
84
89
|
),
|
|
85
90
|
Effect.zipRight(setPhase(Phase.Connecting)),
|
|
86
91
|
)
|
|
87
92
|
|
|
88
93
|
const socket = yield* _(dws.connect({ outbound, onConnecting }))
|
|
89
94
|
|
|
95
|
+
const isReady = Option.liftPredicate(
|
|
96
|
+
(
|
|
97
|
+
p: Discord.GatewayPayload,
|
|
98
|
+
): p is Discord.GatewayPayload<Discord.ReadyEvent> =>
|
|
99
|
+
p.op === Discord.GatewayOpcode.DISPATCH && p.t === "READY",
|
|
100
|
+
)
|
|
101
|
+
|
|
90
102
|
const [latestReady, updateLatestReady] = yield* _(
|
|
91
|
-
Utils.latest(p =>
|
|
92
|
-
Option.some(p).pipe(
|
|
93
|
-
Option.filter(
|
|
94
|
-
(p): p is Discord.GatewayPayload<Discord.ReadyEvent> =>
|
|
95
|
-
p.op === Discord.GatewayOpcode.DISPATCH && p.t === "READY",
|
|
96
|
-
),
|
|
97
|
-
Option.map(p => p.d!),
|
|
98
|
-
)
|
|
99
|
-
),
|
|
103
|
+
Utils.latest(p => Option.map(isReady(p), p => p.d!)),
|
|
100
104
|
)
|
|
101
105
|
const [latestSequence, updateLatestSequence] = yield* _(
|
|
102
106
|
Utils.latest(p => Option.fromNullable(p.s)),
|
|
103
107
|
)
|
|
104
108
|
const maybeUpdateUrl = (p: Discord.GatewayPayload) =>
|
|
105
|
-
Option.
|
|
106
|
-
Option.
|
|
107
|
-
|
|
108
|
-
p.op === Discord.GatewayOpcode.DISPATCH && p.t === "READY",
|
|
109
|
-
),
|
|
110
|
-
Option.map(p => p.d!),
|
|
111
|
-
Option.match({
|
|
109
|
+
Option.match(
|
|
110
|
+
Option.map(isReady(p), p => p.d!),
|
|
111
|
+
{
|
|
112
112
|
onNone: () => Effect.unit,
|
|
113
113
|
onSome: ({ resume_gateway_url }) =>
|
|
114
114
|
socket.setUrl(resume_gateway_url),
|
|
115
|
-
}
|
|
115
|
+
},
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
const hellos = yield* _(Queue.unbounded<Discord.GatewayPayload>())
|
|
@@ -139,13 +139,15 @@ export const make = Effect.gen(function*(_) {
|
|
|
139
139
|
)
|
|
140
140
|
|
|
141
141
|
const onPayload = (p: Discord.GatewayPayload) =>
|
|
142
|
-
|
|
142
|
+
pipe(
|
|
143
|
+
updateLatestReady(p),
|
|
143
144
|
Effect.zipRight(updateLatestSequence(p)),
|
|
144
145
|
Effect.zipRight(maybeUpdateUrl(p)),
|
|
145
146
|
Effect.tap(() => {
|
|
146
147
|
switch (p.op) {
|
|
147
148
|
case Discord.GatewayOpcode.HELLO:
|
|
148
|
-
return
|
|
149
|
+
return pipe(
|
|
150
|
+
Effect.tap(identify, prioritySend),
|
|
149
151
|
Effect.zipRight(setPhase(Phase.Handshake)),
|
|
150
152
|
Effect.zipRight(Queue.offer(hellos, p)),
|
|
151
153
|
)
|
|
@@ -161,20 +163,19 @@ export const make = Effect.gen(function*(_) {
|
|
|
161
163
|
return Effect.zipRight(resume, Hub.publish(hub, p))
|
|
162
164
|
}
|
|
163
165
|
return Hub.publish(hub, p)
|
|
166
|
+
default:
|
|
167
|
+
return Effect.unit
|
|
164
168
|
}
|
|
165
|
-
|
|
166
|
-
return Effect.unit
|
|
167
169
|
}),
|
|
168
170
|
)
|
|
169
171
|
|
|
170
|
-
const drainSendQueue =
|
|
171
|
-
Effect.tap(send),
|
|
172
|
-
Effect.forever,
|
|
172
|
+
const drainSendQueue = Effect.forever(
|
|
173
|
+
Effect.tap(Queue.take(sendQueue), send),
|
|
173
174
|
)
|
|
174
175
|
|
|
175
176
|
const run = Effect.all(
|
|
176
177
|
[
|
|
177
|
-
|
|
178
|
+
Effect.forever(Effect.flatMap(socket.take, onPayload)),
|
|
178
179
|
heartbeats,
|
|
179
180
|
drainSendQueue,
|
|
180
181
|
socket.run,
|
|
@@ -196,5 +197,4 @@ export const LiveShard = Layer.provide(
|
|
|
196
197
|
)
|
|
197
198
|
|
|
198
199
|
export interface RunningShard
|
|
199
|
-
extends Effect.Effect.Success<ReturnType<Shard["connect"]>>
|
|
200
|
-
{}
|
|
200
|
+
extends Effect.Effect.Success<ReturnType<Shard["connect"]>> {}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as Chunk from "@effect/data/Chunk"
|
|
2
2
|
import { Tag } from "@effect/data/Context"
|
|
3
3
|
import * as Duration from "@effect/data/Duration"
|
|
4
|
+
import { pipe } from "@effect/data/Function"
|
|
4
5
|
import * as HashSet from "@effect/data/HashSet"
|
|
5
6
|
import type * as Option from "@effect/data/Option"
|
|
6
7
|
import * as Deferred from "@effect/io/Deferred"
|
|
@@ -24,7 +25,7 @@ const claimRepeatPolicy = Schedule.spaced("3 minutes").pipe(
|
|
|
24
25
|
Schedule.passthrough,
|
|
25
26
|
) as Schedule.Schedule<never, Option.Option<number>, Option.Some<number>>
|
|
26
27
|
|
|
27
|
-
const make = Effect.gen(function*(_) {
|
|
28
|
+
const make = Effect.gen(function* (_) {
|
|
28
29
|
const store = yield* _(ShardStore)
|
|
29
30
|
const rest = yield* _(DiscordREST)
|
|
30
31
|
const { gateway: config } = yield* _(DiscordConfig)
|
|
@@ -33,25 +34,25 @@ const make = Effect.gen(function*(_) {
|
|
|
33
34
|
const currentShards = yield* _(Ref.make(HashSet.empty<RunningShard>()))
|
|
34
35
|
|
|
35
36
|
const takeConfig = (totalCount: number) =>
|
|
36
|
-
Effect.gen(function*(_) {
|
|
37
|
+
Effect.gen(function* (_) {
|
|
37
38
|
const currentCount = yield* _(Ref.make(0))
|
|
38
39
|
|
|
39
40
|
const claimId = (
|
|
40
41
|
sharderCount: number,
|
|
41
42
|
): Effect.Effect<never, never, number> =>
|
|
42
|
-
|
|
43
|
-
.claimId({
|
|
43
|
+
pipe(
|
|
44
|
+
store.claimId({
|
|
44
45
|
totalCount,
|
|
45
46
|
sharderCount,
|
|
46
|
-
})
|
|
47
|
-
.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
)
|
|
47
|
+
}),
|
|
48
|
+
Effect.repeat(claimRepeatPolicy),
|
|
49
|
+
Effect.map(_ => _.value),
|
|
50
|
+
)
|
|
51
51
|
|
|
52
|
-
return
|
|
52
|
+
return pipe(
|
|
53
|
+
Ref.getAndUpdate(currentCount, _ => _ + 1),
|
|
53
54
|
Effect.flatMap(claimId),
|
|
54
|
-
Effect.map(id => ({ id, totalCount } as const)
|
|
55
|
+
Effect.map(id => ({ id, totalCount }) as const),
|
|
55
56
|
)
|
|
56
57
|
})
|
|
57
58
|
|
|
@@ -68,7 +69,7 @@ const make = Effect.gen(function*(_) {
|
|
|
68
69
|
reset_after: 0,
|
|
69
70
|
max_concurrency: 1,
|
|
70
71
|
},
|
|
71
|
-
})
|
|
72
|
+
}),
|
|
72
73
|
),
|
|
73
74
|
)
|
|
74
75
|
|
|
@@ -76,13 +77,14 @@ const make = Effect.gen(function*(_) {
|
|
|
76
77
|
hub: Hub.Hub<Discord.GatewayPayload<Discord.ReceiveEvent>>,
|
|
77
78
|
sendQueue: Queue.Dequeue<Discord.GatewayPayload<Discord.SendEvent>>,
|
|
78
79
|
) =>
|
|
79
|
-
Effect.gen(function*(_) {
|
|
80
|
+
Effect.gen(function* (_) {
|
|
80
81
|
const deferred = yield* _(
|
|
81
82
|
Deferred.make<WebSocketError | WebSocketCloseError, never>(),
|
|
82
83
|
)
|
|
83
84
|
const take = yield* _(takeConfig(config.shardCount ?? gateway.shards))
|
|
84
85
|
|
|
85
|
-
const spawner =
|
|
86
|
+
const spawner = pipe(
|
|
87
|
+
take,
|
|
86
88
|
Effect.map(config => ({
|
|
87
89
|
...config,
|
|
88
90
|
url: gateway.url,
|
|
@@ -93,10 +95,10 @@ const make = Effect.gen(function*(_) {
|
|
|
93
95
|
`dfx.sharder.${id % concurrency}`,
|
|
94
96
|
Duration.millis(config.identifyRateLimit[0]),
|
|
95
97
|
config.identifyRateLimit[1],
|
|
96
|
-
)
|
|
98
|
+
),
|
|
97
99
|
),
|
|
98
100
|
Effect.flatMap(c =>
|
|
99
|
-
shard.connect([c.id, c.totalCount], hub, sendQueue)
|
|
101
|
+
shard.connect([c.id, c.totalCount], hub, sendQueue),
|
|
100
102
|
),
|
|
101
103
|
Effect.flatMap(shard =>
|
|
102
104
|
Effect.acquireUseRelease(
|
|
@@ -106,7 +108,7 @@ const make = Effect.gen(function*(_) {
|
|
|
106
108
|
).pipe(
|
|
107
109
|
Effect.catchAllCause(_ => Deferred.failCause(deferred, _)),
|
|
108
110
|
Effect.fork,
|
|
109
|
-
)
|
|
111
|
+
),
|
|
110
112
|
),
|
|
111
113
|
Effect.forever,
|
|
112
114
|
)
|
package/src/DiscordGateway/WS.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Tag } from "@effect/data/Context"
|
|
2
2
|
import * as Duration from "@effect/data/Duration"
|
|
3
|
+
import { pipe } from "@effect/data/Function"
|
|
3
4
|
import * as Effect from "@effect/io/Effect"
|
|
4
5
|
import * as Layer from "@effect/io/Layer"
|
|
5
6
|
import * as Queue from "@effect/io/Queue"
|
|
6
7
|
import * as Ref from "@effect/io/Ref"
|
|
7
|
-
import * as Runtime from "@effect/io/Runtime"
|
|
8
8
|
import { Log } from "dfx/Log"
|
|
9
9
|
import WebSocket from "isomorphic-ws"
|
|
10
10
|
|
|
@@ -22,7 +22,10 @@ export class WebSocketError {
|
|
|
22
22
|
|
|
23
23
|
export class WebSocketCloseError {
|
|
24
24
|
readonly _tag = "WebSocketCloseError"
|
|
25
|
-
constructor(
|
|
25
|
+
constructor(
|
|
26
|
+
readonly code: number,
|
|
27
|
+
readonly reason: string,
|
|
28
|
+
) {}
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
const isReconnect = (
|
|
@@ -31,14 +34,15 @@ const isReconnect = (
|
|
|
31
34
|
e._tag === "WebSocketCloseError" && e.code === 1012
|
|
32
35
|
|
|
33
36
|
const socket = (urlRef: Ref.Ref<string>) =>
|
|
34
|
-
|
|
37
|
+
pipe(
|
|
38
|
+
Ref.get(urlRef),
|
|
35
39
|
Effect.map(_ => new WebSocket(_) as any as globalThis.WebSocket),
|
|
36
40
|
Effect.acquireRelease(ws =>
|
|
37
41
|
Effect.sync(() => {
|
|
38
42
|
// eslint-disable-next-line no-extra-semi
|
|
39
43
|
;(ws as any).removeAllListeners?.()
|
|
40
44
|
ws.close()
|
|
41
|
-
})
|
|
45
|
+
}),
|
|
42
46
|
),
|
|
43
47
|
)
|
|
44
48
|
|
|
@@ -47,34 +51,24 @@ const offer = (
|
|
|
47
51
|
queue: Queue.Enqueue<WebSocket.Data>,
|
|
48
52
|
log: Log,
|
|
49
53
|
) =>
|
|
50
|
-
Effect.
|
|
51
|
-
|
|
52
|
-
Effect.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
log.debug("WS", "receive", message.data),
|
|
60
|
-
Queue.offer(queue, message.data),
|
|
61
|
-
],
|
|
62
|
-
{ concurrency: "unbounded", discard: true },
|
|
63
|
-
),
|
|
64
|
-
)
|
|
65
|
-
})
|
|
54
|
+
Effect.async<never, WebSocketError | WebSocketCloseError, never>(resume => {
|
|
55
|
+
ws.addEventListener("message", message => {
|
|
56
|
+
Effect.runFork(
|
|
57
|
+
Effect.zipRight(
|
|
58
|
+
log.debug("WS", "receive", message.data),
|
|
59
|
+
Queue.offer(queue, message.data),
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
})
|
|
66
63
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
ws.addEventListener("error", cause => {
|
|
65
|
+
resume(Effect.fail(new WebSocketError("error", cause)))
|
|
66
|
+
})
|
|
70
67
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
)
|
|
76
|
-
),
|
|
77
|
-
)
|
|
68
|
+
ws.addEventListener("close", e => {
|
|
69
|
+
resume(Effect.fail(new WebSocketCloseError(e.code, e.reason)))
|
|
70
|
+
})
|
|
71
|
+
})
|
|
78
72
|
|
|
79
73
|
const waitForOpen = (ws: globalThis.WebSocket, timeout: Duration.Duration) =>
|
|
80
74
|
Effect.timeoutFail(
|
|
@@ -100,7 +94,8 @@ const send = (
|
|
|
100
94
|
take: Effect.Effect<never, never, Message>,
|
|
101
95
|
log: Log,
|
|
102
96
|
) =>
|
|
103
|
-
|
|
97
|
+
pipe(
|
|
98
|
+
take,
|
|
104
99
|
Effect.tap(data => log.debug("WS", "send", data)),
|
|
105
100
|
Effect.tap(data => {
|
|
106
101
|
if (data === Reconnect) {
|
|
@@ -117,7 +112,7 @@ const send = (
|
|
|
117
112
|
Effect.forever,
|
|
118
113
|
)
|
|
119
114
|
|
|
120
|
-
const make = Effect.gen(function*(_) {
|
|
115
|
+
const make = Effect.gen(function* (_) {
|
|
121
116
|
const log = yield* _(Log)
|
|
122
117
|
|
|
123
118
|
const connect = (
|
|
@@ -126,21 +121,23 @@ const make = Effect.gen(function*(_) {
|
|
|
126
121
|
onConnecting = Effect.unit,
|
|
127
122
|
openTimeout = Duration.seconds(3),
|
|
128
123
|
) =>
|
|
129
|
-
Effect.gen(function*(_) {
|
|
124
|
+
Effect.gen(function* (_) {
|
|
130
125
|
const queue = yield* _(Queue.unbounded<WebSocket.Data>())
|
|
131
126
|
|
|
132
|
-
const run =
|
|
127
|
+
const run = pipe(
|
|
128
|
+
onConnecting,
|
|
133
129
|
Effect.zipRight(socket(url)),
|
|
134
130
|
Effect.flatMap(ws =>
|
|
135
131
|
Effect.all(
|
|
136
132
|
[
|
|
137
133
|
offer(ws, queue, log),
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
Effect.zipRight(
|
|
135
|
+
waitForOpen(ws, openTimeout),
|
|
136
|
+
send(ws, takeOutbound, log),
|
|
140
137
|
),
|
|
141
138
|
],
|
|
142
139
|
{ concurrency: "unbounded", discard: true },
|
|
143
|
-
)
|
|
140
|
+
),
|
|
144
141
|
),
|
|
145
142
|
Effect.scoped,
|
|
146
143
|
Effect.retryWhile(isReconnect),
|
package/src/DiscordGateway.ts
CHANGED
|
@@ -11,13 +11,17 @@ import type { WebSocketCloseError, WebSocketError } from "dfx/DiscordGateway/WS"
|
|
|
11
11
|
import type * as Discord from "dfx/types"
|
|
12
12
|
import * as EffectUtils from "dfx/utils/Effect"
|
|
13
13
|
|
|
14
|
-
const fromDispatchFactory =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Stream.
|
|
14
|
+
const fromDispatchFactory =
|
|
15
|
+
<R, E>(
|
|
16
|
+
source: Stream.Stream<R, E, Discord.GatewayPayload<Discord.ReceiveEvent>>,
|
|
17
|
+
) =>
|
|
18
|
+
<K extends keyof Discord.ReceiveEvents>(
|
|
19
|
+
event: K,
|
|
20
|
+
): Stream.Stream<R, E, Discord.ReceiveEvents[K]> =>
|
|
21
|
+
Stream.map(
|
|
22
|
+
Stream.filter(source, p => p.t === event),
|
|
23
|
+
p => p.d! as any,
|
|
24
|
+
)
|
|
21
25
|
|
|
22
26
|
const handleDispatchFactory =
|
|
23
27
|
(hub: Hub.Hub<Discord.GatewayPayload<Discord.ReceiveEvent>>) =>
|
|
@@ -57,7 +61,7 @@ export interface DiscordGateway {
|
|
|
57
61
|
}
|
|
58
62
|
export const DiscordGateway = Tag<DiscordGateway>()
|
|
59
63
|
|
|
60
|
-
export const make = Effect.gen(function*(_) {
|
|
64
|
+
export const make = Effect.gen(function* (_) {
|
|
61
65
|
const sharder = yield* _(Sharder)
|
|
62
66
|
const hub = yield* _(
|
|
63
67
|
Hub.unbounded<Discord.GatewayPayload<Discord.ReceiveEvent>>(),
|
package/src/DiscordREST/utils.ts
CHANGED
|
@@ -9,10 +9,8 @@ export const routeFromConfig = (path: string, method: string) => {
|
|
|
9
9
|
// Only keep major ID's
|
|
10
10
|
const routeURL = path
|
|
11
11
|
.split("?")[0]
|
|
12
|
-
.replace(
|
|
13
|
-
|
|
14
|
-
(match, resource) =>
|
|
15
|
-
majorResources.includes(resource) ? match : `/${resource}`,
|
|
12
|
+
.replace(/\/([A-Za-z]+)\/(\d{16,21}|@me)/g, (match, resource) =>
|
|
13
|
+
majorResources.includes(resource) ? match : `/${resource}`,
|
|
16
14
|
)
|
|
17
15
|
// Strip reactions
|
|
18
16
|
.replace(/\/reactions\/(.*)/, "/reactions")
|
package/src/DiscordREST.ts
CHANGED
|
@@ -29,7 +29,7 @@ export class DiscordRESTError {
|
|
|
29
29
|
) {}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const make = Effect.gen(function*(_) {
|
|
32
|
+
const make = Effect.gen(function* (_) {
|
|
33
33
|
const { rest, token } = yield* _(DiscordConfig)
|
|
34
34
|
|
|
35
35
|
const http = yield* _(Http.client.Client)
|
|
@@ -65,7 +65,7 @@ const make = Effect.gen(function*(_) {
|
|
|
65
65
|
Effect.tap(invalid =>
|
|
66
66
|
invalid
|
|
67
67
|
? maybeWait("dfx.rest.invalid", Duration.minutes(10), 10000)
|
|
68
|
-
: Effect.unit
|
|
68
|
+
: Effect.unit,
|
|
69
69
|
),
|
|
70
70
|
Effect.asUnit,
|
|
71
71
|
)
|
|
@@ -90,7 +90,7 @@ const make = Effect.gen(function*(_) {
|
|
|
90
90
|
bucket.limit,
|
|
91
91
|
),
|
|
92
92
|
),
|
|
93
|
-
})
|
|
93
|
+
}),
|
|
94
94
|
),
|
|
95
95
|
)
|
|
96
96
|
|
|
@@ -102,9 +102,8 @@ const make = Effect.gen(function*(_) {
|
|
|
102
102
|
Effect.Do.pipe(
|
|
103
103
|
Effect.let("route", () => routeFromConfig(request.url, request.method)),
|
|
104
104
|
Effect.bind("rateLimit", () => rateLimitFromHeaders(response.headers)),
|
|
105
|
-
Effect.bind(
|
|
106
|
-
|
|
107
|
-
({ rateLimit }) => store.hasBucket(rateLimit.bucket),
|
|
105
|
+
Effect.bind("hasBucket", ({ rateLimit }) =>
|
|
106
|
+
store.hasBucket(rateLimit.bucket),
|
|
108
107
|
),
|
|
109
108
|
Effect.flatMap(({ hasBucket, rateLimit, route }) => {
|
|
110
109
|
const effectsToRun = [
|
|
@@ -118,9 +117,10 @@ const make = Effect.gen(function*(_) {
|
|
|
118
117
|
store.putBucket({
|
|
119
118
|
key: rateLimit.bucket,
|
|
120
119
|
resetAfter: Duration.toMillis(rateLimit.retryAfter),
|
|
121
|
-
limit:
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
limit:
|
|
121
|
+
!hasBucket && rateLimit.remaining > 0
|
|
122
|
+
? rateLimit.remaining
|
|
123
|
+
: rateLimit.limit,
|
|
124
124
|
}),
|
|
125
125
|
)
|
|
126
126
|
}
|
|
@@ -140,20 +140,19 @@ const make = Effect.gen(function*(_) {
|
|
|
140
140
|
Http.request.prependUrl(req, rest.baseUrl),
|
|
141
141
|
Http.request.setHeaders({
|
|
142
142
|
Authorization: `Bot ${ConfigSecret.value(token)}`,
|
|
143
|
-
"User-Agent":
|
|
144
|
-
`DiscordBot (https://github.com/tim-smart/dfx, ${LIB_VERSION})`,
|
|
143
|
+
"User-Agent": `DiscordBot (https://github.com/tim-smart/dfx, ${LIB_VERSION})`,
|
|
145
144
|
}),
|
|
146
|
-
)
|
|
145
|
+
),
|
|
147
146
|
),
|
|
148
147
|
Http.client.catchAll(error =>
|
|
149
148
|
error.reason === "StatusCode"
|
|
150
149
|
? error.response.json.pipe(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
: Effect.fail(new DiscordRESTError(error))
|
|
150
|
+
Effect.mapError(_ => new DiscordRESTError(_)),
|
|
151
|
+
Effect.flatMap(body =>
|
|
152
|
+
Effect.fail(new DiscordRESTError(error, body)),
|
|
153
|
+
),
|
|
154
|
+
)
|
|
155
|
+
: Effect.fail(new DiscordRESTError(error)),
|
|
157
156
|
),
|
|
158
157
|
)
|
|
159
158
|
|
|
@@ -201,9 +200,8 @@ const make = Effect.gen(function*(_) {
|
|
|
201
200
|
Effect.zipRight(updateBuckets(request, response)),
|
|
202
201
|
Effect.zipRight(
|
|
203
202
|
Effect.sleep(
|
|
204
|
-
Option.getOrElse(
|
|
205
|
-
|
|
206
|
-
() => Duration.seconds(5),
|
|
203
|
+
Option.getOrElse(retryAfter(response.headers), () =>
|
|
204
|
+
Duration.seconds(5),
|
|
207
205
|
),
|
|
208
206
|
),
|
|
209
207
|
),
|
|
@@ -221,9 +219,10 @@ const make = Effect.gen(function*(_) {
|
|
|
221
219
|
options = {},
|
|
222
220
|
params,
|
|
223
221
|
url,
|
|
224
|
-
}: Discord.Route<
|
|
225
|
-
|
|
226
|
-
|
|
222
|
+
}: Discord.Route<
|
|
223
|
+
P,
|
|
224
|
+
Partial<Http.request.Options.NoUrl>
|
|
225
|
+
>): RestResponse<R> => {
|
|
227
226
|
const hasBody = method !== "GET" && method !== "DELETE"
|
|
228
227
|
let request = Http.request.make(method as any)(url, options)
|
|
229
228
|
|
|
@@ -248,8 +247,7 @@ const make = Effect.gen(function*(_) {
|
|
|
248
247
|
})
|
|
249
248
|
|
|
250
249
|
export interface DiscordREST
|
|
251
|
-
extends Discord.Endpoints<Partial<Http.request.Options.NoUrl>>
|
|
252
|
-
{
|
|
250
|
+
extends Discord.Endpoints<Partial<Http.request.Options.NoUrl>> {
|
|
253
251
|
readonly executor: <A = unknown>(
|
|
254
252
|
request: Http.request.ClientRequest,
|
|
255
253
|
) => Effect.Effect<never, DiscordRESTError, ResponseWithData<A>>
|
package/src/Helpers/flags.ts
CHANGED
|
@@ -33,14 +33,16 @@ export function toList<T extends Flags<any>>(
|
|
|
33
33
|
* Returns a function that converts a list of flags names to a bigint bitfield.
|
|
34
34
|
*/
|
|
35
35
|
export const fromListBigint =
|
|
36
|
-
<T extends Flags<bigint>>(flags: T) =>
|
|
36
|
+
<T extends Flags<bigint>>(flags: T) =>
|
|
37
|
+
(list: Array<keyof T>) =>
|
|
37
38
|
list.reduce((acc, key) => acc | flags[key], BigInt(0))
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* Returns a function that converts a list of flags names to a bitfield.
|
|
41
42
|
*/
|
|
42
43
|
export const fromList =
|
|
43
|
-
<T extends Flags<number>>(flags: T) =>
|
|
44
|
+
<T extends Flags<number>>(flags: T) =>
|
|
45
|
+
(list: Array<keyof T>) =>
|
|
44
46
|
list.reduce((acc, key) => acc | flags[key], 0)
|
|
45
47
|
|
|
46
48
|
/**
|
package/src/Helpers/intents.ts
CHANGED
|
@@ -9,9 +9,10 @@ export const ALL = Flags.all(Discord.GatewayIntents)
|
|
|
9
9
|
/**
|
|
10
10
|
* Privileged intents
|
|
11
11
|
*/
|
|
12
|
-
export const PRIVILEGED =
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
export const PRIVILEGED =
|
|
13
|
+
Discord.GatewayIntents.GUILD_PRESENCES |
|
|
14
|
+
Discord.GatewayIntents.GUILD_MEMBERS |
|
|
15
|
+
Discord.GatewayIntents.MESSAGE_CONTENT
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Un-privileged intents
|