dfx 1.0.5 → 1.0.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/dist/Cache/driver.d.ts.map +1 -1
- package/dist/Cache/memory.d.ts.map +1 -1
- package/dist/Cache/memoryTTL.d.ts.map +1 -1
- package/dist/Cache/prelude.d.ts.map +1 -1
- package/dist/Cache.d.ts.map +1 -1
- package/dist/DiscordConfig.d.ts.map +1 -1
- package/dist/DiscordGateway/DiscordWS.d.ts.map +1 -1
- package/dist/DiscordGateway/Messaging.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard/StateStore.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard/heartbeats.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard/identify.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard/sendEvents.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard/utils.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard.d.ts.map +1 -1
- package/dist/DiscordGateway/ShardStore.d.ts.map +1 -1
- package/dist/DiscordGateway/Sharder.d.ts +1 -1
- package/dist/DiscordGateway/Sharder.d.ts.map +1 -1
- package/dist/DiscordGateway.d.ts.map +1 -1
- package/dist/DiscordREST/Generated.d.ts.map +1 -1
- package/dist/DiscordREST/utils.d.ts.map +1 -1
- package/dist/DiscordREST.d.ts.map +1 -1
- package/dist/Helpers/flags.d.ts.map +1 -1
- package/dist/Helpers/intents.d.ts.map +1 -1
- package/dist/Helpers/interactions.d.ts.map +1 -1
- package/dist/Helpers/members.d.ts.map +1 -1
- package/dist/Helpers/permissions.d.ts.map +1 -1
- package/dist/Helpers/ui.d.ts.map +1 -1
- package/dist/Interactions/builder.d.ts.map +1 -1
- package/dist/Interactions/commandHelper.d.ts.map +1 -1
- package/dist/Interactions/context.d.ts.map +1 -1
- package/dist/Interactions/definitions.d.ts.map +1 -1
- package/dist/Interactions/error.d.ts.map +1 -1
- package/dist/Interactions/gateway.d.ts.map +1 -1
- package/dist/Interactions/handlers.d.ts.map +1 -1
- package/dist/Interactions/index.d.ts.map +1 -1
- package/dist/Interactions/utils.d.ts.map +1 -1
- package/dist/Interactions/webhook.d.ts.map +1 -1
- package/dist/RateLimit/memory.d.ts.map +1 -1
- package/dist/RateLimit/utils.d.ts.map +1 -1
- package/dist/RateLimit.d.ts.map +1 -1
- package/dist/gateway.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/Effect.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/webhooks.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/version.ts +1 -1
- package/dist/LICENSE +0 -21
- package/dist/README.md +0 -66
- package/dist/mjs/Cache/driver.mjs +0 -3
- package/dist/mjs/Cache/driver.mjs.map +0 -1
- package/dist/mjs/Cache/memory.mjs +0 -48
- package/dist/mjs/Cache/memory.mjs.map +0 -1
- package/dist/mjs/Cache/memoryTTL.mjs +0 -119
- package/dist/mjs/Cache/memoryTTL.mjs.map +0 -1
- package/dist/mjs/Cache/prelude.mjs +0 -131
- package/dist/mjs/Cache/prelude.mjs.map +0 -1
- package/dist/mjs/Cache.mjs +0 -90
- package/dist/mjs/Cache.mjs.map +0 -1
- package/dist/mjs/DiscordConfig.mjs +0 -32
- package/dist/mjs/DiscordConfig.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/DiscordWS.mjs +0 -77
- package/dist/mjs/DiscordGateway/DiscordWS.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Messaging.mjs +0 -35
- package/dist/mjs/DiscordGateway/Messaging.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard/StateStore.mjs +0 -41
- package/dist/mjs/DiscordGateway/Shard/StateStore.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard/heartbeats.mjs +0 -25
- package/dist/mjs/DiscordGateway/Shard/heartbeats.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard/identify.mjs +0 -29
- package/dist/mjs/DiscordGateway/Shard/identify.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard/sendEvents.mjs +0 -26
- package/dist/mjs/DiscordGateway/Shard/sendEvents.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard/utils.mjs +0 -3
- package/dist/mjs/DiscordGateway/Shard/utils.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard.mjs +0 -147
- package/dist/mjs/DiscordGateway/Shard.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/ShardStore.mjs +0 -24
- package/dist/mjs/DiscordGateway/ShardStore.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Sharder.mjs +0 -67
- package/dist/mjs/DiscordGateway/Sharder.mjs.map +0 -1
- package/dist/mjs/DiscordGateway.mjs +0 -21
- package/dist/mjs/DiscordGateway.mjs.map +0 -1
- package/dist/mjs/DiscordREST/Generated.mjs +0 -2471
- package/dist/mjs/DiscordREST/Generated.mjs.map +0 -1
- package/dist/mjs/DiscordREST/utils.mjs +0 -21
- package/dist/mjs/DiscordREST/utils.mjs.map +0 -1
- package/dist/mjs/DiscordREST.mjs +0 -119
- package/dist/mjs/DiscordREST.mjs.map +0 -1
- package/dist/mjs/Helpers/flags.mjs +0 -45
- package/dist/mjs/Helpers/flags.mjs.map +0 -1
- package/dist/mjs/Helpers/intents.mjs +0 -27
- package/dist/mjs/Helpers/intents.mjs.map +0 -1
- package/dist/mjs/Helpers/interactions.mjs +0 -115
- package/dist/mjs/Helpers/interactions.mjs.map +0 -1
- package/dist/mjs/Helpers/members.mjs +0 -9
- package/dist/mjs/Helpers/members.mjs.map +0 -1
- package/dist/mjs/Helpers/permissions.mjs +0 -84
- package/dist/mjs/Helpers/permissions.mjs.map +0 -1
- package/dist/mjs/Helpers/ui.mjs +0 -137
- package/dist/mjs/Helpers/ui.mjs.map +0 -1
- package/dist/mjs/Interactions/builder.mjs +0 -56
- package/dist/mjs/Interactions/builder.mjs.map +0 -1
- package/dist/mjs/Interactions/commandHelper.mjs +0 -49
- package/dist/mjs/Interactions/commandHelper.mjs.map +0 -1
- package/dist/mjs/Interactions/context.mjs +0 -28
- package/dist/mjs/Interactions/context.mjs.map +0 -1
- package/dist/mjs/Interactions/definitions.mjs +0 -51
- package/dist/mjs/Interactions/definitions.mjs.map +0 -1
- package/dist/mjs/Interactions/error.mjs +0 -2
- package/dist/mjs/Interactions/error.mjs.map +0 -1
- package/dist/mjs/Interactions/gateway.mjs +0 -82
- package/dist/mjs/Interactions/gateway.mjs.map +0 -1
- package/dist/mjs/Interactions/handlers.mjs +0 -64
- package/dist/mjs/Interactions/handlers.mjs.map +0 -1
- package/dist/mjs/Interactions/index.mjs +0 -11
- package/dist/mjs/Interactions/index.mjs.map +0 -1
- package/dist/mjs/Interactions/utils.mjs +0 -26
- package/dist/mjs/Interactions/utils.mjs.map +0 -1
- package/dist/mjs/Interactions/webhook.mjs +0 -75
- package/dist/mjs/Interactions/webhook.mjs.map +0 -1
- package/dist/mjs/RateLimit/memory.mjs +0 -39
- package/dist/mjs/RateLimit/memory.mjs.map +0 -1
- package/dist/mjs/RateLimit/utils.mjs +0 -18
- package/dist/mjs/RateLimit/utils.mjs.map +0 -1
- package/dist/mjs/RateLimit.mjs +0 -28
- package/dist/mjs/RateLimit.mjs.map +0 -1
- package/dist/mjs/gateway.mjs +0 -19
- package/dist/mjs/gateway.mjs.map +0 -1
- package/dist/mjs/index.mjs +0 -18
- package/dist/mjs/index.mjs.map +0 -1
- package/dist/mjs/types.mjs +0 -356
- package/dist/mjs/types.mjs.map +0 -1
- package/dist/mjs/utils/Effect.mjs +0 -44
- package/dist/mjs/utils/Effect.mjs.map +0 -1
- package/dist/mjs/version.mjs +0 -2
- package/dist/mjs/version.mjs.map +0 -1
- package/dist/mjs/webhooks.mjs +0 -6
- package/dist/mjs/webhooks.mjs.map +0 -1
- package/dist/package.json +0 -48
- package/dist/src/Cache/driver.ts +0 -37
- package/dist/src/Cache/memory.ts +0 -83
- package/dist/src/Cache/memoryTTL.ts +0 -225
- package/dist/src/Cache/prelude.ts +0 -279
- package/dist/src/Cache.ts +0 -261
- package/dist/src/DiscordConfig.ts +0 -67
- package/dist/src/DiscordGateway/DiscordWS.ts +0 -157
- package/dist/src/DiscordGateway/Messaging.ts +0 -71
- package/dist/src/DiscordGateway/Shard/StateStore.ts +0 -72
- package/dist/src/DiscordGateway/Shard/heartbeats.ts +0 -60
- package/dist/src/DiscordGateway/Shard/identify.ts +0 -50
- package/dist/src/DiscordGateway/Shard/sendEvents.ts +0 -43
- package/dist/src/DiscordGateway/Shard/utils.ts +0 -13
- package/dist/src/DiscordGateway/Shard.ts +0 -205
- package/dist/src/DiscordGateway/ShardStore.ts +0 -42
- package/dist/src/DiscordGateway/Sharder.ts +0 -118
- package/dist/src/DiscordGateway.ts +0 -79
- package/dist/src/DiscordREST/Generated.ts +0 -10832
- package/dist/src/DiscordREST/utils.ts +0 -42
- package/dist/src/DiscordREST.ts +0 -256
- package/dist/src/Helpers/flags.ts +0 -73
- package/dist/src/Helpers/intents.ts +0 -35
- package/dist/src/Helpers/interactions.ts +0 -317
- package/dist/src/Helpers/members.ts +0 -18
- package/dist/src/Helpers/permissions.ts +0 -145
- package/dist/src/Helpers/ui.ts +0 -253
- package/dist/src/Interactions/builder.ts +0 -171
- package/dist/src/Interactions/commandHelper.ts +0 -231
- package/dist/src/Interactions/context.ts +0 -104
- package/dist/src/Interactions/definitions.ts +0 -144
- package/dist/src/Interactions/error.ts +0 -3
- package/dist/src/Interactions/gateway.ts +0 -193
- package/dist/src/Interactions/handlers.ts +0 -108
- package/dist/src/Interactions/index.ts +0 -30
- package/dist/src/Interactions/utils.ts +0 -93
- package/dist/src/Interactions/webhook.ts +0 -204
- package/dist/src/RateLimit/memory.ts +0 -63
- package/dist/src/RateLimit/utils.ts +0 -28
- package/dist/src/RateLimit.ts +0 -90
- package/dist/src/gateway.ts +0 -50
- package/dist/src/index.ts +0 -44
- package/dist/src/types.ts +0 -3090
- package/dist/src/utils/Effect.ts +0 -65
- package/dist/src/version.ts +0 -1
- package/dist/src/webhooks.ts +0 -25
- package/dist/tsconfig.base.json +0 -54
- package/dist/tsconfig.build.json +0 -10
- package/dist/tsconfig.examples.json +0 -10
- package/dist/tsconfig.json +0 -14
- package/dist/tsconfig.madge.json +0 -12
- package/dist/tsconfig.test.json +0 -10
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import * as Option from "effect/Option"
|
|
2
|
-
import * as Effect from "effect/Effect"
|
|
3
|
-
import * as SendEvents from "./sendEvents.ts"
|
|
4
|
-
import type * as Discord from "../../types.ts"
|
|
5
|
-
import type { ShardState } from "./StateStore.ts"
|
|
6
|
-
|
|
7
|
-
declare const process: { platform?: string | undefined } | undefined
|
|
8
|
-
|
|
9
|
-
export interface Options {
|
|
10
|
-
readonly token: string
|
|
11
|
-
readonly intents: number
|
|
12
|
-
readonly shard: [number, number]
|
|
13
|
-
readonly presence?: Discord.GatewayPresenceUpdateData
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const identify = ({ intents, presence, shard, token }: Options) =>
|
|
17
|
-
SendEvents.identify({
|
|
18
|
-
token,
|
|
19
|
-
intents,
|
|
20
|
-
properties: {
|
|
21
|
-
os:
|
|
22
|
-
typeof process !== "undefined"
|
|
23
|
-
? (process.platform ?? "unknown")
|
|
24
|
-
: "unknown",
|
|
25
|
-
browser: "dfx",
|
|
26
|
-
device: "dfx",
|
|
27
|
-
},
|
|
28
|
-
shard,
|
|
29
|
-
presence,
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
const resume = (token: string, session_id: string, seq: number | null) =>
|
|
33
|
-
SendEvents.resume({
|
|
34
|
-
token,
|
|
35
|
-
session_id,
|
|
36
|
-
seq: seq!,
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
export const identifyOrResume = (
|
|
40
|
-
opts: Options,
|
|
41
|
-
state: Effect.Effect<Option.Option<ShardState>>,
|
|
42
|
-
): Effect.Effect<Discord.GatewayIdentify | Discord.GatewayResume> =>
|
|
43
|
-
Effect.map(
|
|
44
|
-
state,
|
|
45
|
-
Option.match({
|
|
46
|
-
onNone: () => identify(opts),
|
|
47
|
-
onSome: shardState =>
|
|
48
|
-
resume(opts.token, shardState.sessionId, shardState.sequence),
|
|
49
|
-
}),
|
|
50
|
-
)
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import * as Discord from "../../types.ts"
|
|
2
|
-
|
|
3
|
-
export const heartbeat = (
|
|
4
|
-
d: Discord.GatewayHeartbeatData,
|
|
5
|
-
): Discord.GatewayHeartbeat => ({
|
|
6
|
-
op: Discord.GatewayOpcodes.Heartbeat,
|
|
7
|
-
d,
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
export const identify = (
|
|
11
|
-
d: Discord.GatewayIdentifyData,
|
|
12
|
-
): Discord.GatewayIdentify => ({
|
|
13
|
-
op: Discord.GatewayOpcodes.Identify,
|
|
14
|
-
d,
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
export const resume = (
|
|
18
|
-
d: Discord.GatewayResumeData,
|
|
19
|
-
): Discord.GatewayResume => ({
|
|
20
|
-
op: Discord.GatewayOpcodes.Resume,
|
|
21
|
-
d,
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
export const requestGuildMembers = (
|
|
25
|
-
d: Discord.GatewayRequestGuildMembersData,
|
|
26
|
-
): Discord.GatewayRequestGuildMembers => ({
|
|
27
|
-
op: Discord.GatewayOpcodes.RequestGuildMembers,
|
|
28
|
-
d,
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
export const voiceStateUpdate = (
|
|
32
|
-
d: Discord.GatewayVoiceStateUpdateData,
|
|
33
|
-
): Discord.GatewayVoiceStateUpdate => ({
|
|
34
|
-
op: Discord.GatewayOpcodes.VoiceStateUpdate,
|
|
35
|
-
d,
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
export const presenceUpdate = (
|
|
39
|
-
d: Discord.GatewayPresenceUpdateData,
|
|
40
|
-
): Discord.GatewayUpdatePresence => ({
|
|
41
|
-
op: Discord.GatewayOpcodes.PresenceUpdate,
|
|
42
|
-
d,
|
|
43
|
-
})
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type * as Discord from "../../types.ts"
|
|
2
|
-
import * as Stream from "effect/Stream"
|
|
3
|
-
|
|
4
|
-
export const opCode =
|
|
5
|
-
<R, E>(source: Stream.Stream<Discord.GatewayReceivePayload, E, R>) =>
|
|
6
|
-
<const Code extends Discord.GatewayOpcodes>(
|
|
7
|
-
code: Code,
|
|
8
|
-
): Stream.Stream<
|
|
9
|
-
Extract<Discord.GatewayReceivePayload, { readonly op: Code }>,
|
|
10
|
-
E,
|
|
11
|
-
R
|
|
12
|
-
> =>
|
|
13
|
-
Stream.filter(source, p => p.op === code) as any
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import { DiscordConfig } from "../DiscordConfig.ts"
|
|
2
|
-
import type { MessageSend } from "./DiscordWS.ts"
|
|
3
|
-
import { DiscordWS, DiscordWSLive, Reconnect } from "./DiscordWS.ts"
|
|
4
|
-
import { Messaging, MesssagingLive } from "./Messaging.ts"
|
|
5
|
-
import type { ShardState } from "./Shard/StateStore.ts"
|
|
6
|
-
import { ShardStateStore } from "./Shard/StateStore.ts"
|
|
7
|
-
import * as Heartbeats from "./Shard/heartbeats.ts"
|
|
8
|
-
import * as Identify from "./Shard/identify.ts"
|
|
9
|
-
import { RateLimiter, RateLimiterLive } from "../RateLimit.ts"
|
|
10
|
-
import * as Discord from "../types.ts"
|
|
11
|
-
import * as Duration from "effect/Duration"
|
|
12
|
-
import * as Effect from "effect/Effect"
|
|
13
|
-
import * as Layer from "effect/Layer"
|
|
14
|
-
import * as Option from "effect/Option"
|
|
15
|
-
import * as Redacted from "effect/Redacted"
|
|
16
|
-
import type * as Types from "effect/Types"
|
|
17
|
-
import * as FiberHandle from "effect/FiberHandle"
|
|
18
|
-
import { constant, constTrue, constVoid } from "effect/Function"
|
|
19
|
-
import * as Queue from "effect/Queue"
|
|
20
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
21
|
-
import * as PubSub from "effect/PubSub"
|
|
22
|
-
import * as LogLevel from "effect/LogLevel"
|
|
23
|
-
import { MinimumLogLevel } from "effect/References"
|
|
24
|
-
|
|
25
|
-
const enum Phase {
|
|
26
|
-
Connecting,
|
|
27
|
-
Handshake,
|
|
28
|
-
Connected,
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const make = Effect.gen(function* () {
|
|
32
|
-
const { gateway, token } = yield* DiscordConfig
|
|
33
|
-
const limiter = yield* RateLimiter
|
|
34
|
-
const dws = yield* DiscordWS
|
|
35
|
-
const { hub, sendMailbox } = yield* Messaging
|
|
36
|
-
const shardState = yield* ShardStateStore
|
|
37
|
-
|
|
38
|
-
const connect = Effect.fnUntraced(
|
|
39
|
-
function* (shard: [id: number, count: number]) {
|
|
40
|
-
const traceEnabled = LogLevel.isLessThanOrEqualTo(
|
|
41
|
-
yield* MinimumLogLevel,
|
|
42
|
-
"Trace",
|
|
43
|
-
)
|
|
44
|
-
const reconnectHandle = yield* FiberHandle.make()
|
|
45
|
-
let phase = Phase.Connecting
|
|
46
|
-
const stateStore = shardState.forShard(shard)
|
|
47
|
-
const resumeState: Types.Mutable<ShardState> = Option.getOrElse(
|
|
48
|
-
yield* stateStore.get,
|
|
49
|
-
() => ({
|
|
50
|
-
resumeUrl: "",
|
|
51
|
-
sessionId: "",
|
|
52
|
-
sequence: 0,
|
|
53
|
-
}),
|
|
54
|
-
)
|
|
55
|
-
const setPhase = (p: Phase): Effect.Effect<void> =>
|
|
56
|
-
Effect.suspend(() => {
|
|
57
|
-
phase = p
|
|
58
|
-
if (!traceEnabled) return Effect.void
|
|
59
|
-
return Effect.annotateLogs(
|
|
60
|
-
Effect.logTrace("phase transition"),
|
|
61
|
-
"phase",
|
|
62
|
-
p,
|
|
63
|
-
)
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
const heartbeatSend = (p: MessageSend) =>
|
|
67
|
-
Effect.suspend(() => {
|
|
68
|
-
if (phase === Phase.Connecting) return Effect.void
|
|
69
|
-
return write(p)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
const resume = Effect.andThen(
|
|
73
|
-
FiberHandle.clear(reconnectHandle),
|
|
74
|
-
setPhase(Phase.Connected),
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
const onConnecting = setPhase(Phase.Connecting)
|
|
78
|
-
|
|
79
|
-
const socket = yield* dws.connect({ onConnecting })
|
|
80
|
-
const write = (p: MessageSend) =>
|
|
81
|
-
Effect.andThen(
|
|
82
|
-
limiter.maybeWait("dfx.shard.send", Duration.minutes(1), 120),
|
|
83
|
-
socket.write(p),
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
const hellos = yield* Effect.acquireRelease(
|
|
87
|
-
Queue.make<Discord.GatewayHelloData>(),
|
|
88
|
-
Queue.shutdown,
|
|
89
|
-
)
|
|
90
|
-
const acks = yield* Effect.acquireRelease(
|
|
91
|
-
Queue.make<void>(),
|
|
92
|
-
Queue.shutdown,
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
// heartbeats
|
|
96
|
-
yield* Heartbeats.send(hellos, acks, stateStore.get, heartbeatSend).pipe(
|
|
97
|
-
Effect.forkScoped,
|
|
98
|
-
Effect.interruptible,
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
// identify
|
|
102
|
-
const identify = Identify.identifyOrResume(
|
|
103
|
-
{
|
|
104
|
-
token: Redacted.value(token),
|
|
105
|
-
shard,
|
|
106
|
-
intents: gateway.intents,
|
|
107
|
-
presence: gateway.presence,
|
|
108
|
-
},
|
|
109
|
-
stateStore.get,
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
// delayed reconnect
|
|
113
|
-
const delayedReconnect = Effect.delay(socket.write(Reconnect), 30_000)
|
|
114
|
-
|
|
115
|
-
function* onPayload(p: Discord.GatewayReceivePayload) {
|
|
116
|
-
if (typeof p.s === "number") {
|
|
117
|
-
resumeState.sequence = p.s
|
|
118
|
-
}
|
|
119
|
-
if (p.op === Discord.GatewayOpcodes.Dispatch && p.t === "READY") {
|
|
120
|
-
const payload = p.d
|
|
121
|
-
resumeState.sessionId = payload.session_id
|
|
122
|
-
resumeState.resumeUrl = payload.resume_gateway_url
|
|
123
|
-
yield* stateStore.set(resumeState)
|
|
124
|
-
yield* socket.setUrl(payload.resume_gateway_url)
|
|
125
|
-
} else if (
|
|
126
|
-
resumeState.resumeUrl !== "" &&
|
|
127
|
-
resumeState.sessionId !== ""
|
|
128
|
-
) {
|
|
129
|
-
yield* stateStore.set(resumeState)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
switch (p.op) {
|
|
133
|
-
case Discord.GatewayOpcodes.Hello: {
|
|
134
|
-
yield* write(yield* identify)
|
|
135
|
-
yield* setPhase(Phase.Handshake)
|
|
136
|
-
Queue.offerUnsafe(hellos, p.d)
|
|
137
|
-
yield* FiberHandle.run(reconnectHandle, delayedReconnect)
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
case Discord.GatewayOpcodes.HeartbeatAck: {
|
|
141
|
-
Queue.offerUnsafe(acks, void 0)
|
|
142
|
-
return
|
|
143
|
-
}
|
|
144
|
-
case Discord.GatewayOpcodes.InvalidSession: {
|
|
145
|
-
if (!p.d) {
|
|
146
|
-
resumeState.sessionId = ""
|
|
147
|
-
yield* stateStore.clear
|
|
148
|
-
}
|
|
149
|
-
yield* socket.write(Reconnect)
|
|
150
|
-
return
|
|
151
|
-
}
|
|
152
|
-
case Discord.GatewayOpcodes.Dispatch: {
|
|
153
|
-
if (p.t === "READY" || p.t === "RESUMED") {
|
|
154
|
-
yield* resume
|
|
155
|
-
}
|
|
156
|
-
PubSub.publishUnsafe(hub, p)
|
|
157
|
-
return
|
|
158
|
-
}
|
|
159
|
-
case Discord.GatewayOpcodes.Reconnect: {
|
|
160
|
-
yield* socket.write(Reconnect)
|
|
161
|
-
return
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
yield* Effect.whileLoop({
|
|
167
|
-
while: constTrue,
|
|
168
|
-
body: constant(Effect.flatMap(Queue.take(sendMailbox), write)),
|
|
169
|
-
step: constVoid,
|
|
170
|
-
}).pipe(Effect.forkScoped)
|
|
171
|
-
|
|
172
|
-
yield* Effect.gen(function* () {
|
|
173
|
-
while (true) {
|
|
174
|
-
yield* onPayload(yield* socket.take)
|
|
175
|
-
}
|
|
176
|
-
}).pipe(Effect.forkScoped)
|
|
177
|
-
|
|
178
|
-
return { id: shard, write } as const
|
|
179
|
-
},
|
|
180
|
-
(effect, shard) =>
|
|
181
|
-
Effect.annotateLogs(effect, {
|
|
182
|
-
package: "dfx",
|
|
183
|
-
module: "DiscordGateway/Shard",
|
|
184
|
-
shard,
|
|
185
|
-
}),
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
return { connect } as const
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
type ShardService = Effect.Success<typeof make>
|
|
192
|
-
|
|
193
|
-
export class Shard extends ServiceMap.Service<Shard, ShardService>()(
|
|
194
|
-
"dfx/DiscordGateway/Shard",
|
|
195
|
-
) {}
|
|
196
|
-
export const ShardLive = Layer.effect(Shard, make).pipe(
|
|
197
|
-
Layer.provide(DiscordWSLive),
|
|
198
|
-
Layer.provide(MesssagingLive),
|
|
199
|
-
Layer.provide(RateLimiterLive),
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
203
|
-
export interface RunningShard extends Effect.Success<
|
|
204
|
-
ReturnType<ShardService["connect"]>
|
|
205
|
-
> {}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import * as Option from "effect/Option"
|
|
2
|
-
import * as Effect from "effect/Effect"
|
|
3
|
-
import * as Layer from "effect/Layer"
|
|
4
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
5
|
-
|
|
6
|
-
export interface ClaimIdContext {
|
|
7
|
-
sharderCount: number
|
|
8
|
-
totalCount: number
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface ShardStoreService {
|
|
12
|
-
claimId: (ctx: ClaimIdContext) => Effect.Effect<Option.Option<number>>
|
|
13
|
-
allClaimed: (totalCount: number) => Effect.Effect<boolean>
|
|
14
|
-
heartbeat?: (shardId: number) => Effect.Effect<void>
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export class ShardStore extends ServiceMap.Service<
|
|
18
|
-
ShardStore,
|
|
19
|
-
ShardStoreService
|
|
20
|
-
>()("dfx/DiscordGateway/ShardStore") {}
|
|
21
|
-
|
|
22
|
-
// Very basic shard id store, that does no health checks
|
|
23
|
-
const memoryStore = (): ShardStoreService => {
|
|
24
|
-
let currentId = 0
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
claimId: ({ totalCount }) =>
|
|
28
|
-
Effect.sync(() => {
|
|
29
|
-
if (currentId >= totalCount) {
|
|
30
|
-
return Option.none()
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const id = currentId
|
|
34
|
-
currentId++
|
|
35
|
-
return Option.some(id)
|
|
36
|
-
}),
|
|
37
|
-
|
|
38
|
-
allClaimed: totalCount => Effect.sync(() => currentId >= totalCount),
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const MemoryShardStoreLive = Layer.sync(ShardStore, memoryStore)
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { DiscordConfig } from "../DiscordConfig.ts"
|
|
2
|
-
import type { RunningShard } from "./Shard.ts"
|
|
3
|
-
import { Shard, ShardLive } from "./Shard.ts"
|
|
4
|
-
import { ShardStore } from "./ShardStore.ts"
|
|
5
|
-
import { DiscordREST, DiscordRESTLive } from "../DiscordREST.ts"
|
|
6
|
-
import { RateLimiter, RateLimiterLive } from "../RateLimit.ts"
|
|
7
|
-
import type * as Discord from "../types.ts"
|
|
8
|
-
import * as Duration from "effect/Duration"
|
|
9
|
-
import * as Effect from "effect/Effect"
|
|
10
|
-
import { pipe } from "effect/Function"
|
|
11
|
-
import * as Layer from "effect/Layer"
|
|
12
|
-
import type * as Option from "effect/Option"
|
|
13
|
-
import * as Ref from "effect/Ref"
|
|
14
|
-
import * as Schedule from "effect/Schedule"
|
|
15
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
16
|
-
|
|
17
|
-
const claimRepeatPolicy = Schedule.identity<Option.Option<number>>().pipe(
|
|
18
|
-
Schedule.either(Schedule.spaced("3 minutes")),
|
|
19
|
-
Schedule.while(_ => Effect.succeed(_.input._tag === "None")),
|
|
20
|
-
Schedule.passthrough,
|
|
21
|
-
) as Schedule.Schedule<Option.Some<number>, Option.Option<number>>
|
|
22
|
-
|
|
23
|
-
const make = Effect.gen(function* () {
|
|
24
|
-
const store = yield* ShardStore
|
|
25
|
-
const rest = yield* DiscordREST
|
|
26
|
-
const { gateway: gatewayConfig } = yield* DiscordConfig
|
|
27
|
-
const limiter = yield* RateLimiter
|
|
28
|
-
const shard = yield* Shard
|
|
29
|
-
const currentShards = new Set<RunningShard>()
|
|
30
|
-
|
|
31
|
-
const gateway = yield* rest.getBotGateway().pipe(
|
|
32
|
-
Effect.catch(() =>
|
|
33
|
-
Effect.succeed<Discord.APIGatewayBotInfo>({
|
|
34
|
-
url: "wss://gateway.discord.gg/",
|
|
35
|
-
shards: 1,
|
|
36
|
-
session_start_limit: {
|
|
37
|
-
total: 0,
|
|
38
|
-
remaining: 0,
|
|
39
|
-
reset_after: 0,
|
|
40
|
-
max_concurrency: 1,
|
|
41
|
-
},
|
|
42
|
-
}),
|
|
43
|
-
),
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
const totalCount = gatewayConfig.shardCount ?? gateway.shards
|
|
47
|
-
const currentCount = yield* Ref.make(0)
|
|
48
|
-
const claimId = (sharderCount: number): Effect.Effect<number> =>
|
|
49
|
-
pipe(
|
|
50
|
-
store.claimId({
|
|
51
|
-
totalCount,
|
|
52
|
-
sharderCount,
|
|
53
|
-
}),
|
|
54
|
-
Effect.repeat(claimRepeatPolicy),
|
|
55
|
-
Effect.map(_ => _.value),
|
|
56
|
-
)
|
|
57
|
-
const takeConfig = pipe(
|
|
58
|
-
Ref.getAndUpdate(currentCount, _ => _ + 1),
|
|
59
|
-
Effect.flatMap(claimId),
|
|
60
|
-
Effect.map(id => ({ id, totalCount }) as const),
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
const spawner = pipe(
|
|
64
|
-
takeConfig,
|
|
65
|
-
Effect.map(shardConfig => ({
|
|
66
|
-
...shardConfig,
|
|
67
|
-
url: gateway.url,
|
|
68
|
-
concurrency: gateway.session_start_limit.max_concurrency,
|
|
69
|
-
})),
|
|
70
|
-
Effect.tap(({ concurrency, id }) =>
|
|
71
|
-
limiter.maybeWait(
|
|
72
|
-
`dfx.sharder.${id % concurrency}`,
|
|
73
|
-
Duration.millis(gatewayConfig.identifyRateLimit[0]),
|
|
74
|
-
gatewayConfig.identifyRateLimit[1],
|
|
75
|
-
),
|
|
76
|
-
),
|
|
77
|
-
Effect.flatMap(c => shard.connect([c.id, c.totalCount])),
|
|
78
|
-
Effect.tap(runningShard => {
|
|
79
|
-
currentShards.add(runningShard)
|
|
80
|
-
return Effect.void
|
|
81
|
-
}),
|
|
82
|
-
Effect.forever,
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
yield* Effect.replicateEffect(
|
|
86
|
-
spawner,
|
|
87
|
-
gateway.session_start_limit.max_concurrency,
|
|
88
|
-
{ concurrency: "unbounded", discard: true },
|
|
89
|
-
).pipe(
|
|
90
|
-
Effect.scoped,
|
|
91
|
-
Effect.catchCause(Effect.logError),
|
|
92
|
-
Effect.ensuring(Effect.sync(() => currentShards.clear())),
|
|
93
|
-
Effect.forever,
|
|
94
|
-
Effect.forkScoped,
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
return {
|
|
98
|
-
shards: Effect.sync(() => currentShards as ReadonlySet<RunningShard>),
|
|
99
|
-
} as const
|
|
100
|
-
}).pipe(
|
|
101
|
-
Effect.annotateLogs({
|
|
102
|
-
package: "dfx",
|
|
103
|
-
module: "DiscordGateway/Sharder",
|
|
104
|
-
}),
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
export class Sharder extends ServiceMap.Service<
|
|
108
|
-
Sharder,
|
|
109
|
-
{
|
|
110
|
-
readonly shards: Effect.Effect<ReadonlySet<RunningShard>, never, never>
|
|
111
|
-
}
|
|
112
|
-
>()("dfx/DiscordGateway/Sharder") {}
|
|
113
|
-
|
|
114
|
-
export const SharderLive = Layer.effect(Sharder, make).pipe(
|
|
115
|
-
Layer.provide(DiscordRESTLive),
|
|
116
|
-
Layer.provide(RateLimiterLive),
|
|
117
|
-
Layer.provide(ShardLive),
|
|
118
|
-
)
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { WebSocketConstructor } from "effect/unstable/socket/Socket"
|
|
2
|
-
import type { DiscordConfig } from "./DiscordConfig.ts"
|
|
3
|
-
import type { DiscordWSCodec } from "./DiscordGateway/DiscordWS.ts"
|
|
4
|
-
import type { Messsaging } from "./DiscordGateway/Messaging.ts"
|
|
5
|
-
import { Messaging, MesssagingLive } from "./DiscordGateway/Messaging.ts"
|
|
6
|
-
import type { RunningShard } from "./DiscordGateway/Shard.ts"
|
|
7
|
-
import type { ShardStateStore } from "./DiscordGateway/Shard/StateStore.ts"
|
|
8
|
-
import { Sharder, SharderLive } from "./DiscordGateway/Sharder.ts"
|
|
9
|
-
import type { ShardStore } from "./DiscordGateway/ShardStore.ts"
|
|
10
|
-
import type { RateLimitStore } from "./RateLimit.ts"
|
|
11
|
-
import type * as Discord from "./types.ts"
|
|
12
|
-
import * as Effect from "effect/Effect"
|
|
13
|
-
import * as Layer from "effect/Layer"
|
|
14
|
-
import type * as Stream from "effect/Stream"
|
|
15
|
-
import type { HttpClient } from "effect/unstable/http/HttpClient"
|
|
16
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
17
|
-
|
|
18
|
-
export const TypeId = Symbol.for("dfx/DiscordGateway")
|
|
19
|
-
export type TypeId = typeof TypeId
|
|
20
|
-
|
|
21
|
-
export interface DiscordGateway {
|
|
22
|
-
readonly [TypeId]: TypeId
|
|
23
|
-
|
|
24
|
-
readonly dispatch: Stream.Stream<Discord.GatewayReceivePayload>
|
|
25
|
-
readonly fromDispatch: <K extends `${Discord.GatewayDispatchEvents}`>(
|
|
26
|
-
event: K,
|
|
27
|
-
) => Stream.Stream<
|
|
28
|
-
Extract<Discord.DistributedGatewayDispatchPayload, { readonly t: K }>["d"]
|
|
29
|
-
>
|
|
30
|
-
readonly handleDispatch: <
|
|
31
|
-
K extends `${Discord.GatewayDispatchEvents}`,
|
|
32
|
-
R,
|
|
33
|
-
E,
|
|
34
|
-
A,
|
|
35
|
-
>(
|
|
36
|
-
event: K,
|
|
37
|
-
handle: (
|
|
38
|
-
event: Extract<
|
|
39
|
-
Discord.DistributedGatewayDispatchPayload,
|
|
40
|
-
{ readonly t: K }
|
|
41
|
-
>["d"],
|
|
42
|
-
) => Effect.Effect<A, E, R>,
|
|
43
|
-
) => Effect.Effect<never, E, R>
|
|
44
|
-
readonly send: (payload: Discord.GatewaySendPayload) => Effect.Effect<boolean>
|
|
45
|
-
readonly shards: Effect.Effect<ReadonlySet<RunningShard>>
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export const DiscordGateway =
|
|
49
|
-
ServiceMap.Service<DiscordGateway>("dfx/DiscordGateway")
|
|
50
|
-
|
|
51
|
-
export const make: Effect.Effect<DiscordGateway, never, Messsaging | Sharder> =
|
|
52
|
-
Effect.gen(function* () {
|
|
53
|
-
const sharder = yield* Sharder
|
|
54
|
-
const messaging = yield* Messaging
|
|
55
|
-
|
|
56
|
-
return DiscordGateway.of({
|
|
57
|
-
[TypeId]: TypeId,
|
|
58
|
-
dispatch: messaging.dispatch,
|
|
59
|
-
fromDispatch: messaging.fromDispatch as any,
|
|
60
|
-
handleDispatch: messaging.handleDispatch as any,
|
|
61
|
-
send: messaging.send,
|
|
62
|
-
shards: sharder.shards,
|
|
63
|
-
})
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
export const DiscordGatewayLive: Layer.Layer<
|
|
67
|
-
DiscordGateway,
|
|
68
|
-
never,
|
|
69
|
-
| ShardStore
|
|
70
|
-
| DiscordConfig
|
|
71
|
-
| RateLimitStore
|
|
72
|
-
| DiscordWSCodec
|
|
73
|
-
| ShardStateStore
|
|
74
|
-
| WebSocketConstructor
|
|
75
|
-
| HttpClient
|
|
76
|
-
> = Layer.effect(DiscordGateway, make).pipe(
|
|
77
|
-
Layer.provide(MesssagingLive),
|
|
78
|
-
Layer.provide(SharderLive),
|
|
79
|
-
)
|