dfx 0.77.2 → 0.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cache/prelude.d.ts +3 -3
- package/DiscordConfig.d.ts +7 -6
- package/DiscordConfig.d.ts.map +1 -1
- package/DiscordConfig.js +1 -3
- package/DiscordConfig.js.map +1 -1
- package/DiscordGateway/DiscordWS.d.ts +12 -11
- package/DiscordGateway/DiscordWS.d.ts.map +1 -1
- package/DiscordGateway/DiscordWS.js +8 -5
- package/DiscordGateway/DiscordWS.js.map +1 -1
- package/DiscordGateway/Messaging.d.ts +28 -0
- package/DiscordGateway/Messaging.d.ts.map +1 -0
- package/DiscordGateway/Messaging.js +41 -0
- package/DiscordGateway/Messaging.js.map +1 -0
- package/DiscordGateway/Shard.d.ts +14 -11
- package/DiscordGateway/Shard.d.ts.map +1 -1
- package/DiscordGateway/Shard.js +20 -17
- package/DiscordGateway/Shard.js.map +1 -1
- package/DiscordGateway/ShardStore.d.ts +5 -2
- package/DiscordGateway/ShardStore.d.ts.map +1 -1
- package/DiscordGateway/ShardStore.js +1 -1
- package/DiscordGateway/ShardStore.js.map +1 -1
- package/DiscordGateway/Sharder.d.ts +9 -18
- package/DiscordGateway/Sharder.d.ts.map +1 -1
- package/DiscordGateway/Sharder.js +36 -45
- package/DiscordGateway/Sharder.js.map +1 -1
- package/DiscordGateway/WS.d.ts +14 -10
- package/DiscordGateway/WS.d.ts.map +1 -1
- package/DiscordGateway/WS.js +31 -21
- package/DiscordGateway/WS.js.map +1 -1
- package/DiscordGateway.d.ts +10 -7
- package/DiscordGateway.d.ts.map +1 -1
- package/DiscordGateway.js +13 -31
- package/DiscordGateway.js.map +1 -1
- package/DiscordREST.d.ts +6 -4
- package/DiscordREST.d.ts.map +1 -1
- package/DiscordREST.js +7 -6
- package/DiscordREST.js.map +1 -1
- package/Interactions/context.d.ts +35 -17
- package/Interactions/context.d.ts.map +1 -1
- package/Interactions/context.js +6 -6
- package/Interactions/context.js.map +1 -1
- package/Interactions/definitions.d.ts +11 -11
- package/Interactions/definitions.d.ts.map +1 -1
- package/Interactions/definitions.js.map +1 -1
- package/Interactions/gateway.d.ts +7 -6
- package/Interactions/gateway.d.ts.map +1 -1
- package/Interactions/gateway.js +1 -1
- package/Interactions/gateway.js.map +1 -1
- package/Interactions/handlers.d.ts +2 -1
- package/Interactions/handlers.d.ts.map +1 -1
- package/Interactions/webhook.d.ts +5 -6
- package/Interactions/webhook.d.ts.map +1 -1
- package/Interactions/webhook.js +1 -1
- package/Interactions/webhook.js.map +1 -1
- package/RateLimit/memory.d.ts +2 -2
- package/RateLimit/memory.d.ts.map +1 -1
- package/RateLimit/memory.js.map +1 -1
- package/RateLimit.d.ts +10 -9
- package/RateLimit.d.ts.map +1 -1
- package/RateLimit.js +4 -5
- package/RateLimit.js.map +1 -1
- package/gateway.d.ts +2 -2
- package/gateway.d.ts.map +1 -1
- package/gateway.js +1 -2
- package/gateway.js.map +1 -1
- package/index.d.ts +1 -2
- package/index.d.ts.map +1 -1
- package/index.js +1 -3
- package/index.js.map +1 -1
- package/mjs/DiscordConfig.mjs +1 -3
- package/mjs/DiscordConfig.mjs.map +1 -1
- package/mjs/DiscordGateway/DiscordWS.mjs +8 -5
- package/mjs/DiscordGateway/DiscordWS.mjs.map +1 -1
- package/mjs/DiscordGateway/Messaging.mjs +33 -0
- package/mjs/DiscordGateway/Messaging.mjs.map +1 -0
- package/mjs/DiscordGateway/Shard.mjs +20 -17
- package/mjs/DiscordGateway/Shard.mjs.map +1 -1
- package/mjs/DiscordGateway/ShardStore.mjs +1 -1
- package/mjs/DiscordGateway/ShardStore.mjs.map +1 -1
- package/mjs/DiscordGateway/Sharder.mjs +35 -44
- package/mjs/DiscordGateway/Sharder.mjs.map +1 -1
- package/mjs/DiscordGateway/WS.mjs +32 -22
- package/mjs/DiscordGateway/WS.mjs.map +1 -1
- package/mjs/DiscordGateway.mjs +12 -30
- package/mjs/DiscordGateway.mjs.map +1 -1
- package/mjs/DiscordREST.mjs +7 -6
- package/mjs/DiscordREST.mjs.map +1 -1
- package/mjs/Interactions/context.mjs +6 -6
- package/mjs/Interactions/context.mjs.map +1 -1
- package/mjs/Interactions/definitions.mjs.map +1 -1
- package/mjs/Interactions/gateway.mjs +1 -1
- package/mjs/Interactions/gateway.mjs.map +1 -1
- package/mjs/Interactions/webhook.mjs +1 -1
- package/mjs/Interactions/webhook.mjs.map +1 -1
- package/mjs/RateLimit/memory.mjs.map +1 -1
- package/mjs/RateLimit.mjs +4 -5
- package/mjs/RateLimit.mjs.map +1 -1
- package/mjs/gateway.mjs +1 -2
- package/mjs/gateway.mjs.map +1 -1
- package/mjs/index.mjs +1 -2
- package/mjs/index.mjs.map +1 -1
- package/mjs/version.mjs +1 -1
- package/mjs/webhooks.mjs +1 -2
- package/mjs/webhooks.mjs.map +1 -1
- package/package.json +2 -2
- package/src/DiscordConfig.ts +10 -8
- package/src/DiscordGateway/DiscordWS.ts +23 -13
- package/src/DiscordGateway/Messaging.ts +72 -0
- package/src/DiscordGateway/Shard.ts +51 -33
- package/src/DiscordGateway/ShardStore.ts +8 -3
- package/src/DiscordGateway/Sharder.ts +72 -97
- package/src/DiscordGateway/WS.ts +64 -32
- package/src/DiscordGateway.ts +22 -71
- package/src/DiscordREST.ts +40 -27
- package/src/Interactions/context.ts +47 -10
- package/src/Interactions/definitions.ts +22 -20
- package/src/Interactions/gateway.ts +14 -6
- package/src/Interactions/handlers.ts +1 -1
- package/src/Interactions/webhook.ts +18 -4
- package/src/RateLimit/memory.ts +2 -2
- package/src/RateLimit.ts +17 -8
- package/src/gateway.ts +0 -2
- package/src/index.ts +0 -2
- package/src/version.ts +1 -1
- package/src/webhooks.ts +1 -2
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/webhooks.d.ts +1 -2
- package/webhooks.d.ts.map +1 -1
- package/webhooks.js +1 -2
- package/webhooks.js.map +1 -1
- package/src/Log.ts +0 -24
package/mjs/index.mjs
CHANGED
|
@@ -7,9 +7,8 @@ import * as Members from "dfx/Helpers/members";
|
|
|
7
7
|
import * as Perms from "dfx/Helpers/permissions";
|
|
8
8
|
import * as UI from "dfx/Helpers/ui";
|
|
9
9
|
import * as Ix from "dfx/Interactions/index";
|
|
10
|
-
import * as Log from "dfx/Log";
|
|
11
10
|
import * as Discord from "dfx/types";
|
|
12
11
|
export { DiscordREST, DiscordRESTLive } from "dfx/DiscordREST";
|
|
13
12
|
export { MemoryRateLimitStoreLive, RateLimiterLive, RateLimiter, RateLimitStore } from "dfx/RateLimit";
|
|
14
|
-
export { Cache, Discord, DiscordConfig, Flags, Intents, Ix, IxHelpers,
|
|
13
|
+
export { Cache, Discord, DiscordConfig, Flags, Intents, Ix, IxHelpers, Members, Perms, UI };
|
|
15
14
|
//# sourceMappingURL=index.mjs.map
|
package/mjs/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["Cache","DiscordConfig","Flags","Intents","IxHelpers","Members","Perms","UI","Ix","
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["Cache","DiscordConfig","Flags","Intents","IxHelpers","Members","Perms","UI","Ix","Discord","DiscordREST","DiscordRESTLive","MemoryRateLimitStoreLive","RateLimiterLive","RateLimiter","RateLimitStore"],"sources":["../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,OAAO,KAAKA,KAAK,MAAM,WAAW;AAClC,OAAO,KAAKC,aAAa,MAAM,mBAAmB;AAClD,OAAO,KAAKC,KAAK,MAAM,mBAAmB;AAC1C,OAAO,KAAKC,OAAO,MAAM,qBAAqB;AAC9C,OAAO,KAAKC,SAAS,MAAM,0BAA0B;AACrD,OAAO,KAAKC,OAAO,MAAM,qBAAqB;AAC9C,OAAO,KAAKC,KAAK,MAAM,yBAAyB;AAChD,OAAO,KAAKC,EAAE,MAAM,gBAAgB;AACpC,OAAO,KAAKC,EAAE,MAAM,wBAAwB;AAC5C,OAAO,KAAKC,OAAO,MAAM,WAAW;AAEpC,SAASC,WAAW,EAAEC,eAAe,QAAQ,iBAAiB;AAE9D,SAEEC,wBAAwB,EACxBC,eAAe,EACfC,WAAW,EACXC,cAAc,QACT,eAAe;AAEtB,SACEf,KAAK,EACLS,OAAO,EACPR,aAAa,EACbC,KAAK,EACLC,OAAO,EACPK,EAAE,EACFJ,SAAS,EACTC,OAAO,EACPC,KAAK,EACLC,EAAE"}
|
package/mjs/version.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const LIB_VERSION = "0.
|
|
1
|
+
export const LIB_VERSION = "0.78.0";
|
|
2
2
|
//# sourceMappingURL=version.mjs.map
|
package/mjs/webhooks.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { DiscordRESTLive } from "dfx/DiscordREST";
|
|
2
|
-
import * as Log from "dfx/Log";
|
|
3
2
|
import { MemoryRateLimitStoreLive, RateLimiterLive } from "dfx/RateLimit";
|
|
4
3
|
import * as Layer from "effect/Layer";
|
|
5
4
|
export { BadWebhookSignature, WebhookConfig, WebhookParseError, makeHandler, makeSimpleHandler, layer as webhookLayer, layerConfig as webhookLayerConfig } from "dfx/Interactions/webhook";
|
|
6
|
-
export const DiscordLive = /*#__PURE__*/Layer.mergeAll(DiscordRESTLive, RateLimiterLive).pipe( /*#__PURE__*/Layer.provide(MemoryRateLimitStoreLive)
|
|
5
|
+
export const DiscordLive = /*#__PURE__*/Layer.mergeAll(DiscordRESTLive, RateLimiterLive).pipe( /*#__PURE__*/Layer.provide(MemoryRateLimitStoreLive));
|
|
7
6
|
//# sourceMappingURL=webhooks.mjs.map
|
package/mjs/webhooks.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.mjs","names":["DiscordRESTLive","
|
|
1
|
+
{"version":3,"file":"webhooks.mjs","names":["DiscordRESTLive","MemoryRateLimitStoreLive","RateLimiterLive","Layer","BadWebhookSignature","WebhookConfig","WebhookParseError","makeHandler","makeSimpleHandler","layer","webhookLayer","layerConfig","webhookLayerConfig","DiscordLive","mergeAll","pipe","provide"],"sources":["../src/webhooks.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,eAAe,QAAQ,iBAAiB;AACjD,SACEC,wBAAoD,EACpDC,eAAkC,QAC7B,eAAe;AACtB,OAAO,KAAKC,KAAK,MAAM,cAAc;AAErC,SACEC,mBAAmB,EACnBC,aAAa,EACbC,iBAAiB,EACjBC,WAAW,EACXC,iBAAiB,EACjBC,KAAK,IAAIC,YAAY,EACrBC,WAAW,IAAIC,kBAAkB,QAC5B,0BAA0B;AAEjC,OAAO,MAAMC,WAAW,gBAAGV,KAAK,CAACW,QAAQ,CACvCd,eAAe,EACfE,eAAe,CAChB,CAACa,IAAI,eAACZ,KAAK,CAACa,OAAO,CAACf,wBAAwB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dfx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.78.0",
|
|
4
4
|
"description": "Effect-TS discord library",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -48,6 +48,6 @@
|
|
|
48
48
|
"utf-8-validate": "^6.0.3",
|
|
49
49
|
"zlib-sync": "^0.1.9"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "efc2997291e09256e66f3654d4bc1ae3422291c8",
|
|
52
52
|
"main": "./index.js"
|
|
53
53
|
}
|
package/src/DiscordConfig.ts
CHANGED
|
@@ -10,8 +10,11 @@ import * as Discord from "dfx/types"
|
|
|
10
10
|
const VERSION = 10
|
|
11
11
|
|
|
12
12
|
export interface DiscordConfig {
|
|
13
|
+
readonly _: unique symbol
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface DiscordConfigService {
|
|
13
17
|
readonly token: ConfigSecret.ConfigSecret
|
|
14
|
-
readonly debug: boolean
|
|
15
18
|
readonly rest: {
|
|
16
19
|
readonly baseUrl: string
|
|
17
20
|
readonly globalRateLimit: {
|
|
@@ -27,23 +30,22 @@ export interface DiscordConfig {
|
|
|
27
30
|
readonly identifyRateLimit: readonly [window: number, limit: number]
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
|
-
export const DiscordConfig = Tag<DiscordConfig>(
|
|
33
|
+
export const DiscordConfig = Tag<DiscordConfig, DiscordConfigService>(
|
|
34
|
+
"dfx/DiscordConfig",
|
|
35
|
+
)
|
|
31
36
|
|
|
32
37
|
export interface MakeOpts {
|
|
33
38
|
readonly token: ConfigSecret.ConfigSecret
|
|
34
|
-
readonly
|
|
35
|
-
readonly
|
|
36
|
-
readonly gateway?: Partial<DiscordConfig["gateway"]>
|
|
39
|
+
readonly rest?: Partial<DiscordConfigService["rest"]>
|
|
40
|
+
readonly gateway?: Partial<DiscordConfigService["gateway"]>
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
export const make = ({
|
|
40
|
-
debug = false,
|
|
41
44
|
gateway,
|
|
42
45
|
rest,
|
|
43
46
|
token,
|
|
44
|
-
}: MakeOpts):
|
|
47
|
+
}: MakeOpts): DiscordConfigService => ({
|
|
45
48
|
token,
|
|
46
|
-
debug,
|
|
47
49
|
rest: {
|
|
48
50
|
baseUrl: `https://discord.com/api/v${VERSION}`,
|
|
49
51
|
...(rest ?? {}),
|
|
@@ -16,12 +16,17 @@ export interface OpenOpts {
|
|
|
16
16
|
onConnecting?: Effect.Effect<never, never, void>
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export interface
|
|
19
|
+
export interface DiscordWSCodecService {
|
|
20
20
|
type: "json" | "etf"
|
|
21
21
|
encode: (p: Discord.GatewayPayload) => string
|
|
22
22
|
decode: (p: WebSocket.Data) => Discord.GatewayPayload
|
|
23
23
|
}
|
|
24
|
-
export
|
|
24
|
+
export interface DiscordWSCodec {
|
|
25
|
+
readonly _: unique symbol
|
|
26
|
+
}
|
|
27
|
+
export const DiscordWSCodec = Tag<DiscordWSCodec, DiscordWSCodecService>(
|
|
28
|
+
"dfx/DiscordGateway/DiscordWS/Codec",
|
|
29
|
+
)
|
|
25
30
|
export const JsonDiscordWSCodecLive = Layer.succeed(DiscordWSCodec, {
|
|
26
31
|
type: "json",
|
|
27
32
|
encode: p => JSON.stringify(p),
|
|
@@ -47,18 +52,19 @@ const make = Effect.gen(function* (_) {
|
|
|
47
52
|
const takeOutbound = Effect.map(outbound, msg =>
|
|
48
53
|
msg === Reconnect ? msg : encoding.encode(msg),
|
|
49
54
|
)
|
|
50
|
-
const socket = yield* _(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
const socket = yield* _(
|
|
56
|
+
ws.connect({
|
|
57
|
+
urlRef,
|
|
58
|
+
takeOutbound,
|
|
59
|
+
onConnecting,
|
|
60
|
+
reconnectWhen: e =>
|
|
61
|
+
(e._tag === "WebSocketCloseError" && e.code < 2000) ||
|
|
62
|
+
(e._tag === "WebSocketError" && e.reason === "open-timeout"),
|
|
63
|
+
}),
|
|
58
64
|
)
|
|
65
|
+
const take = Effect.map(socket.take, encoding.decode)
|
|
59
66
|
|
|
60
67
|
return {
|
|
61
|
-
run,
|
|
62
68
|
take,
|
|
63
69
|
setUrl,
|
|
64
70
|
} as const
|
|
@@ -67,8 +73,12 @@ const make = Effect.gen(function* (_) {
|
|
|
67
73
|
return { connect } as const
|
|
68
74
|
})
|
|
69
75
|
|
|
70
|
-
export interface DiscordWS
|
|
71
|
-
|
|
76
|
+
export interface DiscordWS {
|
|
77
|
+
readonly _: unique symbol
|
|
78
|
+
}
|
|
79
|
+
export const DiscordWS = Tag<DiscordWS, Effect.Effect.Success<typeof make>>(
|
|
80
|
+
"dfx/DiscordGateway/DiscordWS",
|
|
81
|
+
)
|
|
72
82
|
export const DiscordWSLive = Layer.provide(
|
|
73
83
|
Layer.effect(DiscordWS, make),
|
|
74
84
|
WSLive,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Tag } from "effect/Context"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import * as PubSub from "effect/PubSub"
|
|
4
|
+
import * as Layer from "effect/Layer"
|
|
5
|
+
import * as Queue from "effect/Queue"
|
|
6
|
+
import * as Stream from "effect/Stream"
|
|
7
|
+
import type * as Discord from "dfx/types"
|
|
8
|
+
import * as EffectUtils from "dfx/utils/Effect"
|
|
9
|
+
|
|
10
|
+
const fromDispatchFactory =
|
|
11
|
+
<R, E>(
|
|
12
|
+
source: Stream.Stream<R, E, Discord.GatewayPayload<Discord.ReceiveEvent>>,
|
|
13
|
+
) =>
|
|
14
|
+
<K extends keyof Discord.ReceiveEvents>(
|
|
15
|
+
event: K,
|
|
16
|
+
): Stream.Stream<R, E, Discord.ReceiveEvents[K]> =>
|
|
17
|
+
Stream.map(
|
|
18
|
+
Stream.filter(source, p => p.t === event),
|
|
19
|
+
p => p.d! as any,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
const handleDispatchFactory =
|
|
23
|
+
(hub: PubSub.PubSub<Discord.GatewayPayload<Discord.ReceiveEvent>>) =>
|
|
24
|
+
<K extends keyof Discord.ReceiveEvents, R, E, A>(
|
|
25
|
+
event: K,
|
|
26
|
+
handle: (event: Discord.ReceiveEvents[K]) => Effect.Effect<R, E, A>,
|
|
27
|
+
): Effect.Effect<R, E, never> =>
|
|
28
|
+
EffectUtils.subscribeForEachPar(hub, _ => {
|
|
29
|
+
if (_.t === event) {
|
|
30
|
+
return handle(_.d as any)
|
|
31
|
+
}
|
|
32
|
+
return Effect.unit as any
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
export const make = Effect.gen(function* (_) {
|
|
36
|
+
const hub = yield* _(
|
|
37
|
+
Effect.acquireRelease(
|
|
38
|
+
PubSub.unbounded<Discord.GatewayPayload<Discord.ReceiveEvent>>(),
|
|
39
|
+
PubSub.shutdown,
|
|
40
|
+
),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
const sendQueue = yield* _(
|
|
44
|
+
Effect.acquireRelease(
|
|
45
|
+
Queue.unbounded<Discord.GatewayPayload<Discord.SendEvent>>(),
|
|
46
|
+
Queue.shutdown,
|
|
47
|
+
),
|
|
48
|
+
)
|
|
49
|
+
const send = (payload: Discord.GatewayPayload<Discord.SendEvent>) =>
|
|
50
|
+
sendQueue.offer(payload)
|
|
51
|
+
|
|
52
|
+
const dispatch = Stream.fromPubSub(hub)
|
|
53
|
+
const fromDispatch = fromDispatchFactory(dispatch)
|
|
54
|
+
const handleDispatch = handleDispatchFactory(hub)
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
hub,
|
|
58
|
+
sendQueue,
|
|
59
|
+
dispatch,
|
|
60
|
+
fromDispatch,
|
|
61
|
+
handleDispatch,
|
|
62
|
+
send,
|
|
63
|
+
} as const
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
export interface Messsaging {
|
|
67
|
+
readonly _: unique symbol
|
|
68
|
+
}
|
|
69
|
+
export const Messaging = Tag<Messsaging, Effect.Effect.Success<typeof make>>(
|
|
70
|
+
"dfx/DiscordGateway/Messaging",
|
|
71
|
+
)
|
|
72
|
+
export const MesssagingLive = Layer.scoped(Messaging, make)
|
|
@@ -17,9 +17,9 @@ import * as Identify from "dfx/DiscordGateway/Shard/identify"
|
|
|
17
17
|
import * as InvalidSession from "dfx/DiscordGateway/Shard/invalidSession"
|
|
18
18
|
import * as Utils from "dfx/DiscordGateway/Shard/utils"
|
|
19
19
|
import { Reconnect } from "dfx/DiscordGateway/WS"
|
|
20
|
-
import { Log } from "dfx/Log"
|
|
21
20
|
import { RateLimiterLive, RateLimiter } from "dfx/RateLimit"
|
|
22
21
|
import * as Discord from "dfx/types"
|
|
22
|
+
import { Messaging, MesssagingLive } from "dfx/DiscordGateway/Messaging"
|
|
23
23
|
|
|
24
24
|
const enum Phase {
|
|
25
25
|
Connecting,
|
|
@@ -31,19 +31,18 @@ export const make = Effect.gen(function* (_) {
|
|
|
31
31
|
const { gateway, token } = yield* _(DiscordConfig)
|
|
32
32
|
const limiter = yield* _(RateLimiter)
|
|
33
33
|
const dws = yield* _(DiscordWS)
|
|
34
|
-
const
|
|
34
|
+
const { hub, sendQueue } = yield* _(Messaging)
|
|
35
35
|
|
|
36
|
-
const connect = (
|
|
37
|
-
shard: [id: number, count: number],
|
|
38
|
-
hub: PubSub.PubSub<Discord.GatewayPayload<Discord.ReceiveEvent>>,
|
|
39
|
-
sendQueue: Queue.Dequeue<Discord.GatewayPayload<Discord.SendEvent>>,
|
|
40
|
-
) =>
|
|
36
|
+
const connect = (shard: [id: number, count: number]) =>
|
|
41
37
|
Effect.gen(function* (_) {
|
|
42
38
|
const outboundQueue = yield* _(Queue.unbounded<Message>())
|
|
43
39
|
const pendingQueue = yield* _(Queue.unbounded<Message>())
|
|
44
40
|
const phase = yield* _(Ref.make(Phase.Connecting))
|
|
45
41
|
const setPhase = (p: Phase) =>
|
|
46
|
-
Effect.zipLeft(
|
|
42
|
+
Effect.zipLeft(
|
|
43
|
+
Ref.set(phase, p),
|
|
44
|
+
Effect.annotateLogs(Effect.logTrace("phase transition"), "phase", p),
|
|
45
|
+
)
|
|
47
46
|
const outbound = Effect.zipLeft(
|
|
48
47
|
Queue.take(outboundQueue),
|
|
49
48
|
limiter.maybeWait("dfx.shard.send", Duration.minutes(1), 120),
|
|
@@ -115,15 +114,23 @@ export const make = Effect.gen(function* (_) {
|
|
|
115
114
|
},
|
|
116
115
|
)
|
|
117
116
|
|
|
118
|
-
const hellos = yield* _(
|
|
119
|
-
|
|
117
|
+
const hellos = yield* _(
|
|
118
|
+
Effect.acquireRelease(
|
|
119
|
+
Queue.unbounded<Discord.GatewayPayload>(),
|
|
120
|
+
Queue.shutdown,
|
|
121
|
+
),
|
|
122
|
+
)
|
|
123
|
+
const acks = yield* _(
|
|
124
|
+
Effect.acquireRelease(
|
|
125
|
+
Queue.unbounded<Discord.GatewayPayload>(),
|
|
126
|
+
Queue.shutdown,
|
|
127
|
+
),
|
|
128
|
+
)
|
|
120
129
|
|
|
121
130
|
// heartbeats
|
|
122
|
-
|
|
123
|
-
hellos,
|
|
124
|
-
|
|
125
|
-
latestSequence,
|
|
126
|
-
heartbeatSend,
|
|
131
|
+
yield* _(
|
|
132
|
+
Heartbeats.send(hellos, acks, latestSequence, heartbeatSend),
|
|
133
|
+
Effect.forkScoped,
|
|
127
134
|
)
|
|
128
135
|
|
|
129
136
|
// identify
|
|
@@ -169,32 +176,43 @@ export const make = Effect.gen(function* (_) {
|
|
|
169
176
|
}),
|
|
170
177
|
)
|
|
171
178
|
|
|
172
|
-
|
|
173
|
-
|
|
179
|
+
yield* _(
|
|
180
|
+
Queue.take(sendQueue),
|
|
181
|
+
Effect.tap(send),
|
|
182
|
+
Effect.forever,
|
|
183
|
+
Effect.forkScoped,
|
|
174
184
|
)
|
|
175
185
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
socket.run,
|
|
182
|
-
],
|
|
183
|
-
{ discard: true, concurrency: "unbounded" },
|
|
186
|
+
yield* _(
|
|
187
|
+
socket.take,
|
|
188
|
+
Effect.flatMap(onPayload),
|
|
189
|
+
Effect.forever,
|
|
190
|
+
Effect.forkScoped,
|
|
184
191
|
)
|
|
185
192
|
|
|
186
|
-
return { id: shard, send
|
|
187
|
-
})
|
|
193
|
+
return { id: shard, send } as const
|
|
194
|
+
}).pipe(
|
|
195
|
+
Effect.annotateLogs({
|
|
196
|
+
package: "dfx",
|
|
197
|
+
module: "DiscordGateway/Shard",
|
|
198
|
+
shard,
|
|
199
|
+
}),
|
|
200
|
+
)
|
|
188
201
|
|
|
189
202
|
return { connect } as const
|
|
190
203
|
})
|
|
191
204
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
export
|
|
195
|
-
|
|
196
|
-
|
|
205
|
+
type ShardService = Effect.Effect.Success<typeof make>
|
|
206
|
+
|
|
207
|
+
export interface Shard {
|
|
208
|
+
readonly _: unique symbol
|
|
209
|
+
}
|
|
210
|
+
export const Shard = Tag<Shard, ShardService>("dfx/DiscordGateway/Shard")
|
|
211
|
+
export const ShardLive = Layer.effect(Shard, make).pipe(
|
|
212
|
+
Layer.provide(DiscordWSLive),
|
|
213
|
+
Layer.provide(MesssagingLive),
|
|
214
|
+
Layer.provide(RateLimiterLive),
|
|
197
215
|
)
|
|
198
216
|
|
|
199
217
|
export interface RunningShard
|
|
200
|
-
extends Effect.Effect.Success<ReturnType<
|
|
218
|
+
extends Effect.Effect.Success<ReturnType<ShardService["connect"]>> {}
|
|
@@ -8,17 +8,22 @@ export interface ClaimIdContext {
|
|
|
8
8
|
totalCount: number
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export interface
|
|
11
|
+
export interface ShardStoreService {
|
|
12
12
|
claimId: (
|
|
13
13
|
ctx: ClaimIdContext,
|
|
14
14
|
) => Effect.Effect<never, never, Option.Option<number>>
|
|
15
15
|
allClaimed: (totalCount: number) => Effect.Effect<never, never, boolean>
|
|
16
16
|
heartbeat?: (shardId: number) => Effect.Effect<never, never, void>
|
|
17
17
|
}
|
|
18
|
-
export
|
|
18
|
+
export interface ShardStore {
|
|
19
|
+
readonly _: unique symbol
|
|
20
|
+
}
|
|
21
|
+
export const ShardStore = Tag<ShardStore, ShardStoreService>(
|
|
22
|
+
"dfx/DiscordGateway/ShardStore",
|
|
23
|
+
)
|
|
19
24
|
|
|
20
25
|
// Very basic shard id store, that does no health checks
|
|
21
|
-
const memoryStore = ():
|
|
26
|
+
const memoryStore = (): ShardStoreService => {
|
|
22
27
|
let currentId = 0
|
|
23
28
|
|
|
24
29
|
return {
|
|
@@ -1,24 +1,19 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DiscordConfig } from "dfx/DiscordConfig"
|
|
2
|
+
import type { RunningShard } from "dfx/DiscordGateway/Shard"
|
|
3
|
+
import { Shard, ShardLive } from "dfx/DiscordGateway/Shard"
|
|
4
|
+
import { ShardStore } from "dfx/DiscordGateway/ShardStore"
|
|
5
|
+
import { DiscordREST, DiscordRESTLive } from "dfx/DiscordREST"
|
|
6
|
+
import { RateLimiter, RateLimiterLive } from "dfx/RateLimit"
|
|
7
|
+
import type * as Discord from "dfx/types"
|
|
2
8
|
import { Tag } from "effect/Context"
|
|
3
9
|
import * as Duration from "effect/Duration"
|
|
10
|
+
import * as Effect from "effect/Effect"
|
|
4
11
|
import { pipe } from "effect/Function"
|
|
5
12
|
import * as HashSet from "effect/HashSet"
|
|
6
|
-
import type * as Option from "effect/Option"
|
|
7
|
-
import * as Deferred from "effect/Deferred"
|
|
8
|
-
import * as Effect from "effect/Effect"
|
|
9
|
-
import type * as PubSub from "effect/PubSub"
|
|
10
13
|
import * as Layer from "effect/Layer"
|
|
11
|
-
import type * as
|
|
14
|
+
import type * as Option from "effect/Option"
|
|
12
15
|
import * as Ref from "effect/Ref"
|
|
13
16
|
import * as Schedule from "effect/Schedule"
|
|
14
|
-
import { DiscordConfig } from "dfx/DiscordConfig"
|
|
15
|
-
import type { RunningShard } from "dfx/DiscordGateway/Shard"
|
|
16
|
-
import { ShardLive, Shard } from "dfx/DiscordGateway/Shard"
|
|
17
|
-
import { ShardStore } from "dfx/DiscordGateway/ShardStore"
|
|
18
|
-
import type { WebSocketCloseError, WebSocketError } from "dfx/DiscordGateway/WS"
|
|
19
|
-
import { DiscordREST } from "dfx/DiscordREST"
|
|
20
|
-
import { RateLimiterLive, RateLimiter } from "dfx/RateLimit"
|
|
21
|
-
import type * as Discord from "dfx/types"
|
|
22
17
|
|
|
23
18
|
const claimRepeatPolicy = Schedule.spaced("3 minutes").pipe(
|
|
24
19
|
Schedule.whileInput((_: Option.Option<number>) => _._tag === "None"),
|
|
@@ -33,29 +28,6 @@ const make = Effect.gen(function* (_) {
|
|
|
33
28
|
const shard = yield* _(Shard)
|
|
34
29
|
const currentShards = yield* _(Ref.make(HashSet.empty<RunningShard>()))
|
|
35
30
|
|
|
36
|
-
const takeConfig = (totalCount: number) =>
|
|
37
|
-
Effect.gen(function* (_) {
|
|
38
|
-
const currentCount = yield* _(Ref.make(0))
|
|
39
|
-
|
|
40
|
-
const claimId = (
|
|
41
|
-
sharderCount: number,
|
|
42
|
-
): Effect.Effect<never, never, number> =>
|
|
43
|
-
pipe(
|
|
44
|
-
store.claimId({
|
|
45
|
-
totalCount,
|
|
46
|
-
sharderCount,
|
|
47
|
-
}),
|
|
48
|
-
Effect.repeat(claimRepeatPolicy),
|
|
49
|
-
Effect.map(_ => _.value),
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
return pipe(
|
|
53
|
-
Ref.getAndUpdate(currentCount, _ => _ + 1),
|
|
54
|
-
Effect.flatMap(claimId),
|
|
55
|
-
Effect.map(id => ({ id, totalCount }) as const),
|
|
56
|
-
)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
31
|
const gateway = yield* _(
|
|
60
32
|
rest.getGatewayBot(),
|
|
61
33
|
Effect.flatMap(r => r.json),
|
|
@@ -73,68 +45,71 @@ const make = Effect.gen(function* (_) {
|
|
|
73
45
|
),
|
|
74
46
|
)
|
|
75
47
|
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
})),
|
|
93
|
-
Effect.tap(({ concurrency, id }) =>
|
|
94
|
-
limiter.maybeWait(
|
|
95
|
-
`dfx.sharder.${id % concurrency}`,
|
|
96
|
-
Duration.millis(config.identifyRateLimit[0]),
|
|
97
|
-
config.identifyRateLimit[1],
|
|
98
|
-
),
|
|
99
|
-
),
|
|
100
|
-
Effect.flatMap(c =>
|
|
101
|
-
shard.connect([c.id, c.totalCount], hub, sendQueue),
|
|
102
|
-
),
|
|
103
|
-
Effect.flatMap(shard =>
|
|
104
|
-
Effect.acquireUseRelease(
|
|
105
|
-
Ref.update(currentShards, HashSet.add(shard)),
|
|
106
|
-
() => shard.run,
|
|
107
|
-
() => Ref.update(currentShards, HashSet.remove(shard)),
|
|
108
|
-
).pipe(
|
|
109
|
-
Effect.catchAllCause(_ => Deferred.failCause(deferred, _)),
|
|
110
|
-
Effect.fork,
|
|
111
|
-
),
|
|
112
|
-
),
|
|
113
|
-
Effect.forever,
|
|
114
|
-
)
|
|
48
|
+
const totalCount = config.shardCount ?? gateway.shards
|
|
49
|
+
const currentCount = yield* _(Ref.make(0))
|
|
50
|
+
const claimId = (sharderCount: number): Effect.Effect<never, never, number> =>
|
|
51
|
+
pipe(
|
|
52
|
+
store.claimId({
|
|
53
|
+
totalCount,
|
|
54
|
+
sharderCount,
|
|
55
|
+
}),
|
|
56
|
+
Effect.repeat(claimRepeatPolicy),
|
|
57
|
+
Effect.map(_ => _.value),
|
|
58
|
+
)
|
|
59
|
+
const takeConfig = pipe(
|
|
60
|
+
Ref.getAndUpdate(currentCount, _ => _ + 1),
|
|
61
|
+
Effect.flatMap(claimId),
|
|
62
|
+
Effect.map(id => ({ id, totalCount }) as const),
|
|
63
|
+
)
|
|
115
64
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
65
|
+
const spawner = pipe(
|
|
66
|
+
takeConfig,
|
|
67
|
+
Effect.map(config => ({
|
|
68
|
+
...config,
|
|
69
|
+
url: gateway.url,
|
|
70
|
+
concurrency: gateway.session_start_limit.max_concurrency,
|
|
71
|
+
})),
|
|
72
|
+
Effect.tap(({ concurrency, id }) =>
|
|
73
|
+
limiter.maybeWait(
|
|
74
|
+
`dfx.sharder.${id % concurrency}`,
|
|
75
|
+
Duration.millis(config.identifyRateLimit[0]),
|
|
76
|
+
config.identifyRateLimit[1],
|
|
77
|
+
),
|
|
78
|
+
),
|
|
79
|
+
Effect.flatMap(c => shard.connect([c.id, c.totalCount])),
|
|
80
|
+
Effect.flatMap(shard => Ref.update(currentShards, HashSet.add(shard))),
|
|
81
|
+
Effect.forever,
|
|
82
|
+
)
|
|
120
83
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
84
|
+
yield* _(
|
|
85
|
+
Effect.replicateEffect(
|
|
86
|
+
spawner,
|
|
87
|
+
gateway.session_start_limit.max_concurrency,
|
|
88
|
+
{ concurrency: "unbounded", discard: true },
|
|
89
|
+
),
|
|
90
|
+
Effect.scoped,
|
|
91
|
+
Effect.catchAllCause(Effect.logError),
|
|
92
|
+
Effect.ensuring(Ref.set(currentShards, HashSet.empty())),
|
|
93
|
+
Effect.forever,
|
|
94
|
+
Effect.forkScoped,
|
|
95
|
+
)
|
|
131
96
|
|
|
132
|
-
return { shards: Ref.get(currentShards)
|
|
133
|
-
})
|
|
97
|
+
return { shards: Ref.get(currentShards) } as const
|
|
98
|
+
}).pipe(
|
|
99
|
+
Effect.annotateLogs({
|
|
100
|
+
package: "dfx",
|
|
101
|
+
module: "DiscordGateway/Sharder",
|
|
102
|
+
}),
|
|
103
|
+
)
|
|
134
104
|
|
|
135
|
-
export interface Sharder
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
105
|
+
export interface Sharder {
|
|
106
|
+
readonly _: unique symbol
|
|
107
|
+
}
|
|
108
|
+
export const Sharder = Tag<Sharder, Effect.Effect.Success<typeof make>>(
|
|
109
|
+
"dfx/DiscordGateway/Sharder",
|
|
110
|
+
)
|
|
111
|
+
export const SharderLive = Layer.scoped(Sharder, make).pipe(
|
|
112
|
+
Layer.provide(DiscordRESTLive),
|
|
113
|
+
Layer.provide(RateLimiterLive),
|
|
114
|
+
Layer.provide(ShardLive),
|
|
140
115
|
)
|