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.
Files changed (194) hide show
  1. package/dist/Cache/driver.d.ts.map +1 -1
  2. package/dist/Cache/memory.d.ts.map +1 -1
  3. package/dist/Cache/memoryTTL.d.ts.map +1 -1
  4. package/dist/Cache/prelude.d.ts.map +1 -1
  5. package/dist/Cache.d.ts.map +1 -1
  6. package/dist/DiscordConfig.d.ts.map +1 -1
  7. package/dist/DiscordGateway/DiscordWS.d.ts.map +1 -1
  8. package/dist/DiscordGateway/Messaging.d.ts.map +1 -1
  9. package/dist/DiscordGateway/Shard/StateStore.d.ts.map +1 -1
  10. package/dist/DiscordGateway/Shard/heartbeats.d.ts.map +1 -1
  11. package/dist/DiscordGateway/Shard/identify.d.ts.map +1 -1
  12. package/dist/DiscordGateway/Shard/sendEvents.d.ts.map +1 -1
  13. package/dist/DiscordGateway/Shard/utils.d.ts.map +1 -1
  14. package/dist/DiscordGateway/Shard.d.ts.map +1 -1
  15. package/dist/DiscordGateway/ShardStore.d.ts.map +1 -1
  16. package/dist/DiscordGateway/Sharder.d.ts +1 -1
  17. package/dist/DiscordGateway/Sharder.d.ts.map +1 -1
  18. package/dist/DiscordGateway.d.ts.map +1 -1
  19. package/dist/DiscordREST/Generated.d.ts.map +1 -1
  20. package/dist/DiscordREST/utils.d.ts.map +1 -1
  21. package/dist/DiscordREST.d.ts.map +1 -1
  22. package/dist/Helpers/flags.d.ts.map +1 -1
  23. package/dist/Helpers/intents.d.ts.map +1 -1
  24. package/dist/Helpers/interactions.d.ts.map +1 -1
  25. package/dist/Helpers/members.d.ts.map +1 -1
  26. package/dist/Helpers/permissions.d.ts.map +1 -1
  27. package/dist/Helpers/ui.d.ts.map +1 -1
  28. package/dist/Interactions/builder.d.ts.map +1 -1
  29. package/dist/Interactions/commandHelper.d.ts.map +1 -1
  30. package/dist/Interactions/context.d.ts.map +1 -1
  31. package/dist/Interactions/definitions.d.ts.map +1 -1
  32. package/dist/Interactions/error.d.ts.map +1 -1
  33. package/dist/Interactions/gateway.d.ts.map +1 -1
  34. package/dist/Interactions/handlers.d.ts.map +1 -1
  35. package/dist/Interactions/index.d.ts.map +1 -1
  36. package/dist/Interactions/utils.d.ts.map +1 -1
  37. package/dist/Interactions/webhook.d.ts.map +1 -1
  38. package/dist/RateLimit/memory.d.ts.map +1 -1
  39. package/dist/RateLimit/utils.d.ts.map +1 -1
  40. package/dist/RateLimit.d.ts.map +1 -1
  41. package/dist/gateway.d.ts.map +1 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/types.d.ts.map +1 -1
  44. package/dist/utils/Effect.d.ts.map +1 -1
  45. package/dist/version.d.ts +1 -1
  46. package/dist/version.d.ts.map +1 -1
  47. package/dist/version.js +1 -1
  48. package/dist/webhooks.d.ts.map +1 -1
  49. package/package.json +5 -5
  50. package/src/version.ts +1 -1
  51. package/dist/LICENSE +0 -21
  52. package/dist/README.md +0 -66
  53. package/dist/mjs/Cache/driver.mjs +0 -3
  54. package/dist/mjs/Cache/driver.mjs.map +0 -1
  55. package/dist/mjs/Cache/memory.mjs +0 -48
  56. package/dist/mjs/Cache/memory.mjs.map +0 -1
  57. package/dist/mjs/Cache/memoryTTL.mjs +0 -119
  58. package/dist/mjs/Cache/memoryTTL.mjs.map +0 -1
  59. package/dist/mjs/Cache/prelude.mjs +0 -131
  60. package/dist/mjs/Cache/prelude.mjs.map +0 -1
  61. package/dist/mjs/Cache.mjs +0 -90
  62. package/dist/mjs/Cache.mjs.map +0 -1
  63. package/dist/mjs/DiscordConfig.mjs +0 -32
  64. package/dist/mjs/DiscordConfig.mjs.map +0 -1
  65. package/dist/mjs/DiscordGateway/DiscordWS.mjs +0 -77
  66. package/dist/mjs/DiscordGateway/DiscordWS.mjs.map +0 -1
  67. package/dist/mjs/DiscordGateway/Messaging.mjs +0 -35
  68. package/dist/mjs/DiscordGateway/Messaging.mjs.map +0 -1
  69. package/dist/mjs/DiscordGateway/Shard/StateStore.mjs +0 -41
  70. package/dist/mjs/DiscordGateway/Shard/StateStore.mjs.map +0 -1
  71. package/dist/mjs/DiscordGateway/Shard/heartbeats.mjs +0 -25
  72. package/dist/mjs/DiscordGateway/Shard/heartbeats.mjs.map +0 -1
  73. package/dist/mjs/DiscordGateway/Shard/identify.mjs +0 -29
  74. package/dist/mjs/DiscordGateway/Shard/identify.mjs.map +0 -1
  75. package/dist/mjs/DiscordGateway/Shard/sendEvents.mjs +0 -26
  76. package/dist/mjs/DiscordGateway/Shard/sendEvents.mjs.map +0 -1
  77. package/dist/mjs/DiscordGateway/Shard/utils.mjs +0 -3
  78. package/dist/mjs/DiscordGateway/Shard/utils.mjs.map +0 -1
  79. package/dist/mjs/DiscordGateway/Shard.mjs +0 -147
  80. package/dist/mjs/DiscordGateway/Shard.mjs.map +0 -1
  81. package/dist/mjs/DiscordGateway/ShardStore.mjs +0 -24
  82. package/dist/mjs/DiscordGateway/ShardStore.mjs.map +0 -1
  83. package/dist/mjs/DiscordGateway/Sharder.mjs +0 -67
  84. package/dist/mjs/DiscordGateway/Sharder.mjs.map +0 -1
  85. package/dist/mjs/DiscordGateway.mjs +0 -21
  86. package/dist/mjs/DiscordGateway.mjs.map +0 -1
  87. package/dist/mjs/DiscordREST/Generated.mjs +0 -2471
  88. package/dist/mjs/DiscordREST/Generated.mjs.map +0 -1
  89. package/dist/mjs/DiscordREST/utils.mjs +0 -21
  90. package/dist/mjs/DiscordREST/utils.mjs.map +0 -1
  91. package/dist/mjs/DiscordREST.mjs +0 -119
  92. package/dist/mjs/DiscordREST.mjs.map +0 -1
  93. package/dist/mjs/Helpers/flags.mjs +0 -45
  94. package/dist/mjs/Helpers/flags.mjs.map +0 -1
  95. package/dist/mjs/Helpers/intents.mjs +0 -27
  96. package/dist/mjs/Helpers/intents.mjs.map +0 -1
  97. package/dist/mjs/Helpers/interactions.mjs +0 -115
  98. package/dist/mjs/Helpers/interactions.mjs.map +0 -1
  99. package/dist/mjs/Helpers/members.mjs +0 -9
  100. package/dist/mjs/Helpers/members.mjs.map +0 -1
  101. package/dist/mjs/Helpers/permissions.mjs +0 -84
  102. package/dist/mjs/Helpers/permissions.mjs.map +0 -1
  103. package/dist/mjs/Helpers/ui.mjs +0 -137
  104. package/dist/mjs/Helpers/ui.mjs.map +0 -1
  105. package/dist/mjs/Interactions/builder.mjs +0 -56
  106. package/dist/mjs/Interactions/builder.mjs.map +0 -1
  107. package/dist/mjs/Interactions/commandHelper.mjs +0 -49
  108. package/dist/mjs/Interactions/commandHelper.mjs.map +0 -1
  109. package/dist/mjs/Interactions/context.mjs +0 -28
  110. package/dist/mjs/Interactions/context.mjs.map +0 -1
  111. package/dist/mjs/Interactions/definitions.mjs +0 -51
  112. package/dist/mjs/Interactions/definitions.mjs.map +0 -1
  113. package/dist/mjs/Interactions/error.mjs +0 -2
  114. package/dist/mjs/Interactions/error.mjs.map +0 -1
  115. package/dist/mjs/Interactions/gateway.mjs +0 -82
  116. package/dist/mjs/Interactions/gateway.mjs.map +0 -1
  117. package/dist/mjs/Interactions/handlers.mjs +0 -64
  118. package/dist/mjs/Interactions/handlers.mjs.map +0 -1
  119. package/dist/mjs/Interactions/index.mjs +0 -11
  120. package/dist/mjs/Interactions/index.mjs.map +0 -1
  121. package/dist/mjs/Interactions/utils.mjs +0 -26
  122. package/dist/mjs/Interactions/utils.mjs.map +0 -1
  123. package/dist/mjs/Interactions/webhook.mjs +0 -75
  124. package/dist/mjs/Interactions/webhook.mjs.map +0 -1
  125. package/dist/mjs/RateLimit/memory.mjs +0 -39
  126. package/dist/mjs/RateLimit/memory.mjs.map +0 -1
  127. package/dist/mjs/RateLimit/utils.mjs +0 -18
  128. package/dist/mjs/RateLimit/utils.mjs.map +0 -1
  129. package/dist/mjs/RateLimit.mjs +0 -28
  130. package/dist/mjs/RateLimit.mjs.map +0 -1
  131. package/dist/mjs/gateway.mjs +0 -19
  132. package/dist/mjs/gateway.mjs.map +0 -1
  133. package/dist/mjs/index.mjs +0 -18
  134. package/dist/mjs/index.mjs.map +0 -1
  135. package/dist/mjs/types.mjs +0 -356
  136. package/dist/mjs/types.mjs.map +0 -1
  137. package/dist/mjs/utils/Effect.mjs +0 -44
  138. package/dist/mjs/utils/Effect.mjs.map +0 -1
  139. package/dist/mjs/version.mjs +0 -2
  140. package/dist/mjs/version.mjs.map +0 -1
  141. package/dist/mjs/webhooks.mjs +0 -6
  142. package/dist/mjs/webhooks.mjs.map +0 -1
  143. package/dist/package.json +0 -48
  144. package/dist/src/Cache/driver.ts +0 -37
  145. package/dist/src/Cache/memory.ts +0 -83
  146. package/dist/src/Cache/memoryTTL.ts +0 -225
  147. package/dist/src/Cache/prelude.ts +0 -279
  148. package/dist/src/Cache.ts +0 -261
  149. package/dist/src/DiscordConfig.ts +0 -67
  150. package/dist/src/DiscordGateway/DiscordWS.ts +0 -157
  151. package/dist/src/DiscordGateway/Messaging.ts +0 -71
  152. package/dist/src/DiscordGateway/Shard/StateStore.ts +0 -72
  153. package/dist/src/DiscordGateway/Shard/heartbeats.ts +0 -60
  154. package/dist/src/DiscordGateway/Shard/identify.ts +0 -50
  155. package/dist/src/DiscordGateway/Shard/sendEvents.ts +0 -43
  156. package/dist/src/DiscordGateway/Shard/utils.ts +0 -13
  157. package/dist/src/DiscordGateway/Shard.ts +0 -205
  158. package/dist/src/DiscordGateway/ShardStore.ts +0 -42
  159. package/dist/src/DiscordGateway/Sharder.ts +0 -118
  160. package/dist/src/DiscordGateway.ts +0 -79
  161. package/dist/src/DiscordREST/Generated.ts +0 -10832
  162. package/dist/src/DiscordREST/utils.ts +0 -42
  163. package/dist/src/DiscordREST.ts +0 -256
  164. package/dist/src/Helpers/flags.ts +0 -73
  165. package/dist/src/Helpers/intents.ts +0 -35
  166. package/dist/src/Helpers/interactions.ts +0 -317
  167. package/dist/src/Helpers/members.ts +0 -18
  168. package/dist/src/Helpers/permissions.ts +0 -145
  169. package/dist/src/Helpers/ui.ts +0 -253
  170. package/dist/src/Interactions/builder.ts +0 -171
  171. package/dist/src/Interactions/commandHelper.ts +0 -231
  172. package/dist/src/Interactions/context.ts +0 -104
  173. package/dist/src/Interactions/definitions.ts +0 -144
  174. package/dist/src/Interactions/error.ts +0 -3
  175. package/dist/src/Interactions/gateway.ts +0 -193
  176. package/dist/src/Interactions/handlers.ts +0 -108
  177. package/dist/src/Interactions/index.ts +0 -30
  178. package/dist/src/Interactions/utils.ts +0 -93
  179. package/dist/src/Interactions/webhook.ts +0 -204
  180. package/dist/src/RateLimit/memory.ts +0 -63
  181. package/dist/src/RateLimit/utils.ts +0 -28
  182. package/dist/src/RateLimit.ts +0 -90
  183. package/dist/src/gateway.ts +0 -50
  184. package/dist/src/index.ts +0 -44
  185. package/dist/src/types.ts +0 -3090
  186. package/dist/src/utils/Effect.ts +0 -65
  187. package/dist/src/version.ts +0 -1
  188. package/dist/src/webhooks.ts +0 -25
  189. package/dist/tsconfig.base.json +0 -54
  190. package/dist/tsconfig.build.json +0 -10
  191. package/dist/tsconfig.examples.json +0 -10
  192. package/dist/tsconfig.json +0 -14
  193. package/dist/tsconfig.madge.json +0 -12
  194. 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
- )