dfx 0.42.8 → 0.43.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/DiscordConfig.d.ts +3 -1
- package/DiscordConfig.js +2 -1
- package/DiscordConfig.js.map +1 -1
- package/DiscordGateway/Shard.d.ts +3 -3
- package/DiscordGateway/Shard.js +37 -31
- package/DiscordGateway/Shard.js.map +1 -1
- package/DiscordGateway/WS.js +11 -8
- package/DiscordGateway/WS.js.map +1 -1
- package/gateway.d.ts +2 -2
- package/gateway.js +7 -9
- package/gateway.js.map +1 -1
- package/package.json +3 -3
- package/src/DiscordConfig.ts +9 -1
- package/src/DiscordGateway/Shard.ts +33 -9
- package/src/DiscordGateway/WS.ts +18 -12
- package/src/gateway.ts +12 -14
- package/src/package.json +52 -0
- package/src/webhooks.ts +14 -17
- package/webhooks.d.ts +2 -2
- package/webhooks.js +9 -10
- package/webhooks.js.map +1 -1
package/DiscordConfig.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ConfigSecret, Duration, Discord, Config } from "dfx/_common";
|
|
2
2
|
export interface DiscordConfig {
|
|
3
3
|
token: ConfigSecret;
|
|
4
|
+
debug: boolean;
|
|
4
5
|
rest: {
|
|
5
6
|
baseUrl: string;
|
|
6
7
|
globalRateLimit: {
|
|
@@ -18,9 +19,10 @@ export interface DiscordConfig {
|
|
|
18
19
|
export declare const DiscordConfig: import("@effect/data/Context").Tag<DiscordConfig, DiscordConfig>;
|
|
19
20
|
export interface MakeOpts {
|
|
20
21
|
token: ConfigSecret;
|
|
22
|
+
debug?: boolean;
|
|
21
23
|
rest?: Partial<DiscordConfig["rest"]>;
|
|
22
24
|
gateway?: Partial<DiscordConfig["gateway"]>;
|
|
23
25
|
}
|
|
24
|
-
export declare const make: ({ token, rest, gateway }: MakeOpts) => DiscordConfig;
|
|
26
|
+
export declare const make: ({ token, debug, rest, gateway, }: MakeOpts) => DiscordConfig;
|
|
25
27
|
export declare const makeLayer: (a_0: MakeOpts) => import("@effect-http/client/_common").Layer<never, never, DiscordConfig>;
|
|
26
28
|
export declare const makeFromConfig: (_: Config.Wrap<MakeOpts>) => import("@effect-http/client/_common").Layer<never, import("./_common.js").ConfigError, DiscordConfig>;
|
package/DiscordConfig.js
CHANGED
|
@@ -6,8 +6,9 @@ import * as tsplus_module_5 from "@effect/io/Config";
|
|
|
6
6
|
import * as tsplus_module_6 from "@effect/io/Effect";
|
|
7
7
|
const VERSION = 10;
|
|
8
8
|
export const DiscordConfig = tsplus_module_1.Tag();
|
|
9
|
-
export const make = ({ token, rest, gateway }) => ({
|
|
9
|
+
export const make = ({ token, debug = false, rest, gateway, }) => ({
|
|
10
10
|
token,
|
|
11
|
+
debug,
|
|
11
12
|
rest: {
|
|
12
13
|
baseUrl: `https://discord.com/api/v${VERSION}`,
|
|
13
14
|
...(rest ?? {}),
|
package/DiscordConfig.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiscordConfig.js","sourceRoot":"","sources":["src/DiscordConfig.ts"],"names":[],"mappings":";;;;;;AAAA,MAAM,OAAO,GAAG,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"DiscordConfig.js","sourceRoot":"","sources":["src/DiscordConfig.ts"],"names":[],"mappings":";;;;;;AAAA,MAAM,OAAO,GAAG,EAAE,CAAA;AAoBlB,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAA,GAAG,EAAiB,CAAA;AASjD,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,EACnB,KAAK,EACL,KAAK,GAAG,KAAK,EACb,IAAI,EACJ,OAAO,GACE,EAAiB,EAAE,CAAC,CAAC;IAC9B,KAAK;IACL,KAAK;IACL,IAAI,EAAE;QACJ,OAAO,EAAE,4BAA4B,OAAO,EAAE;QAC9C,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QACf,eAAe,EAAE;YACf,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,wBAAiB,CAAC,CAAC;YAC3B,GAAG,CAAC,IAAI,EAAE,eAAe,IAAI,EAAE,CAAC;SACjC;KACF;IACD,OAAO,EAAE;QACP,OAAO,EAAE,gBAAA,OAAO,CAAC,cAAc,CAAC,MAAM;QACtC,iBAAiB,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5B,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;KACnB;CACF,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,gBAAA,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,wBAAc,aAAa,EAAE,CAAC,CAAC,CAAC,CAAA;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAwB,EAAE,EAAE,CACzD,wBAAA,2CAAA,uBAAc,CAAC,CAAC,GAAY,IAAI,CAAC,EAAS,aAAa,CAAC,CAAA"}
|
|
@@ -2,10 +2,10 @@ import { Hub, Discord, Effect } from "dfx/_common";
|
|
|
2
2
|
import { DiscordConfig } from "dfx/DiscordConfig";
|
|
3
3
|
import { RateLimiter } from "dfx/RateLimit";
|
|
4
4
|
import { DiscordWS } from "./DiscordWS.js";
|
|
5
|
-
|
|
5
|
+
import { Log } from "dfx/Log";
|
|
6
|
+
export declare const make: import("@effect/io/Effect").Effect<DiscordConfig | Log | RateLimiter | DiscordWS, never, {
|
|
6
7
|
readonly connect: (shard: [id: number, count: number], hub: Hub<Discord.GatewayPayload<Discord.ReceiveEvent>>) => import("@effect/io/Effect").Effect<never, never, {
|
|
7
8
|
readonly run: import("@effect/io/Effect").Effect<never, import("./WS.js").WebSocketError | import("./WS.js").WebSocketCloseError, never>;
|
|
8
|
-
readonly connected: import("@effect/io/Effect").Effect<never, never, boolean>;
|
|
9
9
|
readonly send: (p: Discord.GatewayPayload) => import("@effect/io/Effect").Effect<never, never, boolean>;
|
|
10
10
|
readonly reconnect: import("@effect/io/Effect").Effect<never, never, boolean>;
|
|
11
11
|
}>;
|
|
@@ -13,4 +13,4 @@ export declare const make: import("@effect/io/Effect").Effect<DiscordConfig | Ra
|
|
|
13
13
|
export interface Shard extends Effect.Success<typeof make> {
|
|
14
14
|
}
|
|
15
15
|
export declare const Shard: import("@effect/data/Context").Tag<Shard, Shard>;
|
|
16
|
-
export declare const LiveShard: import("@effect-http/client/_common").Layer<DiscordConfig |
|
|
16
|
+
export declare const LiveShard: import("@effect-http/client/_common").Layer<DiscordConfig | Log | import("dfx/RateLimit").RateLimitStore | import("./DiscordWS.js").DiscordWSCodec, never, Shard>;
|
package/DiscordGateway/Shard.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as tsplus_module_1 from "@effect/io/
|
|
2
|
-
import * as tsplus_module_2 from "
|
|
3
|
-
import * as tsplus_module_3 from "
|
|
4
|
-
import * as tsplus_module_4 from "@effect/io/
|
|
5
|
-
import * as tsplus_module_5 from "@effect/
|
|
6
|
-
import * as tsplus_module_6 from "@effect/data/
|
|
7
|
-
import * as tsplus_module_7 from "@effect/
|
|
1
|
+
import * as tsplus_module_1 from "@effect/io/Effect";
|
|
2
|
+
import * as tsplus_module_2 from "dfx/_common";
|
|
3
|
+
import * as tsplus_module_3 from "@effect/io/Config/Secret";
|
|
4
|
+
import * as tsplus_module_4 from "@effect/io/Queue";
|
|
5
|
+
import * as tsplus_module_5 from "@effect/data/Option";
|
|
6
|
+
import * as tsplus_module_6 from "@effect/data/Chunk";
|
|
7
|
+
import * as tsplus_module_7 from "@effect/io/Ref";
|
|
8
8
|
import * as tsplus_module_8 from "@effect/data/Duration";
|
|
9
9
|
import * as tsplus_module_9 from "@effect/io/Layer";
|
|
10
10
|
import { DiscordConfig } from "dfx/DiscordConfig";
|
|
@@ -15,57 +15,63 @@ import * as Identify from "./Shard/identify.js";
|
|
|
15
15
|
import * as InvalidSession from "./Shard/invalidSession.js";
|
|
16
16
|
import * as Utils from "./Shard/utils.js";
|
|
17
17
|
import { Reconnect } from "./WS.js";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
import { Log } from "dfx/Log";
|
|
19
|
+
export const make = tsplus_module_1.flatMap(DiscordConfig, ({ token, gateway }) => tsplus_module_1.flatMap(RateLimiter, limiter => tsplus_module_1.flatMap(DiscordWS, dws => tsplus_module_1.map(Log, log => {
|
|
20
|
+
const connect = (shard, hub) => tsplus_module_1.flatMap(tsplus_module_4.unbounded(), outboundQueue => tsplus_module_1.flatMap(tsplus_module_4.unbounded(), pendingQueue => tsplus_module_1.flatMap(tsplus_module_7.make(0 /* Phase.Connecting */), phase => {
|
|
21
|
+
const setPhase = (p) => tsplus_module_1.zipLeft(tsplus_module_7.set(phase, p), log.debug("Shard", shard, "phase", p));
|
|
22
|
+
const outbound = tsplus_module_1.tap(outboundQueue
|
|
21
23
|
.take(), () => limiter.maybeWait("dfx.shard.send", tsplus_module_8.minutes(1), 120));
|
|
22
|
-
const send = (p) =>
|
|
24
|
+
const send = (p) => tsplus_module_1.flatMap(tsplus_module_7.get(phase), _ => _ === 2 /* Phase.Connected */
|
|
25
|
+
? outboundQueue.offer(p)
|
|
26
|
+
: pendingQueue.offer(p));
|
|
27
|
+
const heartbeatSend = (p) => tsplus_module_1.flatMap(tsplus_module_7.get(phase), _ => _ !== 0 /* Phase.Connecting */
|
|
28
|
+
? outboundQueue.offer(p)
|
|
29
|
+
: tsplus_module_1.succeed(false));
|
|
23
30
|
const prioritySend = (p) => outboundQueue.offer(p);
|
|
24
|
-
const resume =
|
|
25
|
-
const onReconnect =
|
|
26
|
-
.takeAll(), _ => pendingQueue.offerAll(
|
|
31
|
+
const resume = tsplus_module_1.asUnit(tsplus_module_1.tap(tsplus_module_1.zipRight(setPhase(2 /* Phase.Connected */), pendingQueue.takeAll()), _ => outboundQueue.offerAll(_)));
|
|
32
|
+
const onReconnect = tsplus_module_1.zipRight(tsplus_module_1.tap(outboundQueue
|
|
33
|
+
.takeAll(), _ => pendingQueue.offerAll(tsplus_module_6.filter(_, msg => msg !== Reconnect &&
|
|
27
34
|
msg.op !== 2 /* Discord.GatewayOpcode.IDENTIFY */ &&
|
|
28
35
|
msg.op !== 6 /* Discord.GatewayOpcode.RESUME */ &&
|
|
29
|
-
msg.op !== 1 /* Discord.GatewayOpcode.HEARTBEAT */))),
|
|
30
|
-
return
|
|
31
|
-
const maybeUpdateUrl = (p) =>
|
|
32
|
-
return
|
|
36
|
+
msg.op !== 1 /* Discord.GatewayOpcode.HEARTBEAT */))), setPhase(0 /* Phase.Connecting */));
|
|
37
|
+
return tsplus_module_1.flatMap(dws.connect({ outbound, onReconnect }), socket => tsplus_module_1.flatMap(Utils.latest(p => tsplus_module_5.map(tsplus_module_5.filter((p) => p.op === 0 /* Discord.GatewayOpcode.DISPATCH */ && p.t === "READY")(tsplus_module_5.some(p)), p => p.d)), ([latestReady, updateLatestReady]) => tsplus_module_1.flatMap(Utils.latest(p => tsplus_module_5.fromNullable(p.s)), ([latestSequence, updateLatestSequence]) => {
|
|
38
|
+
const maybeUpdateUrl = (p) => tsplus_module_5.match(tsplus_module_5.map(tsplus_module_5.filter((p) => p.op === 0 /* Discord.GatewayOpcode.DISPATCH */ && p.t === "READY")(tsplus_module_5.some(p)), p => p.d), () => tsplus_module_1.unit(), a => socket.setUrl(a.resume_gateway_url));
|
|
39
|
+
return tsplus_module_1.flatMap(tsplus_module_4.unbounded(), hellos => tsplus_module_1.map(tsplus_module_4.unbounded(), acks => {
|
|
33
40
|
// heartbeats
|
|
34
|
-
const heartbeats = Heartbeats.send(hellos, acks, latestSequence,
|
|
41
|
+
const heartbeats = Heartbeats.send(hellos, acks, latestSequence, heartbeatSend);
|
|
35
42
|
// identify
|
|
36
43
|
const identify = Identify.identifyOrResume({
|
|
37
|
-
token:
|
|
44
|
+
token: tsplus_module_3.value(token),
|
|
38
45
|
shard,
|
|
39
46
|
intents: gateway.intents,
|
|
40
47
|
presence: gateway.presence,
|
|
41
48
|
}, latestReady, latestSequence);
|
|
42
|
-
const onPayload = (p) =>
|
|
43
|
-
let effect =
|
|
49
|
+
const onPayload = (p) => tsplus_module_1.flatMap(tsplus_module_1.zipPar(tsplus_module_1.zipPar(updateLatestReady(p), updateLatestSequence(p)), maybeUpdateUrl(p)), () => {
|
|
50
|
+
let effect = tsplus_module_1.unit();
|
|
44
51
|
switch (p.op) {
|
|
45
52
|
case 10 /* Discord.GatewayOpcode.HELLO */:
|
|
46
|
-
effect =
|
|
53
|
+
effect = tsplus_module_1.zipPar(tsplus_module_1.tap(identify, prioritySend), tsplus_module_1.zipRight(setPhase(1 /* Phase.Handshake */), hellos.offer(p)));
|
|
47
54
|
break;
|
|
48
55
|
case 11 /* Discord.GatewayOpcode.HEARTBEAT_ACK */:
|
|
49
56
|
effect = acks.offer(p);
|
|
50
57
|
break;
|
|
51
58
|
case 9 /* Discord.GatewayOpcode.INVALID_SESSION */:
|
|
52
|
-
effect =
|
|
59
|
+
effect = tsplus_module_1.tap(InvalidSession.fromPayload(p, latestReady), send);
|
|
53
60
|
break;
|
|
54
61
|
case 0 /* Discord.GatewayOpcode.DISPATCH */:
|
|
55
62
|
if (p.t === "READY" || p.t === "RESUMED") {
|
|
56
|
-
effect =
|
|
63
|
+
effect = tsplus_module_1.zipRight(resume, hub.publish(p));
|
|
57
64
|
}
|
|
58
65
|
else {
|
|
59
66
|
effect = hub.publish(p);
|
|
60
67
|
}
|
|
61
68
|
break;
|
|
62
69
|
}
|
|
63
|
-
return
|
|
70
|
+
return tsplus_module_1.map(effect, () => void 0);
|
|
64
71
|
});
|
|
65
|
-
const run =
|
|
72
|
+
const run = tsplus_module_1.zipParLeft(tsplus_module_1.zipParLeft(tsplus_module_1.forever(tsplus_module_1.flatMap(socket.take, onPayload)), heartbeats), socket.run);
|
|
66
73
|
return {
|
|
67
74
|
run,
|
|
68
|
-
connected: tsplus_module_1.get(connecting),
|
|
69
75
|
send: (p) => send(p),
|
|
70
76
|
reconnect: send(Reconnect),
|
|
71
77
|
};
|
|
@@ -73,7 +79,7 @@ export const make = tsplus_module_2.flatMap(DiscordConfig, ({ token, gateway })
|
|
|
73
79
|
})));
|
|
74
80
|
})));
|
|
75
81
|
return { connect };
|
|
76
|
-
})));
|
|
77
|
-
export const Shard =
|
|
78
|
-
export const LiveShard = tsplus_module_9.provide(
|
|
82
|
+
}))));
|
|
83
|
+
export const Shard = tsplus_module_2.Tag();
|
|
84
|
+
export const LiveShard = tsplus_module_9.provide(tsplus_module_1.toLayer(make, Shard))((tsplus_module_9.merge(LiveRateLimiter)(LiveDiscordWS)));
|
|
79
85
|
//# sourceMappingURL=Shard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Shard.js","sourceRoot":"","sources":["../src/DiscordGateway/Shard.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAW,MAAM,gBAAgB,CAAA;AAClE,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAA;AACnD,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAA;AAC/C,OAAO,KAAK,cAAc,MAAM,2BAA2B,CAAA;AAC3D,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"Shard.js","sourceRoot":"","sources":["../src/DiscordGateway/Shard.ts"],"names":[],"mappings":"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"}
|
package/DiscordGateway/WS.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as tsplus_module_1 from "@effect/io/Effect";
|
|
2
2
|
import * as tsplus_module_2 from "@effect/io/Ref";
|
|
3
|
-
import * as tsplus_module_3 from "@effect/
|
|
4
|
-
import * as tsplus_module_4 from "@effect/
|
|
5
|
-
import * as tsplus_module_5 from "
|
|
3
|
+
import * as tsplus_module_3 from "@effect/io/Runtime";
|
|
4
|
+
import * as tsplus_module_4 from "@effect/data/Duration";
|
|
5
|
+
import * as tsplus_module_5 from "@effect/io/Queue";
|
|
6
|
+
import * as tsplus_module_6 from "dfx/_common";
|
|
6
7
|
import { Log } from "dfx/Log";
|
|
7
8
|
import WebSocket from "isomorphic-ws";
|
|
8
9
|
export const Reconnect = Symbol();
|
|
@@ -30,9 +31,11 @@ const socket = (urlRef) => tsplus_module_1.acquireRelease(tsplus_module_1.map(ts
|
|
|
30
31
|
ws.removeAllListeners?.();
|
|
31
32
|
ws.close();
|
|
32
33
|
}));
|
|
33
|
-
const offer = (ws, queue, log) => tsplus_module_1.async(resume => {
|
|
34
|
+
const offer = (ws, queue, log) => tsplus_module_1.flatMap(tsplus_module_1.runtime(), runtime => tsplus_module_1.async(resume => {
|
|
35
|
+
const run = tsplus_module_3.runFork(runtime);
|
|
34
36
|
ws.addEventListener("message", message => {
|
|
35
|
-
|
|
37
|
+
run(tsplus_module_1.zipLeft(queue
|
|
38
|
+
.offer(message.data), log.debug("WS", "offer", message.data)));
|
|
36
39
|
});
|
|
37
40
|
ws.addEventListener("error", cause => {
|
|
38
41
|
resume(tsplus_module_1.fail(new WebSocketError("error", cause)));
|
|
@@ -40,7 +43,7 @@ const offer = (ws, queue, log) => tsplus_module_1.async(resume => {
|
|
|
40
43
|
ws.addEventListener("close", e => {
|
|
41
44
|
resume(tsplus_module_1.fail(new WebSocketCloseError(e.code, e.reason)));
|
|
42
45
|
});
|
|
43
|
-
});
|
|
46
|
+
}));
|
|
44
47
|
const waitForOpen = (ws, timeout) => tsplus_module_1.timeoutFail(tsplus_module_1.suspend(() => {
|
|
45
48
|
if (ws.readyState === WebSocket.OPEN) {
|
|
46
49
|
return tsplus_module_1.unit();
|
|
@@ -63,12 +66,12 @@ const send = (ws, take, log) => tsplus_module_1.forever(tsplus_module_1.tap(tspl
|
|
|
63
66
|
});
|
|
64
67
|
}));
|
|
65
68
|
const make = tsplus_module_1.map(Log, log => {
|
|
66
|
-
const connect = (url, takeOutbound, onReconnect = tsplus_module_1.unit(), openTimeout =
|
|
69
|
+
const connect = (url, takeOutbound, onReconnect = tsplus_module_1.unit(), openTimeout = tsplus_module_4.seconds(3)) => tsplus_module_1.map(tsplus_module_5.unbounded(), queue => {
|
|
67
70
|
const run = tsplus_module_1.retryWhile(tsplus_module_1.tapError(tsplus_module_1.scoped(tsplus_module_1.flatMap(socket(url), ws => tsplus_module_1.zipParLeft(offer(ws, queue, log), tsplus_module_1.zipRight(waitForOpen(ws, openTimeout), send(ws, takeOutbound, log))))), _ => (isReconnect(_) ? onReconnect : tsplus_module_1.unit())), isReconnect);
|
|
68
71
|
return { run, take: queue.take() };
|
|
69
72
|
});
|
|
70
73
|
return { connect };
|
|
71
74
|
});
|
|
72
|
-
export const WS =
|
|
75
|
+
export const WS = tsplus_module_6.Tag();
|
|
73
76
|
export const LiveWS = tsplus_module_1.toLayer(make, WS);
|
|
74
77
|
//# sourceMappingURL=WS.js.map
|
package/DiscordGateway/WS.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WS.js","sourceRoot":"","sources":["../src/DiscordGateway/WS.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WS.js","sourceRoot":"","sources":["../src/DiscordGateway/WS.ts"],"names":[],"mappings":"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"}
|
package/gateway.d.ts
CHANGED
|
@@ -9,5 +9,5 @@ export * as WS from "./DiscordGateway/WS.js";
|
|
|
9
9
|
export { run as runIx } from "./Interactions/gateway.js";
|
|
10
10
|
export declare const MemoryRateLimit: import("@effect-http/client/_common").Layer<Log.Log, never, import("dfx").RateLimiter>;
|
|
11
11
|
export declare const MemoryBot: import("@effect-http/client/_common").Layer<DiscordConfig.DiscordConfig | Log.Log | import("@effect-http/client").HttpRequestExecutor, never, import("dfx").DiscordREST | import("dfx").RateLimiter | import("./DiscordGateway.js").DiscordGateway>;
|
|
12
|
-
export declare const makeLiveWithoutFetch: (config: Config.Wrap<DiscordConfig.MakeOpts
|
|
13
|
-
export declare const makeLive: (config: Config.Wrap<DiscordConfig.MakeOpts
|
|
12
|
+
export declare const makeLiveWithoutFetch: (config: Config.Wrap<DiscordConfig.MakeOpts>) => import("@effect-http/client/_common").Layer<import("@effect-http/client").HttpRequestExecutor, import("./_common.js").ConfigError, import("dfx").DiscordREST | DiscordConfig.DiscordConfig | Log.Log | import("dfx").RateLimiter | import("./DiscordGateway.js").DiscordGateway>;
|
|
13
|
+
export declare const makeLive: (config: Config.Wrap<DiscordConfig.MakeOpts>) => import("@effect-http/client/_common").Layer<never, import("./_common.js").ConfigError, import("dfx").DiscordREST | DiscordConfig.DiscordConfig | Log.Log | import("dfx").RateLimiter | import("./DiscordGateway.js").DiscordGateway>;
|
package/gateway.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as tsplus_module_1 from "@effect/io/Layer";
|
|
2
2
|
import * as tsplus_module_2 from "@effect/io/Config";
|
|
3
|
+
import * as tsplus_module_3 from "@effect/io/Effect";
|
|
3
4
|
import { LiveFetchRequestExecutor } from "@effect-http/client";
|
|
4
5
|
import { DiscordConfig, LiveDiscordREST, Log } from "dfx";
|
|
5
6
|
import { LiveDiscordGateway } from "./DiscordGateway.js";
|
|
@@ -15,13 +16,10 @@ export * as WS from "./DiscordGateway/WS.js";
|
|
|
15
16
|
export { run as runIx } from "./Interactions/gateway.js";
|
|
16
17
|
export const MemoryRateLimit = tsplus_module_1.provide(LiveRateLimiter)(LiveMemoryRateLimitStore);
|
|
17
18
|
export const MemoryBot = tsplus_module_1.provide((tsplus_module_1.merge(MemoryRateLimit)((tsplus_module_1.provideMerge(LiveDiscordGateway)(LiveDiscordREST)))))((tsplus_module_1.merge(LiveJsonDiscordWSCodec)(tsplus_module_1.merge(LiveMemoryRateLimitStore)(LiveMemoryShardStore))));
|
|
18
|
-
export const makeLiveWithoutFetch = (config
|
|
19
|
-
const LiveLog = debug ? Log.LiveLogDebug : Log.LiveLog;
|
|
20
|
-
const LiveConfig =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export const makeLive = (config, debug = false) => {
|
|
25
|
-
return tsplus_module_1.provide(makeLiveWithoutFetch(config, debug))(LiveFetchRequestExecutor);
|
|
26
|
-
};
|
|
19
|
+
export const makeLiveWithoutFetch = (config) => tsplus_module_1.unwrapEffect(tsplus_module_3.map(tsplus_module_3.map(tsplus_module_3.config(tsplus_module_2.unwrap(config)), DiscordConfig.make), config => {
|
|
20
|
+
const LiveLog = config.debug ? Log.LiveLogDebug : Log.LiveLog;
|
|
21
|
+
const LiveConfig = tsplus_module_1.succeed(DiscordConfig.DiscordConfig, config);
|
|
22
|
+
return tsplus_module_1.provideMerge(MemoryBot)(tsplus_module_1.merge(LiveConfig)(LiveLog));
|
|
23
|
+
}));
|
|
24
|
+
export const makeLive = (config) => tsplus_module_1.provide(makeLiveWithoutFetch(config))(LiveFetchRequestExecutor);
|
|
27
25
|
//# sourceMappingURL=gateway.js.map
|
package/gateway.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["src/gateway.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["src/gateway.ts"],"names":[],"mappings":";;;AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAE1E,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxE,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAC1D,OAAO,KAAK,KAAK,MAAM,2BAA2B,CAAA;AAClD,OAAO,KAAK,UAAU,MAAM,gCAAgC,CAAA;AAC5D,OAAO,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAC5C,OAAO,EAAE,GAAG,IAAI,KAAK,EAAE,MAAM,2BAA2B,CAAA;AAExD,MAAM,CAAC,MAAM,eAAe,2BAA+B,eAAe,EAA3C,wBAAwB,CAAmB,CAAA;AAE1E,MAAM,CAAC,MAAM,SAAS,2BAEpB,uBAA0C,eAAe,EAAxD,8BAAmB,kBAAkB,EAApC,eAAe,EAAsB,EAAmB,EAD1D,uBAAmD,sBAAsB,wBAAjD,wBAAwB,EAA/C,oBAAoB,GAAqD,CAChB,CAAA;AAE5D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,MAA2C,EAC3C,EAAE,CACF,6BACE,oBAAA,2CAAA,uBAAc,MAAM,CAAC,GACP,aAAa,CAAC,IAAI,CAAC,EAC1B,MAAM,CAAC,EAAE;IACZ,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAA;IAC7D,MAAM,UAAU,GAAG,wBAAc,aAAa,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;IACrE,oCAA8B,SAAS,wBAAtB,UAAU,EAApB,OAAO,GAAyB;AACzC,CAAC,CAAC,CACL,CAAA;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,MAA2C,EAAE,EAAE,yBAC1C,oBAAoB,CAAC,MAAM,CAAC,EAAxD,wBAAwB,CAAgC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dfx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.43.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@tim-smart/discord-api-docs-parser": "^0.5.2",
|
|
28
28
|
"@tsplus-types/effect__data": "0.12.2-3b576ba",
|
|
29
|
-
"@tsplus-types/effect__io": "0.25.8-
|
|
29
|
+
"@tsplus-types/effect__io": "0.25.8-11739c0",
|
|
30
30
|
"@tsplus-types/effect__stream": "0.21.1-3b576ba",
|
|
31
31
|
"@types/ws": "^8.5.4",
|
|
32
32
|
"dotenv": "^16.0.3",
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
"ws": "^8.13.0"
|
|
49
49
|
},
|
|
50
50
|
"sideEffects": false,
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "eb969e6b2d8ac1c0a5ab877898feae57728b5e3c"
|
|
52
52
|
}
|
package/src/DiscordConfig.ts
CHANGED
|
@@ -2,6 +2,7 @@ const VERSION = 10
|
|
|
2
2
|
|
|
3
3
|
export interface DiscordConfig {
|
|
4
4
|
token: ConfigSecret
|
|
5
|
+
debug: boolean
|
|
5
6
|
rest: {
|
|
6
7
|
baseUrl: string
|
|
7
8
|
globalRateLimit: {
|
|
@@ -21,12 +22,19 @@ export const DiscordConfig = Tag<DiscordConfig>()
|
|
|
21
22
|
|
|
22
23
|
export interface MakeOpts {
|
|
23
24
|
token: ConfigSecret
|
|
25
|
+
debug?: boolean
|
|
24
26
|
rest?: Partial<DiscordConfig["rest"]>
|
|
25
27
|
gateway?: Partial<DiscordConfig["gateway"]>
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
export const make = ({
|
|
30
|
+
export const make = ({
|
|
29
31
|
token,
|
|
32
|
+
debug = false,
|
|
33
|
+
rest,
|
|
34
|
+
gateway,
|
|
35
|
+
}: MakeOpts): DiscordConfig => ({
|
|
36
|
+
token,
|
|
37
|
+
debug,
|
|
30
38
|
rest: {
|
|
31
39
|
baseUrl: `https://discord.com/api/v${VERSION}`,
|
|
32
40
|
...(rest ?? {}),
|
|
@@ -6,11 +6,19 @@ import * as Identify from "./Shard/identify.js"
|
|
|
6
6
|
import * as InvalidSession from "./Shard/invalidSession.js"
|
|
7
7
|
import * as Utils from "./Shard/utils.js"
|
|
8
8
|
import { Reconnect } from "./WS.js"
|
|
9
|
+
import { Log } from "dfx/Log"
|
|
10
|
+
|
|
11
|
+
const enum Phase {
|
|
12
|
+
Connecting,
|
|
13
|
+
Handshake,
|
|
14
|
+
Connected,
|
|
15
|
+
}
|
|
9
16
|
|
|
10
17
|
export const make = Do($ => {
|
|
11
18
|
const { token, gateway } = $(DiscordConfig)
|
|
12
19
|
const limiter = $(RateLimiter)
|
|
13
20
|
const dws = $(DiscordWS)
|
|
21
|
+
const log = $(Log)
|
|
14
22
|
|
|
15
23
|
const connect = (
|
|
16
24
|
shard: [id: number, count: number],
|
|
@@ -19,7 +27,9 @@ export const make = Do($ => {
|
|
|
19
27
|
Do($ => {
|
|
20
28
|
const outboundQueue = $(Queue.unbounded<Message>())
|
|
21
29
|
const pendingQueue = $(Queue.unbounded<Message>())
|
|
22
|
-
const
|
|
30
|
+
const phase = $(Ref.make(Phase.Connecting))
|
|
31
|
+
const setPhase = (p: Phase) =>
|
|
32
|
+
phase.set(p).zipLeft(log.debug("Shard", shard, "phase", p))
|
|
23
33
|
const outbound = outboundQueue
|
|
24
34
|
.take()
|
|
25
35
|
.tap(() =>
|
|
@@ -27,14 +37,22 @@ export const make = Do($ => {
|
|
|
27
37
|
)
|
|
28
38
|
|
|
29
39
|
const send = (p: Message) =>
|
|
30
|
-
|
|
31
|
-
_
|
|
40
|
+
phase.get.flatMap(_ =>
|
|
41
|
+
_ === Phase.Connected
|
|
42
|
+
? outboundQueue.offer(p)
|
|
43
|
+
: pendingQueue.offer(p),
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
const heartbeatSend = (p: Message) =>
|
|
47
|
+
phase.get.flatMap(_ =>
|
|
48
|
+
_ !== Phase.Connecting
|
|
49
|
+
? outboundQueue.offer(p)
|
|
50
|
+
: Effect.succeed(false),
|
|
32
51
|
)
|
|
33
52
|
|
|
34
53
|
const prioritySend = (p: Message) => outboundQueue.offer(p)
|
|
35
54
|
|
|
36
|
-
const resume =
|
|
37
|
-
.set(false)
|
|
55
|
+
const resume = setPhase(Phase.Connected)
|
|
38
56
|
.zipRight(pendingQueue.takeAll())
|
|
39
57
|
.tap(_ => outboundQueue.offerAll(_)).asUnit
|
|
40
58
|
|
|
@@ -51,7 +69,7 @@ export const make = Do($ => {
|
|
|
51
69
|
),
|
|
52
70
|
),
|
|
53
71
|
)
|
|
54
|
-
.zipRight(
|
|
72
|
+
.zipRight(setPhase(Phase.Connecting))
|
|
55
73
|
|
|
56
74
|
const socket = $(dws.connect({ outbound, onReconnect }))
|
|
57
75
|
|
|
@@ -84,7 +102,12 @@ export const make = Do($ => {
|
|
|
84
102
|
const acks = $(Queue.unbounded<Discord.GatewayPayload>())
|
|
85
103
|
|
|
86
104
|
// heartbeats
|
|
87
|
-
const heartbeats = Heartbeats.send(
|
|
105
|
+
const heartbeats = Heartbeats.send(
|
|
106
|
+
hellos,
|
|
107
|
+
acks,
|
|
108
|
+
latestSequence,
|
|
109
|
+
heartbeatSend,
|
|
110
|
+
)
|
|
88
111
|
|
|
89
112
|
// identify
|
|
90
113
|
const identify = Identify.identifyOrResume(
|
|
@@ -110,7 +133,9 @@ export const make = Do($ => {
|
|
|
110
133
|
|
|
111
134
|
switch (p.op) {
|
|
112
135
|
case Discord.GatewayOpcode.HELLO:
|
|
113
|
-
effect = identify
|
|
136
|
+
effect = identify
|
|
137
|
+
.tap(prioritySend)
|
|
138
|
+
.zipPar(setPhase(Phase.Handshake).zipRight(hellos.offer(p)))
|
|
114
139
|
break
|
|
115
140
|
case Discord.GatewayOpcode.HEARTBEAT_ACK:
|
|
116
141
|
effect = acks.offer(p)
|
|
@@ -137,7 +162,6 @@ export const make = Do($ => {
|
|
|
137
162
|
|
|
138
163
|
return {
|
|
139
164
|
run,
|
|
140
|
-
connected: connecting.get,
|
|
141
165
|
send: (p: Discord.GatewayPayload) => send(p),
|
|
142
166
|
reconnect: send(Reconnect),
|
|
143
167
|
} as const
|
package/src/DiscordGateway/WS.ts
CHANGED
|
@@ -38,20 +38,26 @@ const offer = (
|
|
|
38
38
|
queue: Enqueue<WebSocket.Data>,
|
|
39
39
|
log: Log,
|
|
40
40
|
) =>
|
|
41
|
-
Effect.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
Effect.runtime<never>().flatMap(runtime =>
|
|
42
|
+
Effect.async<never, WebSocketError | WebSocketCloseError, never>(resume => {
|
|
43
|
+
const run = runtime.runFork
|
|
44
|
+
ws.addEventListener("message", message => {
|
|
45
|
+
run(
|
|
46
|
+
queue
|
|
47
|
+
.offer(message.data)
|
|
48
|
+
.zipLeft(log.debug("WS", "offer", message.data)),
|
|
49
|
+
)
|
|
50
|
+
})
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
ws.addEventListener("error", cause => {
|
|
53
|
+
resume(Effect.fail(new WebSocketError("error", cause)))
|
|
54
|
+
})
|
|
50
55
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
ws.addEventListener("close", e => {
|
|
57
|
+
resume(Effect.fail(new WebSocketCloseError(e.code, e.reason)))
|
|
58
|
+
})
|
|
59
|
+
}),
|
|
60
|
+
)
|
|
55
61
|
|
|
56
62
|
const waitForOpen = (ws: globalThis.WebSocket, timeout: Duration) =>
|
|
57
63
|
Effect.suspend(() => {
|
package/src/gateway.ts
CHANGED
|
@@ -21,18 +21,16 @@ export const MemoryBot =
|
|
|
21
21
|
|
|
22
22
|
export const makeLiveWithoutFetch = (
|
|
23
23
|
config: Config.Wrap<DiscordConfig.MakeOpts>,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
) =>
|
|
25
|
+
Layer.unwrapEffect(
|
|
26
|
+
Config.unwrap(config)
|
|
27
|
+
.config.map(DiscordConfig.make)
|
|
28
|
+
.map(config => {
|
|
29
|
+
const LiveLog = config.debug ? Log.LiveLogDebug : Log.LiveLog
|
|
30
|
+
const LiveConfig = Layer.succeed(DiscordConfig.DiscordConfig, config)
|
|
31
|
+
return LiveLog + LiveConfig > MemoryBot
|
|
32
|
+
}),
|
|
33
|
+
)
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
export const makeLive = (
|
|
34
|
-
config: Config.Wrap<DiscordConfig.MakeOpts>,
|
|
35
|
-
debug = false,
|
|
36
|
-
) => {
|
|
37
|
-
return LiveFetchRequestExecutor >> makeLiveWithoutFetch(config, debug)
|
|
38
|
-
}
|
|
35
|
+
export const makeLive = (config: Config.Wrap<DiscordConfig.MakeOpts>) =>
|
|
36
|
+
LiveFetchRequestExecutor >> makeLiveWithoutFetch(config)
|
package/src/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dfx",
|
|
3
|
+
"version": "0.43.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public",
|
|
7
|
+
"directory": "dist"
|
|
8
|
+
},
|
|
9
|
+
"description": "Effect-TS discord library",
|
|
10
|
+
"author": "Tim Smart <hello@timsmart.co>",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/tim-smart/dfx.git"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"scripts": {
|
|
17
|
+
"prepublishOnly": "make build",
|
|
18
|
+
"types": "discord-api-codegen ./discord-api-docs -l typescript -o 'imports=RestResponse|dfx/DiscordREST/types' 'endpointReturnType=RestResponse' > src/types.ts && prettier -w src/types.ts"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./index.js",
|
|
22
|
+
"./gateway": "./gateway.js",
|
|
23
|
+
"./webhooks": "./webhooks.js",
|
|
24
|
+
"./*": "./*.js"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@tim-smart/discord-api-docs-parser": "^0.5.2",
|
|
28
|
+
"@tsplus-types/effect__data": "0.12.2-3b576ba",
|
|
29
|
+
"@tsplus-types/effect__io": "0.25.8-11739c0",
|
|
30
|
+
"@tsplus-types/effect__stream": "0.21.1-3b576ba",
|
|
31
|
+
"@types/ws": "^8.5.4",
|
|
32
|
+
"dotenv": "^16.0.3",
|
|
33
|
+
"lerna": "^6.6.1",
|
|
34
|
+
"madge": "^6.0.0",
|
|
35
|
+
"typescript": "https://cdn.jsdelivr.net/npm/@tsplus/installer@0.0.171/compiler/typescript.tgz"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@effect-http/client": "^0.24.2",
|
|
39
|
+
"@effect/data": "^0.12.2",
|
|
40
|
+
"@effect/io": "~0.25.8",
|
|
41
|
+
"@effect/stream": "~0.21.1",
|
|
42
|
+
"tweetnacl": "^1.0.3"
|
|
43
|
+
},
|
|
44
|
+
"optionalDependencies": {
|
|
45
|
+
"bufferutil": "^4.0.7",
|
|
46
|
+
"isomorphic-ws": "^5.0.0",
|
|
47
|
+
"utf-8-validate": "^6.0.3",
|
|
48
|
+
"ws": "^8.13.0"
|
|
49
|
+
},
|
|
50
|
+
"sideEffects": false,
|
|
51
|
+
"gitHead": "eb969e6b2d8ac1c0a5ab877898feae57728b5e3c"
|
|
52
|
+
}
|
package/src/webhooks.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LiveFetchRequestExecutor } from "@effect-http/client"
|
|
2
2
|
import { LiveDiscordREST } from "./DiscordREST.js"
|
|
3
|
-
import { MakeConfigOpts,
|
|
3
|
+
import { MakeConfigOpts, makeConfigLayer } from "./Interactions/webhook.js"
|
|
4
4
|
import { LiveMemoryRateLimitStore, LiveRateLimiter } from "./RateLimit.js"
|
|
5
5
|
import * as DiscordConfig from "dfx/DiscordConfig"
|
|
6
6
|
import * as Log from "./Log.js"
|
|
@@ -20,22 +20,19 @@ export const MemoryREST = LiveMemoryRateLimitStore >> LiveDiscordREST
|
|
|
20
20
|
|
|
21
21
|
export const makeLiveWithoutFetch = (
|
|
22
22
|
options: Config.Wrap<DiscordConfig.MakeOpts & MakeConfigOpts>,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
) =>
|
|
24
|
+
Layer.unwrapEffect(
|
|
25
|
+
Config.unwrap(options).config.map(options => {
|
|
26
|
+
const config = DiscordConfig.make(options)
|
|
27
|
+
const LiveConfig = Layer.succeed(DiscordConfig.DiscordConfig, config)
|
|
28
|
+
const LiveWebhook = makeConfigLayer(options)
|
|
29
|
+
const LiveLog = config.debug ? Log.LiveLogDebug : Log.LiveLog
|
|
30
|
+
const LiveEnv =
|
|
31
|
+
(LiveLog + LiveConfig) >> (MemoryREST + LiveWebhook + MemoryRateLimit)
|
|
32
|
+
return LiveEnv
|
|
33
|
+
}),
|
|
34
|
+
)
|
|
35
35
|
|
|
36
36
|
export const makeLive = (
|
|
37
37
|
config: Config.Wrap<DiscordConfig.MakeOpts & MakeConfigOpts>,
|
|
38
|
-
|
|
39
|
-
) => {
|
|
40
|
-
return LiveFetchRequestExecutor >> makeLiveWithoutFetch(config, debug)
|
|
41
|
-
}
|
|
38
|
+
) => LiveFetchRequestExecutor >> makeLiveWithoutFetch(config)
|
package/webhooks.d.ts
CHANGED
|
@@ -5,5 +5,5 @@ import * as Log from "./Log.js";
|
|
|
5
5
|
export { BadWebhookSignature, makeConfigLayer, makeHandler, makeSimpleHandler, WebhookConfig, WebhookParseError, } from "./Interactions/webhook.js";
|
|
6
6
|
export declare const MemoryRateLimit: import("@effect-http/client/_common").Layer<Log.Log, never, import("./RateLimit.js").RateLimiter>;
|
|
7
7
|
export declare const MemoryREST: import("@effect-http/client/_common").Layer<DiscordConfig.DiscordConfig | Log.Log | import("@effect-http/client").HttpRequestExecutor, never, import("./DiscordREST.js").DiscordREST>;
|
|
8
|
-
export declare const makeLiveWithoutFetch: (options: Config.Wrap<DiscordConfig.MakeOpts & MakeConfigOpts
|
|
9
|
-
export declare const makeLive: (config: Config.Wrap<DiscordConfig.MakeOpts & MakeConfigOpts
|
|
8
|
+
export declare const makeLiveWithoutFetch: (options: Config.Wrap<DiscordConfig.MakeOpts & MakeConfigOpts>) => import("@effect-http/client/_common").Layer<import("@effect-http/client").HttpRequestExecutor, import("./_common.js").ConfigError, import("./DiscordREST.js").DiscordREST | import("./RateLimit.js").RateLimiter | import("./Interactions/webhook.js").WebhookConfig>;
|
|
9
|
+
export declare const makeLive: (config: Config.Wrap<DiscordConfig.MakeOpts & MakeConfigOpts>) => import("@effect-http/client/_common").Layer<never, import("./_common.js").ConfigError, import("./DiscordREST.js").DiscordREST | import("./RateLimit.js").RateLimiter | import("./Interactions/webhook.js").WebhookConfig>;
|
package/webhooks.js
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import * as tsplus_module_1 from "@effect/io/Layer";
|
|
2
2
|
import * as tsplus_module_2 from "@effect/io/Config";
|
|
3
|
+
import * as tsplus_module_3 from "@effect/io/Effect";
|
|
3
4
|
import { LiveFetchRequestExecutor } from "@effect-http/client";
|
|
4
5
|
import { LiveDiscordREST } from "./DiscordREST.js";
|
|
5
|
-
import {
|
|
6
|
+
import { makeConfigLayer } from "./Interactions/webhook.js";
|
|
6
7
|
import { LiveMemoryRateLimitStore, LiveRateLimiter } from "./RateLimit.js";
|
|
7
8
|
import * as DiscordConfig from "dfx/DiscordConfig";
|
|
8
9
|
import * as Log from "./Log.js";
|
|
9
10
|
export { BadWebhookSignature, makeConfigLayer, makeHandler, makeSimpleHandler, WebhookConfig, WebhookParseError, } from "./Interactions/webhook.js";
|
|
10
11
|
export const MemoryRateLimit = tsplus_module_1.provide(LiveRateLimiter)(LiveMemoryRateLimitStore);
|
|
11
12
|
export const MemoryREST = tsplus_module_1.provide(LiveDiscordREST)(LiveMemoryRateLimitStore);
|
|
12
|
-
export const makeLiveWithoutFetch = (options
|
|
13
|
-
const config =
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
13
|
+
export const makeLiveWithoutFetch = (options) => tsplus_module_1.unwrapEffect(tsplus_module_3.map(tsplus_module_3.config(tsplus_module_2.unwrap(options)), options => {
|
|
14
|
+
const config = DiscordConfig.make(options);
|
|
15
|
+
const LiveConfig = tsplus_module_1.succeed(DiscordConfig.DiscordConfig, config);
|
|
16
|
+
const LiveWebhook = makeConfigLayer(options);
|
|
17
|
+
const LiveLog = config.debug ? Log.LiveLogDebug : Log.LiveLog;
|
|
17
18
|
const LiveEnv = tsplus_module_1.provide((tsplus_module_1.merge(MemoryRateLimit)(tsplus_module_1.merge(LiveWebhook)(MemoryREST))))((tsplus_module_1.merge(LiveConfig)(LiveLog)));
|
|
18
19
|
return LiveEnv;
|
|
19
|
-
};
|
|
20
|
-
export const makeLive = (config
|
|
21
|
-
return tsplus_module_1.provide(makeLiveWithoutFetch(config, debug))(LiveFetchRequestExecutor);
|
|
22
|
-
};
|
|
20
|
+
}));
|
|
21
|
+
export const makeLive = (config) => tsplus_module_1.provide(makeLiveWithoutFetch(config))(LiveFetchRequestExecutor);
|
|
23
22
|
//# sourceMappingURL=webhooks.js.map
|
package/webhooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["src/webhooks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["src/webhooks.ts"],"names":[],"mappings":";;;AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAkB,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3E,OAAO,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC1E,OAAO,KAAK,aAAa,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAE/B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,iBAAiB,GAClB,MAAM,2BAA2B,CAAA;AAElC,MAAM,CAAC,MAAM,eAAe,2BAA+B,eAAe,EAA3C,wBAAwB,CAAmB,CAAA;AAE1E,MAAM,CAAC,MAAM,UAAU,2BAA+B,eAAe,EAA3C,wBAAwB,CAAmB,CAAA;AAErE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,OAA6D,EAC7D,EAAE,CACF,6BACE,2CAAA,uBAAc,OAAO,CAAC,GAAY,OAAO,CAAC,EAAE;IAC1C,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC1C,MAAM,UAAU,GAAG,wBAAc,aAAa,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;IACrE,MAAM,WAAW,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAA;IAC7D,MAAM,OAAO,2BACe,uBAA4B,eAAe,wBAA7B,WAAW,EAAxB,UAAU,GAAiC,EAAtE,uBAAW,UAAU,EAApB,OAAO,EAAc,CAAgD,CAAA;IACxE,OAAO,OAAO,CAAA;AAChB,CAAC,CAAC,CACH,CAAA;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,MAA4D,EAC5D,EAAE,yBAA6B,oBAAoB,CAAC,MAAM,CAAC,EAAxD,wBAAwB,CAAgC,CAAA"}
|