@mostfeatured/dbi 0.0.81 → 0.0.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DBI.d.ts +15 -0
- package/dist/DBI.d.ts.map +1 -1
- package/dist/DBI.js +33 -1
- package/dist/DBI.js.map +1 -1
- package/dist/Events.d.ts +17 -1
- package/dist/Events.d.ts.map +1 -1
- package/dist/Events.js.map +1 -1
- package/dist/methods/handleMessageCommands.d.ts +6 -0
- package/dist/methods/handleMessageCommands.d.ts.map +1 -0
- package/dist/methods/handleMessageCommands.js +301 -0
- package/dist/methods/handleMessageCommands.js.map +1 -0
- package/dist/methods/hookInteractionListeners.d.ts.map +1 -1
- package/dist/methods/hookInteractionListeners.js +1 -1
- package/dist/methods/hookInteractionListeners.js.map +1 -1
- package/dist/types/ChatInput/ChatInputOptions.d.ts +6 -6
- package/dist/types/ChatInput/ChatInputOptions.d.ts.map +1 -1
- package/dist/types/ChatInput/ChatInputOptions.js.map +1 -1
- package/dist/types/Interaction.d.ts +5 -1
- package/dist/types/Interaction.d.ts.map +1 -1
- package/dist/types/Interaction.js.map +1 -1
- package/dist/types/other/FakeMessageInteraction.d.ts +75 -0
- package/dist/types/other/FakeMessageInteraction.d.ts.map +1 -0
- package/dist/types/other/FakeMessageInteraction.js +311 -0
- package/dist/types/other/FakeMessageInteraction.js.map +1 -0
- package/package.json +2 -1
- package/readme.md +35 -0
- package/src/DBI.ts +53 -1
- package/src/Events.ts +10 -1
- package/src/methods/handleMessageCommands.ts +310 -0
- package/src/methods/hookInteractionListeners.ts +1 -2
- package/src/types/ChatInput/ChatInputOptions.ts +3 -3
- package/src/types/Interaction.ts +1 -1
- package/src/types/other/FakeMessageInteraction.ts +294 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { ApplicationCommandType, ChatInputCommandInteraction, Message, MessagePayload, ApplicationCommandOptionType } from "discord.js";
|
|
2
|
+
import { NamespaceEnums } from "../../generated/namespaceData";
|
|
3
|
+
import { DBI } from "../DBI";
|
|
4
|
+
import { FakeMessageInteraction } from "../types/other/FakeMessageInteraction";
|
|
5
|
+
import { TDBILocaleString } from "../types/other/Locale";
|
|
6
|
+
|
|
7
|
+
const INTEGER_REGEX = /^-?\d+$/;
|
|
8
|
+
const NUMBER_REGEX = /^-?\d+(?:\.\d+)?$/;
|
|
9
|
+
|
|
10
|
+
export type TDBIMessageCommandArgumentErrorTypes = "MissingRequiredOption" | "MinLength" | "MaxLength" | "InvalidChoice" | "InvalidInteger" | "MinInteger" | "MaxInteger" | "InvalidNumber" | "MinNumber" | "MaxNumber" | "InvalidBoolean" | "InvalidUser" | "InvalidChannel" | "InvalidRole" | "InvalidMentionable" | "InvalidCompleteChoice";
|
|
11
|
+
|
|
12
|
+
export async function handleMessageCommands(dbi: DBI<NamespaceEnums>, message: Message) {
|
|
13
|
+
const chatInputs = dbi.data.interactions.filter(i => i.type === "ChatInput");
|
|
14
|
+
const prefixes = dbi.config.messageCommands.prefixes ?? [];
|
|
15
|
+
if (!prefixes.length) return;
|
|
16
|
+
const content = message.content;
|
|
17
|
+
const usedPrefix = prefixes.find(p => content.startsWith(p));
|
|
18
|
+
if (!usedPrefix) return;
|
|
19
|
+
const contentWithoutPrefix = content.slice(usedPrefix?.length ?? 0);
|
|
20
|
+
const contentLower = contentWithoutPrefix.toLowerCase();
|
|
21
|
+
|
|
22
|
+
let locale: string = message.guild.preferredLocale?.split("-")?.at(0) || dbi.config.defaults.locale as any;
|
|
23
|
+
let usedAlias: string | undefined;
|
|
24
|
+
let chatInput = chatInputs.find(i => {
|
|
25
|
+
let found = contentLower.startsWith(i.name);
|
|
26
|
+
if (found) return true;
|
|
27
|
+
let alias = i.other?.messageCommand?.aliases?.find(a => contentLower.startsWith(a));
|
|
28
|
+
if (alias) {
|
|
29
|
+
usedAlias = alias;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
});
|
|
34
|
+
let commandName = usedAlias ?? chatInput?.name;
|
|
35
|
+
|
|
36
|
+
if (!chatInput) {
|
|
37
|
+
fLoop: for (const [localeInterName, localeData] of dbi.data.interactionLocales) {
|
|
38
|
+
for (const [localeName, translation] of Object.entries(localeData.data || {})) {
|
|
39
|
+
if (contentLower.startsWith(translation.name)) {
|
|
40
|
+
commandName = translation.name;
|
|
41
|
+
locale = localeName;
|
|
42
|
+
chatInput = chatInputs.find(i => i.name === localeData.name);
|
|
43
|
+
break fLoop;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!chatInput) return;
|
|
50
|
+
|
|
51
|
+
const interaction = new FakeMessageInteraction(dbi, message, chatInput, locale, commandName, usedPrefix);
|
|
52
|
+
|
|
53
|
+
if (chatInput.options.length) {
|
|
54
|
+
let errorType: TDBIMessageCommandArgumentErrorTypes;
|
|
55
|
+
let lastOption: any;
|
|
56
|
+
let lastValue: any;
|
|
57
|
+
let lastExtra: any;
|
|
58
|
+
let lastIndex: number;
|
|
59
|
+
for (let i = 0; i < chatInput.options.length; i++) {
|
|
60
|
+
lastIndex = i;
|
|
61
|
+
const option: any = interaction.dbiChatInputOptions[i];
|
|
62
|
+
const value = interaction.parsedArgs.get(option.name)?.value;
|
|
63
|
+
|
|
64
|
+
lastOption = option;
|
|
65
|
+
lastValue = value;
|
|
66
|
+
|
|
67
|
+
switch (option.type) {
|
|
68
|
+
case ApplicationCommandOptionType.String: {
|
|
69
|
+
if (option.autocomplete && option.onComplete) {
|
|
70
|
+
let choices = await option.onComplete({
|
|
71
|
+
interaction,
|
|
72
|
+
value
|
|
73
|
+
});
|
|
74
|
+
if (!choices.length) choices = await option.onComplete({
|
|
75
|
+
interaction,
|
|
76
|
+
value: ""
|
|
77
|
+
});
|
|
78
|
+
if (choices.length > 20) throw new Error("Autocomplete returned more than 20 choices.");
|
|
79
|
+
lastExtra = choices;
|
|
80
|
+
if (!choices.find(c => c.name === value || c.value === value)) {
|
|
81
|
+
if (value) {
|
|
82
|
+
errorType = "InvalidCompleteChoice";
|
|
83
|
+
break;
|
|
84
|
+
} else if (option.required && !value) {
|
|
85
|
+
errorType = "MissingRequiredOption";
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
option._choices = choices;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (option.choices) {
|
|
93
|
+
const localeData = dbi.data.interactionLocales.get(chatInput.name)?.data;
|
|
94
|
+
const choicesLocaleData = localeData?.[locale as TDBILocaleString]?.options?.[option.name]?.choices;
|
|
95
|
+
if (!option.choices.find(c => c.name === value || c.value === value || (choicesLocaleData?.[c.value] && choicesLocaleData?.[c.value] === value))) {
|
|
96
|
+
lastExtra = option.choices.map(c => ({ name: choicesLocaleData?.[c.value] ?? c.name, value: c.value }));
|
|
97
|
+
if (value) {
|
|
98
|
+
errorType = "InvalidChoice";
|
|
99
|
+
break;
|
|
100
|
+
} else if (option.required && !value) {
|
|
101
|
+
errorType = "MissingRequiredOption";
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (option.minLength && value.length < option.minLength) {
|
|
109
|
+
errorType = "MinLength";
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
if (option.maxLength && value.length > option.maxLength) {
|
|
113
|
+
errorType = "MaxLength";
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
case ApplicationCommandOptionType.Integer: {
|
|
120
|
+
let parsedInt = parseInt(value);
|
|
121
|
+
|
|
122
|
+
if (option.autocomplete && option.onComplete) {
|
|
123
|
+
let choices = await option.onComplete({
|
|
124
|
+
interaction,
|
|
125
|
+
value
|
|
126
|
+
});
|
|
127
|
+
if (!choices.length) choices = await option.onComplete({
|
|
128
|
+
interaction,
|
|
129
|
+
value: ""
|
|
130
|
+
});
|
|
131
|
+
if (choices.length > 20) throw new Error("Autocomplete returned more than 20 choices.");
|
|
132
|
+
lastExtra = choices;
|
|
133
|
+
if (!choices.find(c => c.value === parsedInt || c.name === value)) {
|
|
134
|
+
if (value) {
|
|
135
|
+
errorType = "InvalidCompleteChoice";
|
|
136
|
+
break;
|
|
137
|
+
} else if (option.required && !value) {
|
|
138
|
+
errorType = "MissingRequiredOption";
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
option._choices = choices;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (option.choices) {
|
|
147
|
+
const localeData = dbi.data.interactionLocales.get(chatInput.name)?.data;
|
|
148
|
+
const choicesLocaleData = localeData?.[locale as TDBILocaleString]?.options?.[option.name]?.choices;
|
|
149
|
+
if (!option.choices.find(c => c.value === parsedInt || c.name === value || (choicesLocaleData?.[c.value] && choicesLocaleData?.[c.value] === value))) {
|
|
150
|
+
lastExtra = option.choices.map(c => ({ name: choicesLocaleData?.[c.value] ?? c.name, value: c.value }));
|
|
151
|
+
if (value) {
|
|
152
|
+
errorType = "InvalidChoice";
|
|
153
|
+
break;
|
|
154
|
+
} else if (option.required && !value) {
|
|
155
|
+
errorType = "MissingRequiredOption";
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (!INTEGER_REGEX.test(value)) {
|
|
163
|
+
errorType = "InvalidInteger";
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (option.minValue && parsedInt < option.minValue) {
|
|
168
|
+
errorType = "MinInteger";
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (option.maxValue && parsedInt > option.maxValue) {
|
|
173
|
+
errorType = "MaxInteger";
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
case ApplicationCommandOptionType.Number: {
|
|
180
|
+
let parsedFloat = parseFloat(value);
|
|
181
|
+
|
|
182
|
+
if (option.autocomplete && option.onComplete) {
|
|
183
|
+
let choices = await option.onComplete({
|
|
184
|
+
interaction,
|
|
185
|
+
value
|
|
186
|
+
});
|
|
187
|
+
if (!choices.length) choices = await option.onComplete({
|
|
188
|
+
interaction,
|
|
189
|
+
value: ""
|
|
190
|
+
});
|
|
191
|
+
if (choices.length > 20) throw new Error("Autocomplete returned more than 20 choices.");
|
|
192
|
+
lastExtra = choices;
|
|
193
|
+
if (!choices.find(c => c.value === parsedFloat || c.name === value)) {
|
|
194
|
+
if (value) {
|
|
195
|
+
errorType = "InvalidCompleteChoice";
|
|
196
|
+
break;
|
|
197
|
+
} else if (option.required && !value) {
|
|
198
|
+
errorType = "MissingRequiredOption";
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
option._choices = choices;
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (option.choices) {
|
|
207
|
+
const localeData = dbi.data.interactionLocales.get(chatInput.name)?.data;
|
|
208
|
+
const choicesLocaleData = localeData?.[locale as TDBILocaleString]?.options?.[option.name]?.choices;
|
|
209
|
+
if (!option.choices.find(c => c.value === parsedFloat || c.name === value || (choicesLocaleData?.[c.value] && choicesLocaleData?.[c.value] === value))) {
|
|
210
|
+
lastExtra = option.choices.map(c => ({ name: choicesLocaleData?.[c.value] ?? c.name, value: c.value }));
|
|
211
|
+
if (value) {
|
|
212
|
+
errorType = "InvalidChoice";
|
|
213
|
+
break;
|
|
214
|
+
} else if (option.required && !value) {
|
|
215
|
+
errorType = "MissingRequiredOption";
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (!NUMBER_REGEX.test(value)) {
|
|
223
|
+
errorType = "InvalidNumber";
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (option.minValue && parsedFloat < option.minValue) {
|
|
228
|
+
errorType = "MinNumber";
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (option.maxValue && parsedFloat > option.maxValue) {
|
|
233
|
+
errorType = "MaxNumber";
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
case ApplicationCommandOptionType.Boolean: {
|
|
239
|
+
let boolKeys = Object.keys(dbi.config.messageCommands.typeAliases.booleans);
|
|
240
|
+
if (!boolKeys.includes(value.toLowerCase())) {
|
|
241
|
+
errorType = "InvalidBoolean";
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
case ApplicationCommandOptionType.User: {
|
|
247
|
+
if (!interaction.options.getUser(option.name)) {
|
|
248
|
+
errorType = "InvalidUser";
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
case ApplicationCommandOptionType.Channel: {
|
|
254
|
+
if (!interaction.options.getChannel(option.name, null, option.channelTypes)) {
|
|
255
|
+
errorType = "InvalidChannel";
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
case ApplicationCommandOptionType.Role: {
|
|
261
|
+
if (!interaction.options.getRole(option.name)) {
|
|
262
|
+
errorType = "InvalidRole";
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
case ApplicationCommandOptionType.Mentionable: {
|
|
268
|
+
if (!interaction.options.getMentionable(option.name)) {
|
|
269
|
+
errorType = "InvalidMentionable";
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
case ApplicationCommandOptionType.Attachment: {
|
|
275
|
+
if (option.required && !value) {
|
|
276
|
+
errorType = "MissingRequiredOption";
|
|
277
|
+
}
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (errorType) {
|
|
283
|
+
break;
|
|
284
|
+
} else {
|
|
285
|
+
lastExtra = null;
|
|
286
|
+
lastIndex = null;
|
|
287
|
+
lastOption = null;
|
|
288
|
+
lastValue = null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (errorType) {
|
|
293
|
+
let res = await dbi.events.trigger("messageCommandArgumentError", {
|
|
294
|
+
interaction,
|
|
295
|
+
message,
|
|
296
|
+
error: {
|
|
297
|
+
type: errorType,
|
|
298
|
+
option: lastOption,
|
|
299
|
+
extra: lastExtra,
|
|
300
|
+
index: lastIndex
|
|
301
|
+
},
|
|
302
|
+
value: lastValue
|
|
303
|
+
});
|
|
304
|
+
if (!res) return;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
dbi.data.clients.first().client.emit("interactionCreate", interaction as any);
|
|
310
|
+
}
|
|
@@ -7,9 +7,8 @@ const componentTypes = ["Button", "StringSelectMenu", "UserSelectMenu", "RoleSel
|
|
|
7
7
|
|
|
8
8
|
export function hookInteractionListeners(dbi: DBI<NamespaceEnums>): () => any {
|
|
9
9
|
async function handle(inter: Discord.Interaction<"cached">) {
|
|
10
|
-
|
|
11
10
|
const dbiInter =
|
|
12
|
-
dbi.data.interactions.find(i => {
|
|
11
|
+
(inter as any).dbiChatInput ?? dbi.data.interactions.find(i => {
|
|
13
12
|
let isUsesCustomId = (inter.isButton() || inter.isAnySelectMenu() || inter.isModalSubmit());
|
|
14
13
|
let parsedId = isUsesCustomId ? parseCustomId(dbi, (inter as any).customId) : null;
|
|
15
14
|
return (
|
|
@@ -19,7 +19,7 @@ export class DBIChatInputOptions<TNamespace extends NamespaceEnums> {
|
|
|
19
19
|
constructor(dbi: DBI<TNamespace>) {
|
|
20
20
|
this.dbi = dbi;
|
|
21
21
|
}
|
|
22
|
-
stringAutocomplete(cfg: TDBIBaseOption & TDBIMinMaxLength & { onComplete(ctx: IDBICompleteCtx<TNamespace, string>): Promise<TDBIValueName<string>[]> }) {
|
|
22
|
+
stringAutocomplete(cfg: TDBIBaseOption & TDBIMinMaxLength & { onComplete(ctx: IDBICompleteCtx<TNamespace, string>): Promise<TDBIValueName<string>[]> | TDBIValueName<string>[] }) {
|
|
23
23
|
return {
|
|
24
24
|
type: Discord.ApplicationCommandOptionType.String,
|
|
25
25
|
name: cfg.name,
|
|
@@ -60,7 +60,7 @@ export class DBIChatInputOptions<TNamespace extends NamespaceEnums> {
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
numberAutocomplete(cfg: TDBIBaseOption & TDBIMinMaxValue & { onComplete(ctx: IDBICompleteCtx<TNamespace, string>): Promise<TDBIValueName<number>[]> }) {
|
|
63
|
+
numberAutocomplete(cfg: TDBIBaseOption & TDBIMinMaxValue & { onComplete(ctx: IDBICompleteCtx<TNamespace, string>): Promise<TDBIValueName<number>[]> | TDBIValueName<number>[] }) {
|
|
64
64
|
return {
|
|
65
65
|
type: Discord.ApplicationCommandOptionType.Number,
|
|
66
66
|
name: cfg.name,
|
|
@@ -102,7 +102,7 @@ export class DBIChatInputOptions<TNamespace extends NamespaceEnums> {
|
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
integerAutocomplete(cfg: TDBIBaseOption & TDBIMinMaxValue & { onComplete(ctx: IDBICompleteCtx<TNamespace, string>): Promise<TDBIValueName<number>[]> }) {
|
|
105
|
+
integerAutocomplete(cfg: TDBIBaseOption & TDBIMinMaxValue & { onComplete(ctx: IDBICompleteCtx<TNamespace, string>): Promise<TDBIValueName<number>[]> | TDBIValueName<number>[] }) {
|
|
106
106
|
return {
|
|
107
107
|
type: Discord.ApplicationCommandOptionType.Integer,
|
|
108
108
|
name: cfg.name,
|
package/src/types/Interaction.ts
CHANGED
|
@@ -81,7 +81,7 @@ export class DBIBaseInteraction<TNamespace extends NamespaceEnums> {
|
|
|
81
81
|
description: string;
|
|
82
82
|
readonly type: TDBIInteractionTypes;
|
|
83
83
|
options?: any | any[];
|
|
84
|
-
other?: Record<string, any
|
|
84
|
+
other?: Record<string, any> & { messageCommand: { aliases: string[] } };
|
|
85
85
|
rateLimits?: DBIRateLimit[];
|
|
86
86
|
toJSON(overrides: any): any { }
|
|
87
87
|
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { Message, MessagePayload, ApplicationCommandType, ChatInputCommandInteraction, Locale, APIInteractionGuildMember, GuildMember, PermissionsBitField, CacheType, CommandInteractionOptionResolver, CommandOptionDataTypeResolvable, ApplicationCommandOptionType, User, Attachment } from 'discord.js';
|
|
2
|
+
import { TDBIInteractions } from '../Interaction';
|
|
3
|
+
import { plsParseArgs } from "plsargs";
|
|
4
|
+
import { DBI } from '../../DBI';
|
|
5
|
+
import { NamespaceEnums } from "../../../generated/namespaceData";
|
|
6
|
+
import { ChannelType } from "discord-api-types/v10";
|
|
7
|
+
|
|
8
|
+
export class FakeMessageInteraction /* implements ChatInputCommandInteraction */ {
|
|
9
|
+
channelId: string;
|
|
10
|
+
commandName: string;
|
|
11
|
+
appPermissions: any;
|
|
12
|
+
applicationId: string;
|
|
13
|
+
channel: any;
|
|
14
|
+
command: any;
|
|
15
|
+
commandGuildId: string;
|
|
16
|
+
commandId: any;
|
|
17
|
+
commandType: ApplicationCommandType.ChatInput;
|
|
18
|
+
// awaitModalSubmit: (...arr: any[]) => any;
|
|
19
|
+
// fetchReply: () => Promise<any>;
|
|
20
|
+
deferred: boolean = false;
|
|
21
|
+
client: any;
|
|
22
|
+
createdAt: Date;
|
|
23
|
+
ephemeral: boolean = false;
|
|
24
|
+
createdTimestamp: number;
|
|
25
|
+
guild: any;
|
|
26
|
+
guildId: string;
|
|
27
|
+
guildLocale: Locale;
|
|
28
|
+
id: string;
|
|
29
|
+
user: User;
|
|
30
|
+
private repliedMessage: Message | undefined;
|
|
31
|
+
private lastFollowUp: Message | undefined;
|
|
32
|
+
member: GuildMember | APIInteractionGuildMember;
|
|
33
|
+
memberPermissions: Readonly<PermissionsBitField>;
|
|
34
|
+
parsedArgs = new Map<string, FakeMessageInteractionArgument>();
|
|
35
|
+
usedCommandName: string;
|
|
36
|
+
fullCommandName: string;
|
|
37
|
+
options: any;
|
|
38
|
+
dbiChatInput: TDBIInteractions<string | number>;
|
|
39
|
+
dbiChatInputOptions: any[];
|
|
40
|
+
fake: boolean = true;
|
|
41
|
+
|
|
42
|
+
constructor(private dbi: DBI<NamespaceEnums>, private message: Message, chatInput: TDBIInteractions<string | number>, public locale: string, commandName: string, private usedPrefix: string) {
|
|
43
|
+
const self = this;
|
|
44
|
+
|
|
45
|
+
this.channelId = message.channel.id;
|
|
46
|
+
this.commandName = chatInput.name.split(" ").at(0);
|
|
47
|
+
this.appPermissions = message.guild?.members.me.permissionsIn(message.channel as any) ?? new PermissionsBitField(8n);
|
|
48
|
+
this.applicationId = message.client.user.id;
|
|
49
|
+
this.channel = message.channel as any;
|
|
50
|
+
this.commandGuildId = message.guild.id;
|
|
51
|
+
this.commandType = ApplicationCommandType.ChatInput;
|
|
52
|
+
|
|
53
|
+
this.client = message.client;
|
|
54
|
+
this.createdAt = message.createdAt;
|
|
55
|
+
this.createdTimestamp = message.createdTimestamp;
|
|
56
|
+
this.guild = message.guild;
|
|
57
|
+
this.guildId = message.guild?.id;
|
|
58
|
+
this.guildLocale = message.guild?.preferredLocale;
|
|
59
|
+
this.id = message.guild?.commands.cache.find((cmd) => cmd.name === this.commandName)?.id ?? message.client.application.commands.cache.find((cmd) => cmd.name === this.commandName)?.id ?? "-1";
|
|
60
|
+
this.locale = message.guild?.preferredLocale;
|
|
61
|
+
this.member = message.member;
|
|
62
|
+
this.memberPermissions = message.member?.permissions;
|
|
63
|
+
this.user = message.author;
|
|
64
|
+
|
|
65
|
+
this.usedCommandName = commandName;
|
|
66
|
+
this.fullCommandName = chatInput.name;
|
|
67
|
+
this.dbiChatInput = chatInput;
|
|
68
|
+
this.dbiChatInputOptions = chatInput.options ? chatInput.options.map(i => ({ ...i })) : [];
|
|
69
|
+
|
|
70
|
+
{
|
|
71
|
+
const argContent = message.content.slice(usedPrefix.length + commandName.length).replace(/ +/, " ").trim();
|
|
72
|
+
const args = plsParseArgs(argContent);
|
|
73
|
+
|
|
74
|
+
const options = chatInput.options ?? [];
|
|
75
|
+
const atchs = [...message.attachments.values()];
|
|
76
|
+
for (let i = 0, attachmentIndex = 0, namedValueSize = 0; i < options.length; i++) {
|
|
77
|
+
const option = options[i];
|
|
78
|
+
if (!option) break;
|
|
79
|
+
if (option.type === ApplicationCommandOptionType.Attachment) {
|
|
80
|
+
this.parsedArgs.set(option.name, {
|
|
81
|
+
type: option.type,
|
|
82
|
+
value: atchs.at(attachmentIndex)?.url,
|
|
83
|
+
attachment: atchs.at(attachmentIndex++)
|
|
84
|
+
})
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const arg = args.get(option.name) ?? args.get(i - attachmentIndex - namedValueSize);
|
|
88
|
+
if (args.get(option.name)) namedValueSize++;
|
|
89
|
+
this.parsedArgs.set(option.name, {
|
|
90
|
+
type: option.type,
|
|
91
|
+
value: arg
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log(this.parsedArgs)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.options = {
|
|
99
|
+
get(name: string) {
|
|
100
|
+
const rawValue = self.getRawOptionValue(name);
|
|
101
|
+
if (!rawValue) return null;
|
|
102
|
+
return {
|
|
103
|
+
value: rawValue,
|
|
104
|
+
get boolean() { return self.options.getBoolean(name); },
|
|
105
|
+
get channel() { return self.options.getChannel(name); },
|
|
106
|
+
get string() { return self.options.getString(name); },
|
|
107
|
+
get integer() { return self.options.getInteger(name); },
|
|
108
|
+
get number() { return self.options.getNumber(name); },
|
|
109
|
+
get user() { return self.options.getUser(name); },
|
|
110
|
+
get member() { return self.options.getMember(name); },
|
|
111
|
+
get role() { return self.options.getRole(name); },
|
|
112
|
+
get mentionable() { return self.options.getMentionable(name); },
|
|
113
|
+
get attachment() { return self.options.getAttachment(name); }
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
getSubcommand() {
|
|
117
|
+
let splitted = self.fullCommandName.split(" ");
|
|
118
|
+
if (splitted.length === 1) return null;
|
|
119
|
+
return splitted.at(-1);
|
|
120
|
+
},
|
|
121
|
+
getSubcommandGroup() {
|
|
122
|
+
let splitted = self.fullCommandName.split(" ");
|
|
123
|
+
if (splitted.length === 3) return splitted[1];
|
|
124
|
+
return null;
|
|
125
|
+
},
|
|
126
|
+
getBoolean(name: string) {
|
|
127
|
+
const rawValue = self.getRawOptionValue(name);
|
|
128
|
+
if (!rawValue) return null;
|
|
129
|
+
return !!self.dbi.config.messageCommands.typeAliases.booleans[rawValue.toLowerCase()];
|
|
130
|
+
},
|
|
131
|
+
getChannel(name: string, _: any, channelType?: ChannelType) {
|
|
132
|
+
const rawValue = self.getRawOptionValue(name);
|
|
133
|
+
if (!rawValue) return null;
|
|
134
|
+
let value = rawValue.replace(/<#|>/g, "");
|
|
135
|
+
let channel = self.message.client.channels.cache.get(value);
|
|
136
|
+
if (!channel) channel = self.message.client.channels.cache.find(c => {
|
|
137
|
+
if (self.guildId && (c as any).guildId && (c as any).guildId !== self.guildId) return false;
|
|
138
|
+
return (c as any).name === value;
|
|
139
|
+
});
|
|
140
|
+
if (channelType && channel?.type !== channelType) return null;
|
|
141
|
+
return channel;
|
|
142
|
+
},
|
|
143
|
+
getString(name: string) {
|
|
144
|
+
const dbiOption = self.getClonedDBIOption(name);
|
|
145
|
+
let rawValue = `${self.getRawOptionValue(name)}`;
|
|
146
|
+
let choices = dbiOption.choices ?? dbiOption._choices;
|
|
147
|
+
if (choices) return choices.find(c => c.value === rawValue || c.name === rawValue)?.value ?? rawValue;
|
|
148
|
+
return rawValue;
|
|
149
|
+
},
|
|
150
|
+
getInteger(name: string) {
|
|
151
|
+
const dbiOption = self.getClonedDBIOption(name);
|
|
152
|
+
let rawValue = self.getRawOptionValue(name);
|
|
153
|
+
let parsedValue = parseInt(rawValue);
|
|
154
|
+
let choices = dbiOption.choices ?? dbiOption._choices;
|
|
155
|
+
if (choices) return choices.find(c => c.value === parsedValue || c.name === rawValue)?.value ?? rawValue;
|
|
156
|
+
return rawValue;
|
|
157
|
+
},
|
|
158
|
+
getNumber(name: string) {
|
|
159
|
+
const dbiOption = self.getClonedDBIOption(name);
|
|
160
|
+
let rawValue = self.getRawOptionValue(name);
|
|
161
|
+
let parsedValue = parseFloat(rawValue);
|
|
162
|
+
let choices = dbiOption.choices ?? dbiOption._choices;
|
|
163
|
+
if (choices) return choices.find(c => c.value === parsedValue || c.name === rawValue)?.value ?? rawValue;
|
|
164
|
+
return rawValue;
|
|
165
|
+
},
|
|
166
|
+
getUser(name: string) {
|
|
167
|
+
const rawValue = self.getRawOptionValue(name);
|
|
168
|
+
if (!rawValue) return null;
|
|
169
|
+
let value = rawValue.replace(/<@!?|>/g, "");
|
|
170
|
+
let user = self.message.client.users.cache.get(value);
|
|
171
|
+
if (!user) user = self.message.client.users.cache.find(u => u.username === value || u.tag === value);
|
|
172
|
+
return user;
|
|
173
|
+
},
|
|
174
|
+
getMember(name: string) {
|
|
175
|
+
const rawValue = self.getRawOptionValue(name);
|
|
176
|
+
if (!rawValue) return null;
|
|
177
|
+
let value = rawValue.replace(/<@!?|>/g, "");
|
|
178
|
+
let member = self.message.guild?.members.cache.get(value);
|
|
179
|
+
if (!member) member = self.message.guild?.members.cache.find(m => m.user.username === value || m.user.tag === value);
|
|
180
|
+
return member;
|
|
181
|
+
},
|
|
182
|
+
getRole(name: string) {
|
|
183
|
+
const rawValue = self.getRawOptionValue(name);
|
|
184
|
+
if (!rawValue) return null;
|
|
185
|
+
let value = rawValue.replace(/<@&|>/g, "");
|
|
186
|
+
let role = self.message.guild?.roles.cache.get(value);
|
|
187
|
+
if (!role) role = self.message.guild?.roles.cache.find(r => r.name === value);
|
|
188
|
+
return role;
|
|
189
|
+
},
|
|
190
|
+
getMentionable(name: string) {
|
|
191
|
+
const rawValue = self.getRawOptionValue(name);
|
|
192
|
+
if (!rawValue) return null;
|
|
193
|
+
let value = rawValue.replace(/<@(!|&)?|>/g, "");
|
|
194
|
+
let user = self.message.client.users.cache.get(value);
|
|
195
|
+
if (!user) user = self.message.client.users.cache.find(u => u.username === value || u.tag === value);
|
|
196
|
+
if (user) return user;
|
|
197
|
+
let member = self.message.guild?.members.cache.get(value);
|
|
198
|
+
if (!member) member = self.message.guild?.members.cache.find(m => m.user.username === value || m.user.tag === value);
|
|
199
|
+
if (member) return member;
|
|
200
|
+
let role = self.message.guild?.roles.cache.get(value);
|
|
201
|
+
if (!role) role = self.message.guild?.roles.cache.find(r => r.name === value);
|
|
202
|
+
if (role) return role;
|
|
203
|
+
return null;
|
|
204
|
+
},
|
|
205
|
+
getMessage() {
|
|
206
|
+
return self.message;
|
|
207
|
+
},
|
|
208
|
+
getAttachment(name: string) {
|
|
209
|
+
let d = self.parsedArgs.get(name);
|
|
210
|
+
return d?.attachment ?? null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private getRawOptionValue(name: string): any {
|
|
216
|
+
return this.parsedArgs.get(name)?.value;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private getClonedDBIOption(name: string): any {
|
|
220
|
+
return this.dbiChatInputOptions.find(o => o.name === name);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
inGuild() {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async deferReply(options: any): Promise<any> {
|
|
228
|
+
// if (options.ephemeral) throw new Error("Ephemeral replies are not supported in message commands.");
|
|
229
|
+
if (this.repliedMessage) throw new Error("Already deferred reply.");
|
|
230
|
+
this.repliedMessage = await this.message.reply(options.content ?? "Loading...");
|
|
231
|
+
this.deferred = true;
|
|
232
|
+
return this.repliedMessage;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async deleteReply() {
|
|
236
|
+
if (!this.repliedMessage) throw new Error("No deferred reply.");
|
|
237
|
+
await this.repliedMessage.delete();
|
|
238
|
+
this.repliedMessage = undefined;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async followUp(content: string | MessagePayload) {
|
|
242
|
+
if (!this.repliedMessage) throw new Error("No deferred reply.");
|
|
243
|
+
if (!this.lastFollowUp) {
|
|
244
|
+
this.lastFollowUp = await this.repliedMessage.reply(content);
|
|
245
|
+
} else {
|
|
246
|
+
this.lastFollowUp = await this.lastFollowUp.reply(content);
|
|
247
|
+
}
|
|
248
|
+
return this.lastFollowUp;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
async editReply(content: string | MessagePayload) {
|
|
252
|
+
if (!this.repliedMessage) throw new Error("No deferred reply.");
|
|
253
|
+
await this.repliedMessage.edit(content);
|
|
254
|
+
return this.repliedMessage;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async reply(content: string | MessagePayload): Promise<any> {
|
|
258
|
+
if (this.repliedMessage) throw new Error("Already deferred reply.");
|
|
259
|
+
this.repliedMessage = await this.message.reply(content);
|
|
260
|
+
return this.repliedMessage;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async awaitModalSubmit() {
|
|
264
|
+
throw new Error("Method not implemented.");
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
async fetchReply() {
|
|
268
|
+
return this.repliedMessage?.id && await this.message.channel.messages.fetch(this.repliedMessage.id);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
isAnySelectMenu() { return false; }
|
|
272
|
+
isAutocomplete() { return false; }
|
|
273
|
+
isButton() { return false; }
|
|
274
|
+
isChannelSelectMenu() { return false; }
|
|
275
|
+
isChatInputCommand() { return true; }
|
|
276
|
+
isCommand() { return true; }
|
|
277
|
+
isContextMenuCommand() { return false; }
|
|
278
|
+
isMentionableSelectMenu() { return false; }
|
|
279
|
+
isMessageComponent() { return false; }
|
|
280
|
+
isMessageContextMenuCommand() { return false; }
|
|
281
|
+
isModalSubmit() { return false; }
|
|
282
|
+
isRepliable() { return true; }
|
|
283
|
+
isRoleSelectMenu() { return false; }
|
|
284
|
+
isStringSelectMenu() { return false; }
|
|
285
|
+
isUserContextMenuCommand() { return false; }
|
|
286
|
+
isUserSelectMenu() { return false; }
|
|
287
|
+
isSelectMenu() { return false; }
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
interface FakeMessageInteractionArgument {
|
|
291
|
+
type: ApplicationCommandOptionType,
|
|
292
|
+
value: any,
|
|
293
|
+
attachment?: Attachment
|
|
294
|
+
}
|