/
PreconditionContainerSingle.ts
136 lines (126 loc) · 5.53 KB
/
PreconditionContainerSingle.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { container } from '@sapphire/pieces';
import { err } from '@sapphire/result';
import type { ChatInputCommandInteraction, ContextMenuCommandInteraction, Message } from 'discord.js';
import { Identifiers } from '../../errors/Identifiers';
import { UserError } from '../../errors/UserError';
import type { Precondition, PreconditionContext, PreconditionKeys, Preconditions, SimplePreconditionKeys } from '../../structures/Precondition';
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from '../../types/CommandTypes';
import type { IPreconditionContainer } from './IPreconditionContainer';
/**
* Defines the simple options for the {@link PreconditionContainerSingle}, where only the name of the precondition can
* be defined.
* @since 2.0.0
*/
export interface SimplePreconditionSingleResolvableDetails {
/**
* The name of the precondition to retrieve from {@link SapphireClient.preconditions}.
* @since 2.0.0
*/
name: SimplePreconditionKeys;
}
/**
* Defines the detailed options for the {@link PreconditionContainerSingle}, where both the {@link PreconditionContext} and the
* name of the precondition can be defined.
* @since 1.0.0
*/
export interface PreconditionSingleResolvableDetails<K extends PreconditionKeys = PreconditionKeys> {
/**
* The name of the precondition to retrieve from {@link SapphireClient.preconditions}.
* @since 1.0.0
*/
name: K;
/**
* The context to be set at {@link PreconditionContainerSingle.context}.
* @since 1.0.0
*/
context: Preconditions[K];
}
/**
* Defines the data accepted by {@link PreconditionContainerSingle}'s constructor.
* @since 1.0.0
*/
export type PreconditionSingleResolvable = SimplePreconditionKeys | SimplePreconditionSingleResolvableDetails | PreconditionSingleResolvableDetails;
/**
* An {@link IPreconditionContainer} which runs a single precondition from {@link SapphireClient.preconditions}.
* @since 1.0.0
*/
export class PreconditionContainerSingle implements IPreconditionContainer {
/**
* The context to be used when calling {@link Precondition.run}. This will always be an empty object (`{}`) when the
* container was constructed with a string, otherwise it is a direct reference to the value from
* {@link PreconditionSingleResolvableDetails.context}.
* @since 1.0.0
*/
public readonly context: Record<PropertyKey, unknown>;
/**
* The name of the precondition to run.
* @since 1.0.0
*/
public readonly name: string;
public constructor(data: PreconditionSingleResolvable) {
if (typeof data === 'string') {
this.context = {};
this.name = data;
} else {
this.context = Reflect.get(data, 'context') ?? {};
this.name = data.name;
}
}
/**
* Runs the container.
* @since 1.0.0
* @param message The message that ran this precondition.
* @param command The command the message invoked.
* @param context The context for the message precondition.
*/
public messageRun(message: Message, command: MessageCommand, context: PreconditionContext = {}) {
const precondition = container.stores.get('preconditions').get(this.name);
if (precondition) {
return precondition.messageRun
? precondition.messageRun(message, command, { ...context, ...this.context })
: precondition.error({
identifier: Identifiers.PreconditionMissingMessageHandler,
message: `The precondition "${precondition.name}" is missing a "messageRun" handler, but it was requested for the "${command.name}" command.`
});
}
return err(new UserError({ identifier: Identifiers.PreconditionUnavailable, message: `The precondition "${this.name}" is not available.` }));
}
/**
* Runs the container.
* @since 3.0.0
* @param interaction The interaction that ran this precondition.
* @param command The command the interaction invoked.
* @param context The context for the chat input command precondition.
*/
public chatInputRun(interaction: ChatInputCommandInteraction, command: ChatInputCommand, context: PreconditionContext = {}) {
const precondition = container.stores.get('preconditions').get(this.name);
if (precondition) {
return precondition.chatInputRun
? precondition.chatInputRun(interaction, command, { ...context, ...this.context })
: precondition.error({
identifier: Identifiers.PreconditionMissingChatInputHandler,
message: `The precondition "${precondition.name}" is missing a "chatInputRun" handler, but it was requested for the "${command.name}" command.`
});
}
return err(new UserError({ identifier: Identifiers.PreconditionUnavailable, message: `The precondition "${this.name}" is not available.` }));
}
/**
* Runs the container.
* @since 3.0.0
* @param interaction The interaction that ran this precondition.
* @param command The command the interaction invoked.
* @param context The context for the context menu command precondition.
*/
public contextMenuRun(interaction: ContextMenuCommandInteraction, command: ContextMenuCommand, context: PreconditionContext = {}) {
const precondition = container.stores.get('preconditions').get(this.name);
if (precondition) {
return precondition.contextMenuRun
? precondition.contextMenuRun(interaction, command, { ...context, ...this.context })
: precondition.error({
identifier: Identifiers.PreconditionMissingContextMenuHandler,
message: `The precondition "${precondition.name}" is missing a "contextMenuRun" handler, but it was requested for the "${command.name}" command.`
});
}
return err(new UserError({ identifier: Identifiers.PreconditionUnavailable, message: `The precondition "${this.name}" is not available.` }));
}
}