@seedcord/core 0.12.0-next.0 → 0.12.0-next.3
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/README.md +3 -3
- package/dist/{Bus-W1K-uMeO.mjs → Bus-VJw-QpoY.mjs} +110 -54
- package/dist/Bus-VJw-QpoY.mjs.map +1 -0
- package/dist/{CoordinatedShutdown-BVtNNSsF.d.mts → CoordinatedShutdown-fPKLWjc5.d.mts} +2 -2
- package/dist/{CoordinatedStartup-DA3gW8op.mjs → CoordinatedStartup-Zw_Lk7Zk.mjs} +3 -3
- package/dist/{CoordinatedStartup-DA3gW8op.mjs.map → CoordinatedStartup-Zw_Lk7Zk.mjs.map} +1 -1
- package/dist/HmrModuleHandler-Btgu8r96.mjs +165 -0
- package/dist/HmrModuleHandler-Btgu8r96.mjs.map +1 -0
- package/dist/{PluginHost-DWBgBS6Q.d.mts → PluginHost-DFnkIldj.d.mts} +10 -9
- package/dist/{PluginHost-CYe-UVpp.mjs → PluginHost-DTtxWRiL.mjs} +4 -4
- package/dist/PluginHost-DTtxWRiL.mjs.map +1 -0
- package/dist/{PluginLifecycle-DdwRzcDj.mjs → PluginLifecycle-hx5zUc-P.mjs} +4 -4
- package/dist/PluginLifecycle-hx5zUc-P.mjs.map +1 -0
- package/dist/{ServerHost-whpI0h4d.d.mts → ServerHost-B5o3ScCF.d.mts} +3 -3
- package/dist/{ServerHost-DHg-Y2_q.mjs → ServerHost-CDaEDR4C.mjs} +4 -4
- package/dist/{ServerHost-DHg-Y2_q.mjs.map → ServerHost-CDaEDR4C.mjs.map} +1 -1
- package/dist/hmr.index.d.mts +20 -20
- package/dist/hmr.index.mjs +1 -1
- package/dist/{index-Boo33hh3.d.mts → index-DGHng1IN.d.mts} +108 -193
- package/dist/index.d.mts +221 -74
- package/dist/index.mjs +222 -103
- package/dist/index.mjs.map +1 -1
- package/dist/internal.index.d.mts +204 -82
- package/dist/internal.index.mjs +572 -73
- package/dist/internal.index.mjs.map +1 -1
- package/dist/node-internal.index.d.mts +4 -3
- package/dist/node-internal.index.mjs +3 -3
- package/dist/node.index.d.mts +2 -2
- package/dist/node.index.mjs +4 -4
- package/dist/{phases-Dojnr-ng.d.mts → phases-C2QCSqRu.d.mts} +60 -50
- package/dist/plugin.index.d.mts +1 -1
- package/dist/plugin.index.mjs +1 -1
- package/dist/{subscribers-D4_HZcgw.mjs → subscribers-CGuVjbrg.mjs} +139 -253
- package/dist/subscribers-CGuVjbrg.mjs.map +1 -0
- package/package.json +10 -9
- package/dist/Bus-W1K-uMeO.mjs.map +0 -1
- package/dist/HmrModuleHandler-BMD7dg8N.mjs +0 -162
- package/dist/HmrModuleHandler-BMD7dg8N.mjs.map +0 -1
- package/dist/PluginHost-CYe-UVpp.mjs.map +0 -1
- package/dist/PluginLifecycle-DdwRzcDj.mjs.map +0 -1
- package/dist/subscribers-D4_HZcgw.mjs.map +0 -1
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as InteractionRouteKeys, C as CommandMetadataKey, D as InteractionKind, N as BuilderComponent, O as InteractionMetadataKey, S as assertUniqueKeys, k as InteractionMiddlewareMetadataKey, x as PublishDefault } from "./Bus-VJw-QpoY.mjs";
|
|
2
2
|
import "reflect-metadata";
|
|
3
3
|
import { CustomId, decodeFor } from "@seedcord/custom-id";
|
|
4
4
|
import { TextDisplayBuilder } from "@discordjs/builders";
|
|
5
|
-
import { ApplicationCommandType,
|
|
5
|
+
import { ApplicationCommandType, Routes } from "discord-api-types/v10";
|
|
6
6
|
import { SeedcordErrorCode, paint } from "@seedcord/errors";
|
|
7
7
|
import { SeedcordError, SeedcordTypeError } from "@seedcord/errors/internal";
|
|
8
8
|
import { Logger } from "@seedcord/logger";
|
|
9
9
|
import { asError, isStringArray, pluralize, routeLeavesOf } from "@seedcord/utils/internal";
|
|
10
|
-
import {
|
|
10
|
+
import { toEpochSeconds } from "@seedcord/utils";
|
|
11
11
|
|
|
12
|
+
//#region src/stops/NoticeCard.ts
|
|
13
|
+
var NoticeCard = class extends BuilderComponent {
|
|
14
|
+
constructor(description, title = "Cannot Proceed") {
|
|
15
|
+
super("container");
|
|
16
|
+
this.instance.addTextDisplayComponents(new TextDisplayBuilder().setContent(`### ${title}\n${description}`));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
12
21
|
//#region src/stops/Notice.ts
|
|
13
22
|
/**
|
|
14
23
|
* Base class for a user-facing refusal or a reported fault.
|
|
@@ -38,7 +47,7 @@ import { prettify, toEpochSeconds } from "@seedcord/utils";
|
|
|
38
47
|
* super(`balance ${balance} is below the cost`);
|
|
39
48
|
* }
|
|
40
49
|
*
|
|
41
|
-
* render(_ctx: RenderContext): ReplyResponse {
|
|
50
|
+
* override render(_ctx: RenderContext): ReplyResponse {
|
|
42
51
|
* return { components: [new TooPoorCard(this.balance).component] };
|
|
43
52
|
* }
|
|
44
53
|
* }
|
|
@@ -63,7 +72,7 @@ var Notice = class extends Error {
|
|
|
63
72
|
*/
|
|
64
73
|
ephemeral = true;
|
|
65
74
|
/**
|
|
66
|
-
* A short one-line reason. When every
|
|
75
|
+
* A short one-line reason. When every gate in an {@link or} refuses and each one sets this, `or`
|
|
67
76
|
* throws a refusal listing them under `You need to meet at least one of these:`. Write a verb phrase that
|
|
68
77
|
* finishes that line, for example, "be the bot owner".
|
|
69
78
|
*/
|
|
@@ -73,14 +82,13 @@ var Notice = class extends Error {
|
|
|
73
82
|
this.name = new.target.name;
|
|
74
83
|
Error.captureStackTrace(this, this.constructor);
|
|
75
84
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
this.instance.addTextDisplayComponents(new TextDisplayBuilder().setContent(`### ${title}\n${description}`));
|
|
85
|
+
/**
|
|
86
|
+
* Builds what the user sees. Called fresh each time the denial is shown, so the builders are new
|
|
87
|
+
* and the bot color resolves at render time. By default it returns seedcord's refusal card with the message as
|
|
88
|
+
* its text. Override it to show your own components.
|
|
89
|
+
*/
|
|
90
|
+
render(_ctx) {
|
|
91
|
+
return { components: [new NoticeCard(this.message).component] };
|
|
84
92
|
}
|
|
85
93
|
};
|
|
86
94
|
|
|
@@ -309,7 +317,7 @@ const KIND_LABELS = {
|
|
|
309
317
|
[ApplicationCommandType.PrimaryEntryPoint]: "entry point command"
|
|
310
318
|
};
|
|
311
319
|
function multiGuildWarning({ name, type }) {
|
|
312
|
-
const consequence = type === ApplicationCommandType.ChatInput ? "
|
|
320
|
+
const consequence = type === ApplicationCommandType.ChatInput ? "so its mention stays plain text (not clickable)" : "so its id stays unset";
|
|
313
321
|
return `${paint.sky.bold(name)} is deployed to multiple guilds, ${consequence}.`;
|
|
314
322
|
}
|
|
315
323
|
function warnLinks(logger, { multiGuild, notInCode }) {
|
|
@@ -390,16 +398,21 @@ function interactionRoutesOf(constructor) {
|
|
|
390
398
|
}
|
|
391
399
|
return pairs;
|
|
392
400
|
}
|
|
393
|
-
function
|
|
401
|
+
function routeDecoratorOf(kind) {
|
|
402
|
+
return `@${kind.charAt(0).toUpperCase()}${kind.slice(1)}Route`;
|
|
403
|
+
}
|
|
404
|
+
function storeInteractionRoute(route, routes, constructor, fix = "Remove the repeat.") {
|
|
394
405
|
const key = InteractionRouteKeys[route];
|
|
395
406
|
const saved = Reflect.getMetadata(key, constructor);
|
|
396
407
|
const existing = isStringArray(saved) ? saved : [];
|
|
397
408
|
const toStore = typeof routes === "string" ? [routes] : routes;
|
|
409
|
+
const own = Reflect.getOwnMetadata(key, constructor);
|
|
410
|
+
assertUniqueKeys(routeDecoratorOf(route), constructor, [...isStringArray(own) ? own : [], ...toStore], fix);
|
|
398
411
|
Reflect.defineMetadata(key, [...existing, ...toStore], constructor);
|
|
399
412
|
Reflect.defineMetadata(InteractionMetadataKey, true, constructor);
|
|
400
413
|
}
|
|
401
414
|
function storeComponentRoute(route, defs, constructor) {
|
|
402
|
-
storeInteractionRoute(route, defs.map((def) => def.prefix), constructor);
|
|
415
|
+
storeInteractionRoute(route, defs.map((def) => def.prefix), constructor, "Remove the repeat, or give each customId its own prefix.");
|
|
403
416
|
Reflect.defineMetadata(ComponentDefsKey, defs, constructor);
|
|
404
417
|
}
|
|
405
418
|
function contextMenuRouteOf(kind) {
|
|
@@ -484,7 +497,7 @@ const ILLEGAL = {
|
|
|
484
497
|
update: {
|
|
485
498
|
"deferred-reply": {
|
|
486
499
|
reason: "this interaction was deferred as a reply",
|
|
487
|
-
alternative: "
|
|
500
|
+
alternative: "update() only rewrites a source message. Use edit() to fill the placeholder."
|
|
488
501
|
},
|
|
489
502
|
replied: {
|
|
490
503
|
reason: "this interaction was already replied to",
|
|
@@ -497,11 +510,11 @@ const ILLEGAL = {
|
|
|
497
510
|
} },
|
|
498
511
|
edit: { unacked: {
|
|
499
512
|
reason: "nothing has been sent yet",
|
|
500
|
-
alternative: "Send with reply() or defer() first,
|
|
513
|
+
alternative: "Send with reply() or defer() first. After that, edit() rewrites it."
|
|
501
514
|
} },
|
|
502
515
|
delete: { unacked: {
|
|
503
516
|
reason: "nothing has been sent yet",
|
|
504
|
-
alternative: "Acknowledge first with reply() or defer(),
|
|
517
|
+
alternative: "Acknowledge first with reply() or defer(). After that, delete() removes the reply."
|
|
505
518
|
} },
|
|
506
519
|
showModal: {
|
|
507
520
|
"deferred-reply": showModalReason,
|
|
@@ -540,12 +553,15 @@ var AckTrace = class extends Error {
|
|
|
540
553
|
};
|
|
541
554
|
|
|
542
555
|
//#endregion
|
|
543
|
-
//#region src/
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
return replyLogger;
|
|
556
|
+
//#region src/miscellaneous/lazyLogger.ts
|
|
557
|
+
function lazyLogger(label, options) {
|
|
558
|
+
let logger;
|
|
559
|
+
return () => logger ??= new Logger(label, options);
|
|
548
560
|
}
|
|
561
|
+
|
|
562
|
+
//#endregion
|
|
563
|
+
//#region src/reply/responseReport.ts
|
|
564
|
+
const logger = lazyLogger("Reply", { channel: "interactions" });
|
|
549
565
|
/** @internal */
|
|
550
566
|
function publishResponse(telemetry, report) {
|
|
551
567
|
const durationMs = performance.now() - report.startedAt;
|
|
@@ -725,122 +741,33 @@ function serializeReply(response, routeId) {
|
|
|
725
741
|
};
|
|
726
742
|
}
|
|
727
743
|
|
|
728
|
-
//#endregion
|
|
729
|
-
//#region src/gates/Gate.ts
|
|
730
|
-
/**
|
|
731
|
-
* Builds a {@link Gate} from a check. The check refuses by throwing a Notice or a Silence and passes
|
|
732
|
-
* by returning. The required context is inferred from `ctx`, so annotate it as narrowly as the fields
|
|
733
|
-
* the check reads. No annotation defaults to {@link GateContextBase}, an agnostic gate that fits every
|
|
734
|
-
* handler.
|
|
735
|
-
*
|
|
736
|
-
* @typeParam Name - The gate's name, captured as a literal for mismatch errors.
|
|
737
|
-
* @typeParam Ctx - The context the check reads, inferred from the `ctx` annotation.
|
|
738
|
-
*
|
|
739
|
-
* @param name - The gate's name, used in mismatch errors.
|
|
740
|
-
* @param fn - The check, which refuses by throwing a Notice or a Silence and passes by returning.
|
|
741
|
-
*
|
|
742
|
-
* @see {@link defineEffectGate}
|
|
743
|
-
* @see the `@Gated` decorator from your transport package
|
|
744
|
-
*
|
|
745
|
-
* @example
|
|
746
|
-
* ```ts
|
|
747
|
-
* // a gate factory that takes its own option and closes over it
|
|
748
|
-
* function MinRoles(min: number): Gate<GateContextBase, 'MinRoles'> {
|
|
749
|
-
* return defineGate('MinRoles', (ctx) => {
|
|
750
|
-
* if (ctx.memberRoleIds.length < min) throw new NotEnoughRoles(min);
|
|
751
|
-
* });
|
|
752
|
-
* }
|
|
753
|
-
* ```
|
|
754
|
-
*
|
|
755
|
-
* @example
|
|
756
|
-
* ```ts
|
|
757
|
-
* // agnostic gate (no ctx annotation): fits any handler
|
|
758
|
-
* const Owner = defineGate('owner', (ctx) => {
|
|
759
|
-
* if (!ctx.userId) throw new NotOwner();
|
|
760
|
-
* });
|
|
761
|
-
* ```
|
|
762
|
-
*/
|
|
763
|
-
function defineGate(name, fn) {
|
|
764
|
-
return {
|
|
765
|
-
name,
|
|
766
|
-
check: async (ctx) => fn(ctx)
|
|
767
|
-
};
|
|
768
|
-
}
|
|
769
|
-
/**
|
|
770
|
-
* Builds an {@link EffectGate} from a `check` and a `commit`. `check` peeks and refuses by throwing, and
|
|
771
|
-
* `commit` applies the side effect, running only once the whole gate set passes so a later refusal never
|
|
772
|
-
* commits. In an `or`, a refusing arm's queued commit is rolled back. This is how {@link Cooldown} peeks
|
|
773
|
-
* in `check` and charges the slot in `commit`.
|
|
774
|
-
*
|
|
775
|
-
* @typeParam Name - The gate's literal name, used to name a mismatch error.
|
|
776
|
-
* @typeParam Ctx - The context both `check` and `commit` read, inferred from the `ctx` annotation.
|
|
777
|
-
*
|
|
778
|
-
* @param name - The gate's name, used in mismatch errors.
|
|
779
|
-
* @param check - Peeks and refuses by throwing, without applying the side effect.
|
|
780
|
-
* @param commit - Applies the side effect, running only after the whole gate set passes.
|
|
781
|
-
*
|
|
782
|
-
* @see {@link defineGate}
|
|
783
|
-
* @see the `@Gated` decorator from your transport package
|
|
784
|
-
* @see {@link Cooldown}
|
|
785
|
-
*
|
|
786
|
-
* @example
|
|
787
|
-
* ```ts
|
|
788
|
-
* // an effect-gate factory that takes its own limit and closes over it
|
|
789
|
-
* function UsesPerDay(max: number): EffectGate<GateContextBase, 'UsesPerDay'> {
|
|
790
|
-
* return defineEffectGate(
|
|
791
|
-
* 'UsesPerDay',
|
|
792
|
-
* (ctx) => {
|
|
793
|
-
* // peek and refuse by throwing. do not mutate yet
|
|
794
|
-
* if (usedToday(ctx.userId) >= max) throw new OutOfUsesNotice(max);
|
|
795
|
-
* },
|
|
796
|
-
* (ctx) => {
|
|
797
|
-
* // runs only after the whole gate set passes
|
|
798
|
-
* recordUse(ctx.userId);
|
|
799
|
-
* }
|
|
800
|
-
* );
|
|
801
|
-
* }
|
|
802
|
-
* ```
|
|
803
|
-
*/
|
|
804
|
-
function defineEffectGate(name, check, commit) {
|
|
805
|
-
return {
|
|
806
|
-
name,
|
|
807
|
-
check: async (ctx) => check(ctx),
|
|
808
|
-
commit: async (ctx) => commit(ctx)
|
|
809
|
-
};
|
|
810
|
-
}
|
|
811
|
-
|
|
812
744
|
//#endregion
|
|
813
745
|
//#region src/notices/index.ts
|
|
814
|
-
var
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
}
|
|
818
|
-
};
|
|
819
|
-
var NotOwner = class extends GateNotice {
|
|
820
|
-
constructor(message = "Only the bot owner can use this.") {
|
|
821
|
-
super(message);
|
|
746
|
+
var NotOwner = class extends Notice {
|
|
747
|
+
constructor() {
|
|
748
|
+
super("Only the bot owner can use this.");
|
|
822
749
|
this.summary = "be the bot owner";
|
|
823
750
|
}
|
|
824
751
|
};
|
|
825
|
-
var NotInGuild = class extends
|
|
826
|
-
constructor(
|
|
827
|
-
super(
|
|
752
|
+
var NotInGuild = class extends Notice {
|
|
753
|
+
constructor() {
|
|
754
|
+
super("This can only be used in a server.");
|
|
828
755
|
this.summary = "be in a server";
|
|
829
756
|
}
|
|
830
757
|
};
|
|
831
|
-
var NotInDm = class extends
|
|
832
|
-
constructor(
|
|
833
|
-
super(message);
|
|
758
|
+
var NotInDm = class extends Notice {
|
|
759
|
+
constructor() {
|
|
760
|
+
super("This can only be used in a direct message.");
|
|
834
761
|
this.summary = "be in a direct message";
|
|
835
762
|
}
|
|
836
763
|
};
|
|
837
764
|
function retryAt(resetAt) {
|
|
838
765
|
return `<t:${toEpochSeconds(resetAt)}:R>`;
|
|
839
766
|
}
|
|
840
|
-
var OnCooldown = class extends
|
|
767
|
+
var OnCooldown = class extends Notice {
|
|
841
768
|
resetAt;
|
|
842
|
-
constructor(resetAt
|
|
843
|
-
super(
|
|
769
|
+
constructor(resetAt) {
|
|
770
|
+
super(`You are doing that too fast. Try again ${retryAt(resetAt)}.`);
|
|
844
771
|
this.resetAt = resetAt;
|
|
845
772
|
this.summary = `try again ${retryAt(resetAt)}`;
|
|
846
773
|
}
|
|
@@ -864,45 +791,98 @@ var NeedsAny = class extends Notice {
|
|
|
864
791
|
return { components: [new NoticeCard(`You need to meet at least one of these:\n${bullets}`).component] };
|
|
865
792
|
}
|
|
866
793
|
};
|
|
867
|
-
var MissingRole = class extends
|
|
868
|
-
constructor(
|
|
869
|
-
super(
|
|
870
|
-
this.summary =
|
|
794
|
+
var MissingRole = class extends Notice {
|
|
795
|
+
constructor(roleId) {
|
|
796
|
+
super(`You need the <@&${roleId}> role to use this.`);
|
|
797
|
+
this.summary = `hold the <@&${roleId}> role`;
|
|
871
798
|
}
|
|
872
799
|
};
|
|
873
|
-
var
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
this.
|
|
800
|
+
var PermissionsUnresolved = class extends Notice {
|
|
801
|
+
constructor() {
|
|
802
|
+
super("Your server member data could not be resolved. Try again.");
|
|
803
|
+
}
|
|
804
|
+
};
|
|
805
|
+
var PermissionListNotice = class extends Notice {
|
|
806
|
+
permissions;
|
|
807
|
+
lead;
|
|
808
|
+
constructor(message, subject, permissions, wording) {
|
|
809
|
+
super(message);
|
|
810
|
+
this.permissions = permissions;
|
|
811
|
+
const [prefix, words] = subject === null ? ["", wording.caller] : [`${subject} `, wording.subject];
|
|
812
|
+
this.lead = `${prefix}${words.lead}`;
|
|
813
|
+
this.summary = `${prefix}${words.summary} ${permissions.join(", ")}`;
|
|
884
814
|
}
|
|
885
815
|
render() {
|
|
886
|
-
const bullets = this.
|
|
887
|
-
|
|
888
|
-
return { components: [new NoticeCard(`${lead}\n${bullets}`).component] };
|
|
816
|
+
const bullets = this.permissions.map((perm) => `• ${perm}`).join("\n");
|
|
817
|
+
return { components: [new NoticeCard(`${this.lead}\n${bullets}`).component] };
|
|
889
818
|
}
|
|
890
819
|
};
|
|
891
|
-
var
|
|
892
|
-
subject
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
820
|
+
var MissingPermissions = class extends PermissionListNotice {
|
|
821
|
+
constructor(subject, permissions) {
|
|
822
|
+
super("A required permission is missing.", subject, permissions, {
|
|
823
|
+
caller: {
|
|
824
|
+
lead: "You are missing the following permission entries:",
|
|
825
|
+
summary: "hold"
|
|
826
|
+
},
|
|
827
|
+
subject: {
|
|
828
|
+
lead: "is missing the following permission entries:",
|
|
829
|
+
summary: "needs"
|
|
830
|
+
}
|
|
831
|
+
});
|
|
901
832
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
833
|
+
};
|
|
834
|
+
var HasPresentPermissions = class extends PermissionListNotice {
|
|
835
|
+
constructor(subject, permissions) {
|
|
836
|
+
super("A refused permission is held.", subject, permissions, {
|
|
837
|
+
caller: {
|
|
838
|
+
lead: "You hold permissions that aren't allowed here:",
|
|
839
|
+
summary: "not hold"
|
|
840
|
+
},
|
|
841
|
+
subject: {
|
|
842
|
+
lead: "holds permissions that aren't allowed here:",
|
|
843
|
+
summary: "must not hold"
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
|
|
849
|
+
//#endregion
|
|
850
|
+
//#region src/stops/Fault.ts
|
|
851
|
+
/**
|
|
852
|
+
* A generic fault you throw after catching an error you do not have a specific message for.
|
|
853
|
+
*
|
|
854
|
+
* The user sees a fixed generic reply with the tracking uuid, never the cause. `report` defaults to
|
|
855
|
+
* `true`, so the framework logs it and publishes it to the `handledException` bus. Pass `report: false`
|
|
856
|
+
* to show the generic reply without the bus publish. The original error is stored as the standard
|
|
857
|
+
* `cause`, so the real stack reaches the webhook. When the user should see a real message for a fault,
|
|
858
|
+
* subclass {@link Notice} and write your own `render` instead.
|
|
859
|
+
*
|
|
860
|
+
* The framework also renders this for an unhandled throw, where it points the user at
|
|
861
|
+
* `ctx.developerUsername`.
|
|
862
|
+
*
|
|
863
|
+
* @example
|
|
864
|
+
* ```ts
|
|
865
|
+
* import { Fault } from '@seedcord/gateway';
|
|
866
|
+
*
|
|
867
|
+
* try {
|
|
868
|
+
* await db.write(record);
|
|
869
|
+
* } catch (cause) {
|
|
870
|
+
* // user sees the generic reply with the uuid, and the real error rides along as cause for the webhook
|
|
871
|
+
* throw new Fault({ cause });
|
|
872
|
+
*
|
|
873
|
+
* // pass report: false to show the same reply without publishing to the handledException bus
|
|
874
|
+
* // throw new Fault({ cause, report: false });
|
|
875
|
+
* }
|
|
876
|
+
* ```
|
|
877
|
+
*/
|
|
878
|
+
var Fault = class extends Notice {
|
|
879
|
+
constructor(options) {
|
|
880
|
+
super("A fault occurred", options?.cause === void 0 ? void 0 : { cause: options.cause });
|
|
881
|
+
this.report = options?.report ?? true;
|
|
882
|
+
}
|
|
883
|
+
render(ctx) {
|
|
884
|
+
const contact = ctx.developerUsername ?? "the developer";
|
|
885
|
+
return { components: [new NoticeCard(`Something went wrong. Please reach out to ${contact} with a way to reproduce the error and the following:\n### UUID: \`${ctx.uuid}\``, "Error").component] };
|
|
906
886
|
}
|
|
907
887
|
};
|
|
908
888
|
|
|
@@ -938,100 +918,6 @@ function rollbackCommits(ctx, mark) {
|
|
|
938
918
|
if (queue && queue.length > mark) queue.length = mark;
|
|
939
919
|
}
|
|
940
920
|
|
|
941
|
-
//#endregion
|
|
942
|
-
//#region src/gates/catalog/options.ts
|
|
943
|
-
function pickNotice(options, makeDefault) {
|
|
944
|
-
return options?.notice ?? makeDefault(options?.message);
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
//#endregion
|
|
948
|
-
//#region src/permissions/bits.ts
|
|
949
|
-
const PermissionNames = new Map(Object.entries(PermissionFlagsBits).map(([key, bit]) => [bit, prettify(key)]));
|
|
950
|
-
const ADMINISTRATOR = PermissionFlagsBits.Administrator;
|
|
951
|
-
function nameOf(bit) {
|
|
952
|
-
return PermissionNames.get(bit) ?? String(bit);
|
|
953
|
-
}
|
|
954
|
-
function holds(held, bit) {
|
|
955
|
-
return (held & ADMINISTRATOR) === ADMINISTRATOR || (held & bit) === bit;
|
|
956
|
-
}
|
|
957
|
-
/** @internal */
|
|
958
|
-
function hasAll(held, scope) {
|
|
959
|
-
return scope.every((bit) => holds(held, bit));
|
|
960
|
-
}
|
|
961
|
-
/** @internal only reached once hasAll failed, so the administrator bit is absent */
|
|
962
|
-
function missingNames(held, scope) {
|
|
963
|
-
return scope.reduce((names, bit) => {
|
|
964
|
-
if ((held & bit) !== bit) names.push(nameOf(bit));
|
|
965
|
-
return names;
|
|
966
|
-
}, []);
|
|
967
|
-
}
|
|
968
|
-
/** @internal */
|
|
969
|
-
function presentNames(held, scope) {
|
|
970
|
-
return scope.reduce((names, bit) => {
|
|
971
|
-
if (holds(held, bit)) names.push(nameOf(bit));
|
|
972
|
-
return names;
|
|
973
|
-
}, []);
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
//#endregion
|
|
977
|
-
//#region src/gates/catalog/permissions.ts
|
|
978
|
-
const MEMBER_CHECK = {
|
|
979
|
-
unresolved: "Your server member data could not be resolved. Try again.",
|
|
980
|
-
subject: null
|
|
981
|
-
};
|
|
982
|
-
const BOT_CHECK = {
|
|
983
|
-
unresolved: "The bot's permissions could not be resolved. Try again.",
|
|
984
|
-
subject: "The bot"
|
|
985
|
-
};
|
|
986
|
-
function refusePermissions(held, scope, options, guildId, kind) {
|
|
987
|
-
if (held === null) throw pickNotice(options?.notInGuild, (message) => new NotInGuild(message ?? (guildId ? kind.unresolved : void 0)));
|
|
988
|
-
if (hasAll(held, scope)) return;
|
|
989
|
-
throw pickNotice(options?.missing, (message) => new MissingPermissions(message, kind.subject, missingNames(held, scope)));
|
|
990
|
-
}
|
|
991
|
-
function RequirePermissions(scope, options) {
|
|
992
|
-
if (options?.in === "guild") return defineGate("RequirePermissions", (ctx) => {
|
|
993
|
-
refusePermissions(ctx.memberGuildPermissions, scope, options, ctx.guildId, MEMBER_CHECK);
|
|
994
|
-
});
|
|
995
|
-
return defineGate("RequirePermissions", (ctx) => {
|
|
996
|
-
refusePermissions(ctx.memberPermissions, scope, options, ctx.guildId, MEMBER_CHECK);
|
|
997
|
-
});
|
|
998
|
-
}
|
|
999
|
-
function RequireBotPermissions(scope, options) {
|
|
1000
|
-
if (options?.in === "guild") return defineGate("RequireBotPermissions", (ctx) => {
|
|
1001
|
-
refusePermissions(ctx.appGuildPermissions, scope, options, ctx.guildId, BOT_CHECK);
|
|
1002
|
-
});
|
|
1003
|
-
return defineGate("RequireBotPermissions", (ctx) => {
|
|
1004
|
-
refusePermissions(ctx.appPermissions, scope, options, ctx.guildId, BOT_CHECK);
|
|
1005
|
-
});
|
|
1006
|
-
}
|
|
1007
|
-
/**
|
|
1008
|
-
* Requires the caller to hold `roleId`, read from the member's role ids. Refuses outside a guild first,
|
|
1009
|
-
* then when the role is missing. Roles are guild-global, so there is no scope dimension.
|
|
1010
|
-
*
|
|
1011
|
-
* @param roleId - The role snowflake the caller must hold.
|
|
1012
|
-
* @param options - Override each refusal, the outside-guild one with `notInGuild` and the missing-role one with `missingRole`.
|
|
1013
|
-
*
|
|
1014
|
-
* @see the `@Gated` decorator from your transport package
|
|
1015
|
-
*
|
|
1016
|
-
* @example
|
|
1017
|
-
* ```ts
|
|
1018
|
-
* \@Gated(RequireRole('123456789012345678'))
|
|
1019
|
-
* \@SlashRoute('vip')
|
|
1020
|
-
* class VipHandler extends SlashHandler<'vip'> {
|
|
1021
|
-
* async execute() {
|
|
1022
|
-
* // ...
|
|
1023
|
-
* }
|
|
1024
|
-
* }
|
|
1025
|
-
* ```
|
|
1026
|
-
*/
|
|
1027
|
-
function RequireRole(roleId, options) {
|
|
1028
|
-
return defineGate("RequireRole", (ctx) => {
|
|
1029
|
-
if (!ctx.guildId) throw pickNotice(options?.notInGuild, (message) => new NotInGuild(message));
|
|
1030
|
-
if (ctx.memberRoleIds.includes(roleId)) return;
|
|
1031
|
-
throw pickNotice(options?.missingRole, (message) => new MissingRole(message, roleId));
|
|
1032
|
-
});
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
921
|
//#endregion
|
|
1036
922
|
//#region src/stops/Silence.ts
|
|
1037
923
|
/**
|
|
@@ -1092,5 +978,5 @@ function pageCursor(prefix) {
|
|
|
1092
978
|
}
|
|
1093
979
|
|
|
1094
980
|
//#endregion
|
|
1095
|
-
export {
|
|
1096
|
-
//# sourceMappingURL=subscribers-
|
|
981
|
+
export { GLOBAL_ID as $, RegisterInteractionMiddleware as A, RegisterCommand as B, attemptWrite as C, AckTrace as D, lazyLogger as E, storeComponentRoute as F, warnLinks as G, Commands as H, storeInteractionRoute as I, indexById as J, commandKey as K, ComponentDefsKey as L, contextMenuRouteOf as M, interactionRoutesOf as N, checkAckLegality as O, routeDecoratorOf as P, guardedAccessor as Q, decodeComponentRoute as R, translateSerializationError as S, reportedWrite as T, ContextMenus as U, CommandInjector as V, installLinks as W, accessorStore as X, linkCommands as Y, clearStore as Z, NotInGuild as _, discardCommits as a, Notice as at, PermissionsUnresolved as b, runCheck as c, HasPresentPermissions as d, commandsRoute as et, MissingPermissions as f, NotInDm as g, NotAllowed as h, Silence as i, contextMenuLeaves as it, interactionMiddlewareMetaOf as j, sendTarget as k, runCommits as l, NeedsAny as m, pageCursor as n, scopeIdsOf as nt, markCommits as o, NoticeCard as ot, MissingRole as p, commandRefOf as q, ResolvedEmoji as r, skippedNote as rt, rollbackCommits as s, PAGE_MAX as t, globalFirst as tt, Fault as u, NotOwner as v, publishResponse as w, serializeReply as x, OnCooldown as y, ConfigGuilds as z };
|
|
982
|
+
//# sourceMappingURL=subscribers-CGuVjbrg.mjs.map
|