@sapphire/cli 1.5.1-next.5c0f4fc.0 → 1.6.0-next.52e7dec.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/dist/commands/generate.js +23 -4
- package/dist/commands/init.js +2 -1
- package/dist/commands/new.js +6 -2
- package/dist/functions/CreateFileFromTemplate.js +24 -14
- package/dist/lib/types.js +2 -0
- package/dist/prompts/PromptInit.js +6 -0
- package/dist/prompts/PromptNew.js +2 -1
- package/package.json +6 -2
- package/templates/.sapphirerc.json.sapphire +3 -2
- package/templates/.sapphirerc.yml.sapphire +1 -0
- package/templates/components/argument.ts.sapphire +3 -3
- package/templates/components/autocompleteinteractionhandler.js.sapphire +50 -0
- package/templates/components/autocompleteinteractionhandler.ts.sapphire +32 -0
- package/templates/components/buttoninteractionhandler.js.sapphire +39 -0
- package/templates/components/buttoninteractionhandler.ts.sapphire +24 -0
- package/templates/components/contextmenucommand.ts.sapphire +1 -1
- package/templates/components/listener.ts.sapphire +3 -3
- package/templates/components/messagecommand.ts.sapphire +1 -1
- package/templates/components/modalinteractionhandler.js.sapphire +39 -0
- package/templates/components/modalinteractionhandler.ts.sapphire +23 -0
- package/templates/components/route.js.sapphire +1 -0
- package/templates/components/selectmenuinteractionhandler.js.sapphire +39 -0
- package/templates/components/selectmenuinteractionhandler.ts.sapphire +23 -0
- package/templates/schemas/.sapphirerc.scheme.json +4 -1
|
@@ -25,15 +25,34 @@ async function createComponent(component, name, config, configLoc) {
|
|
|
25
25
|
else if (await fileExists(corePath)) {
|
|
26
26
|
return CreateFileFromTemplate(`components/${template}`, target, config, params, false, true);
|
|
27
27
|
}
|
|
28
|
-
throw new Error(
|
|
28
|
+
throw new Error(`Couldn't find a template file for that component type.${parseCommonHints(component)}`);
|
|
29
29
|
}
|
|
30
30
|
async function fetchConfig() {
|
|
31
|
-
const
|
|
32
|
-
if (
|
|
33
|
-
return
|
|
31
|
+
const configFileAsJson = await Promise.race([findUp('.sapphirerc.json', { cwd: '.' }), sleep(5000)]);
|
|
32
|
+
if (configFileAsJson) {
|
|
33
|
+
return configFileAsJson;
|
|
34
34
|
}
|
|
35
35
|
return Promise.race([findUp('.sapphirerc.yml', { cwd: '.' }), sleep(5000)]);
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Parses common hints for the user
|
|
39
|
+
* @param component Component name
|
|
40
|
+
* @returns A string with a hint for the user
|
|
41
|
+
*/
|
|
42
|
+
function parseCommonHints(component) {
|
|
43
|
+
const newLine = '\n';
|
|
44
|
+
const lowerCaseComponent = component.toLowerCase();
|
|
45
|
+
if (lowerCaseComponent === 'command' || lowerCaseComponent === 'commands') {
|
|
46
|
+
return `${newLine}Hint: You wrote "${component}", instead of "messagecommand", "slashcommand", or "contextmenucommand"`;
|
|
47
|
+
}
|
|
48
|
+
if (lowerCaseComponent === 'interaction-handler' ||
|
|
49
|
+
lowerCaseComponent === 'interaction-handlers' ||
|
|
50
|
+
lowerCaseComponent === 'interactionhandler' ||
|
|
51
|
+
lowerCaseComponent === 'interactionhandlers') {
|
|
52
|
+
return `${newLine}Hint: You wrote "${component}", instead of "buttoninteractionhandler", "autocompleteinteractionhandler", "modalinteractionhandler", or "selectmenuinteractionhandler"`;
|
|
53
|
+
}
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
37
56
|
export default async (component, name) => {
|
|
38
57
|
const spinner = new Spinner(`Creating a ${component.toLowerCase()}`).start();
|
|
39
58
|
const fail = (error, additionalExecution) => {
|
package/dist/commands/init.js
CHANGED
|
@@ -20,7 +20,8 @@ export default async () => {
|
|
|
20
20
|
arguments: response.arguments,
|
|
21
21
|
commands: response.commands,
|
|
22
22
|
listeners: response.listeners,
|
|
23
|
-
preconditions: response.preconditions
|
|
23
|
+
preconditions: response.preconditions,
|
|
24
|
+
'interaction-handlers': response['interaction-handlers']
|
|
24
25
|
},
|
|
25
26
|
customFileTemplates: {
|
|
26
27
|
enabled: response.cftEnabled,
|
package/dist/commands/new.js
CHANGED
|
@@ -45,11 +45,15 @@ async function configureYarnRc(location, name, value) {
|
|
|
45
45
|
return true;
|
|
46
46
|
}
|
|
47
47
|
async function installYarnV3(location, verbose) {
|
|
48
|
-
const
|
|
48
|
+
const valueSetVersion = await execa('yarn', ['set', 'version', 'berry'], {
|
|
49
49
|
stdio: verbose ? 'inherit' : undefined,
|
|
50
50
|
cwd: `./${location}/`
|
|
51
51
|
});
|
|
52
|
-
|
|
52
|
+
const valueInstallPlugins = await execa('yarn', ['plugin', 'import', 'interactive-tools'], {
|
|
53
|
+
stdio: verbose ? 'inherit' : undefined,
|
|
54
|
+
cwd: `./${location}/`
|
|
55
|
+
});
|
|
56
|
+
if (valueSetVersion.exitCode !== 0 || valueInstallPlugins.exitCode !== 0) {
|
|
53
57
|
throw new Error('An unknown error occurred while installing Yarn v3. Try running Sapphire CLI with "--verbose" flag.');
|
|
54
58
|
}
|
|
55
59
|
await Promise.all([
|
|
@@ -6,35 +6,45 @@ export async function CreateFileFromTemplate(template, target, config, params, c
|
|
|
6
6
|
const location = custom ? template : `${templatesFolder}${template}`;
|
|
7
7
|
const output = {};
|
|
8
8
|
if (component) {
|
|
9
|
-
const [
|
|
10
|
-
output.
|
|
11
|
-
output.
|
|
9
|
+
const [config, templateContent] = await getComponentTemplateWithConfig(location);
|
|
10
|
+
output.config = config;
|
|
11
|
+
output.templateContent = templateContent;
|
|
12
12
|
}
|
|
13
|
-
output.
|
|
14
|
-
if (!output.
|
|
15
|
-
throw new Error("
|
|
13
|
+
output.templateContent ??= await readFile(location, 'utf8');
|
|
14
|
+
if (!output.templateContent) {
|
|
15
|
+
throw new Error("Couldn't read the template file. Are you sure it exists, the name is correct, and the content is valid?");
|
|
16
16
|
}
|
|
17
17
|
if (params) {
|
|
18
18
|
for (const param of Object.entries(params)) {
|
|
19
|
-
output.
|
|
19
|
+
output.templateContent = output.templateContent.replaceAll(`{{${param[0]}}}`, param[1]);
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
if (!output || (component && (!output.
|
|
23
|
-
throw new Error('
|
|
22
|
+
if (!output || (component && (!output.config || !output.config.category))) {
|
|
23
|
+
throw new Error('The template is invalid. Please create a valid template structure.');
|
|
24
24
|
}
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
if (await fileExists(
|
|
28
|
-
throw new Error('
|
|
25
|
+
const directoryForOutput = component ? config?.locations[output.config.category] : null;
|
|
26
|
+
const targetPath = component ? target.replace('%L%', directoryForOutput) : target;
|
|
27
|
+
if (await fileExists(targetPath)) {
|
|
28
|
+
throw new Error('A component with the provided name already exists. Please provide a unique name.');
|
|
29
29
|
}
|
|
30
|
-
await writeFileRecursive(
|
|
30
|
+
await writeFileRecursive(targetPath, output.templateContent);
|
|
31
31
|
return true;
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Gets the template and the config from a component template
|
|
35
|
+
* @param path Path to the template
|
|
36
|
+
* @returns [config, template] The config and the template
|
|
37
|
+
*/
|
|
33
38
|
async function getComponentTemplateWithConfig(path) {
|
|
34
39
|
const file = await readFile(path, 'utf8');
|
|
35
40
|
const fa = file.split(/---(\r\n|\r|\n|)/gm);
|
|
36
41
|
return [JSON.parse(fa[0]), fa[2]];
|
|
37
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Writes a file recursively
|
|
45
|
+
* @param target Target path
|
|
46
|
+
* @param data Data to write
|
|
47
|
+
*/
|
|
38
48
|
async function writeFileRecursive(target, data) {
|
|
39
49
|
const resolvedTarget = resolve(target);
|
|
40
50
|
const dir = dirname(resolvedTarget);
|
|
@@ -47,6 +47,12 @@ export const PromptInit = [
|
|
|
47
47
|
message: 'Where do you store your preconditions? (do not include the base)',
|
|
48
48
|
initial: 'preconditions'
|
|
49
49
|
},
|
|
50
|
+
{
|
|
51
|
+
type: 'text',
|
|
52
|
+
name: 'interaction-handlers',
|
|
53
|
+
message: 'Where do you store your interaction handlers? (do not include the base)',
|
|
54
|
+
initial: 'interaction-handlers'
|
|
55
|
+
},
|
|
50
56
|
{
|
|
51
57
|
type: 'confirm',
|
|
52
58
|
name: 'cftEnabled',
|
|
@@ -63,7 +63,8 @@ export const PromptNew = (projectName, yarn, pnpm) => {
|
|
|
63
63
|
{
|
|
64
64
|
type: (prev) => (prev === 'Yarn' ? 'confirm' : false),
|
|
65
65
|
name: 'yarnV3',
|
|
66
|
-
message: 'Do you want to use Yarn v3?'
|
|
66
|
+
message: 'Do you want to use Yarn v3?',
|
|
67
|
+
initial: true
|
|
67
68
|
},
|
|
68
69
|
{
|
|
69
70
|
type: 'confirm',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sapphire/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0-next.52e7dec.0",
|
|
4
4
|
"description": "CLI for Sapphire Framework",
|
|
5
5
|
"author": "@sapphire",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,7 +48,10 @@
|
|
|
48
48
|
"@commitlint/config-conventional": "^17.4.4",
|
|
49
49
|
"@favware/cliff-jumper": "^2.0.0",
|
|
50
50
|
"@favware/npm-deprecate": "^1.0.7",
|
|
51
|
+
"@sapphire/decorators": "*",
|
|
51
52
|
"@sapphire/eslint-config": "^4.4.0",
|
|
53
|
+
"@sapphire/framework": "*",
|
|
54
|
+
"@sapphire/plugin-api": "*",
|
|
52
55
|
"@sapphire/prettier-config": "^1.4.5",
|
|
53
56
|
"@sapphire/ts-config": "^4.0.0",
|
|
54
57
|
"@types/js-yaml": "^4.0.5",
|
|
@@ -57,10 +60,11 @@
|
|
|
57
60
|
"@typescript-eslint/eslint-plugin": "^5.58.0",
|
|
58
61
|
"@typescript-eslint/parser": "^5.58.0",
|
|
59
62
|
"cz-conventional-changelog": "^3.3.0",
|
|
63
|
+
"discord.js": "*",
|
|
60
64
|
"eslint": "^8.38.0",
|
|
61
65
|
"eslint-config-prettier": "^8.8.0",
|
|
62
66
|
"eslint-plugin-prettier": "^4.2.1",
|
|
63
|
-
"globby": "^13.1.
|
|
67
|
+
"globby": "^13.1.4",
|
|
64
68
|
"husky": "^8.0.3",
|
|
65
69
|
"lint-staged": "^13.2.1",
|
|
66
70
|
"pinst": "^3.0.0",
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
"arguments": "arguments",
|
|
6
6
|
"commands": "commands",
|
|
7
7
|
"listeners": "listeners",
|
|
8
|
-
"preconditions": "preconditions"
|
|
9
|
-
"
|
|
8
|
+
"preconditions": "preconditions",
|
|
9
|
+
"interaction-handlers": "interaction-handlers",
|
|
10
|
+
"routes": "routes"
|
|
10
11
|
},
|
|
11
12
|
"customFileTemplates": {
|
|
12
13
|
"enabled": false,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{ "category": "arguments" }
|
|
2
2
|
---
|
|
3
3
|
import { ApplyOptions } from '@sapphire/decorators';
|
|
4
|
-
import { Argument
|
|
4
|
+
import { Argument } from '@sapphire/framework';
|
|
5
5
|
|
|
6
|
-
@ApplyOptions<
|
|
6
|
+
@ApplyOptions<Argument.Options>({})
|
|
7
7
|
export class UserArgument extends Argument<string> {
|
|
8
|
-
|
|
8
|
+
public override run(parameter: string) {
|
|
9
9
|
return this.ok(parameter);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{ "category": "interaction-handlers" }
|
|
2
|
+
---
|
|
3
|
+
const { InteractionHandler, InteractionHandlerTypes } = require('@sapphire/framework');
|
|
4
|
+
const { InteractionHandler, InteractionHandlerTypes } = require('@sapphire/framework');
|
|
5
|
+
|
|
6
|
+
class AutocompleteHandler extends InteractionHandler {
|
|
7
|
+
/**
|
|
8
|
+
* @param {InteractionHandler.Context} context
|
|
9
|
+
* @param {InteractionHandler.Options} options
|
|
10
|
+
*/
|
|
11
|
+
constructor(context, options) {
|
|
12
|
+
super(context, {
|
|
13
|
+
...options,
|
|
14
|
+
interactionHandlerType: InteractionHandlerTypes.Autocomplete
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {import('discord.js').AutocompleteInteraction} interaction
|
|
20
|
+
* @param {import('discord.js').ApplicationCommandOptionChoiceData[]} result
|
|
21
|
+
*/
|
|
22
|
+
async run(interaction, result) {
|
|
23
|
+
return interaction.respond(result);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {import('discord.js').AutocompleteInteraction} interaction
|
|
28
|
+
*/
|
|
29
|
+
async parse(interaction) {
|
|
30
|
+
// Only run this interaction for the command with ID '1000000000000000000'
|
|
31
|
+
if (interaction.commandId !== '1000000000000000000') return this.none();
|
|
32
|
+
// Get the focussed (current) option
|
|
33
|
+
const focusedOption = interaction.options.getFocused(true);
|
|
34
|
+
// Ensure that the option name is one that can be autocompleted, or return none if not.
|
|
35
|
+
switch (focusedOption.name) {
|
|
36
|
+
case 'search': {
|
|
37
|
+
// Search your API or similar. This is example code!
|
|
38
|
+
const searchResult = await myApi.searchForSomething(focusedOption.value);
|
|
39
|
+
// Map the search results to the structure required for Autocomplete
|
|
40
|
+
return this.some(searchResult.map((match) => ({ name: match.name, value: match.key })));
|
|
41
|
+
}
|
|
42
|
+
default:
|
|
43
|
+
return this.none();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
AutocompleteHandler
|
|
50
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{ "category": "interaction-handlers" }
|
|
2
|
+
---
|
|
3
|
+
import { ApplyOptions } from '@sapphire/decorators';
|
|
4
|
+
import { InteractionHandler, InteractionHandlerTypes } from '@sapphire/framework';
|
|
5
|
+
import { AutocompleteInteraction, type ApplicationCommandOptionChoiceData } from 'discord.js';
|
|
6
|
+
|
|
7
|
+
@ApplyOptions<InteractionHandler.Options>({
|
|
8
|
+
interactionHandlerType: InteractionHandlerTypes.Autocomplete
|
|
9
|
+
})
|
|
10
|
+
export class AutocompleteHandler extends InteractionHandler {
|
|
11
|
+
public override async run(interaction: AutocompleteInteraction, result: ApplicationCommandOptionChoiceData[]) {
|
|
12
|
+
return interaction.respond(result);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public override async parse(interaction: AutocompleteInteraction) {
|
|
16
|
+
// Only run this interaction for the command with ID '1000000000000000000'
|
|
17
|
+
if (interaction.commandId !== '1000000000000000000') return this.none();
|
|
18
|
+
// Get the focussed (current) option
|
|
19
|
+
const focusedOption = interaction.options.getFocused(true);
|
|
20
|
+
// Ensure that the option name is one that can be autocompleted, or return none if not.
|
|
21
|
+
switch (focusedOption.name) {
|
|
22
|
+
case 'search': {
|
|
23
|
+
// Search your API or similar. This is example code!
|
|
24
|
+
const searchResult = await myApi.searchForSomething(focusedOption.value);
|
|
25
|
+
// Map the search results to the structure required for Autocomplete
|
|
26
|
+
return this.some(searchResult.map((match) => ({ name: match.name, value: match.key })));
|
|
27
|
+
}
|
|
28
|
+
default:
|
|
29
|
+
return this.none();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{ "category": "interaction-handlers" }
|
|
2
|
+
---
|
|
3
|
+
const { InteractionHandler, InteractionHandlerTypes } = require('@sapphire/framework');
|
|
4
|
+
|
|
5
|
+
class ButtonHandler extends InteractionHandler {
|
|
6
|
+
/**
|
|
7
|
+
* @param {InteractionHandler.Context} context
|
|
8
|
+
* @param {InteractionHandler.Options} options
|
|
9
|
+
*/
|
|
10
|
+
constructor(context, options) {
|
|
11
|
+
super(context, {
|
|
12
|
+
...options,
|
|
13
|
+
interactionHandlerType: InteractionHandlerTypes.Button
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {import('discord.js').ButtonInteraction} interaction
|
|
19
|
+
*/
|
|
20
|
+
async run(interaction) {
|
|
21
|
+
await interaction.reply({
|
|
22
|
+
content: 'Hello from a button interaction handler!',
|
|
23
|
+
// Let's make it so only the person who pressed the button can see this message!
|
|
24
|
+
ephemeral: true
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {import('discord.js').ButtonInteraction} interaction
|
|
30
|
+
*/
|
|
31
|
+
parse(interaction) {
|
|
32
|
+
if (interaction.customId !== 'my-awesome-button') return this.none();
|
|
33
|
+
return this.some();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
ButtonHandler
|
|
39
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{ "category": "interaction-handlers" }
|
|
2
|
+
---
|
|
3
|
+
import { ApplyOptions } from '@sapphire/decorators';
|
|
4
|
+
import { InteractionHandler, InteractionHandlerTypes } from '@sapphire/framework';
|
|
5
|
+
import type { ButtonInteraction } from 'discord.js';
|
|
6
|
+
|
|
7
|
+
@ApplyOptions<InteractionHandler.Options>({
|
|
8
|
+
interactionHandlerType: InteractionHandlerTypes.Button
|
|
9
|
+
})
|
|
10
|
+
export class ButtonHandler extends InteractionHandler {
|
|
11
|
+
public async run(interaction: ButtonInteraction) {
|
|
12
|
+
await interaction.reply({
|
|
13
|
+
content: 'Hello from a button interaction handler!',
|
|
14
|
+
// Let's make it so only the person who pressed the button can see this message!
|
|
15
|
+
ephemeral: true
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public override parse(interaction: ButtonInteraction) {
|
|
20
|
+
if (interaction.customId !== 'my-awesome-button') return this.none();
|
|
21
|
+
|
|
22
|
+
return this.some();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -16,7 +16,7 @@ export class UserCommand extends Command {
|
|
|
16
16
|
);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
public async contextMenuRun(interaction: Command.ContextMenuCommandInteraction) {
|
|
19
|
+
public override async contextMenuRun(interaction: Command.ContextMenuCommandInteraction) {
|
|
20
20
|
return interaction.reply({ content: 'Hello world!' });
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{ "category": "listeners" }
|
|
2
2
|
---
|
|
3
3
|
import { ApplyOptions } from '@sapphire/decorators';
|
|
4
|
-
import { Listener
|
|
4
|
+
import { Listener } from '@sapphire/framework';
|
|
5
5
|
|
|
6
|
-
@ApplyOptions<
|
|
6
|
+
@ApplyOptions<Listener.Options>({})
|
|
7
7
|
export class UserEvent extends Listener {
|
|
8
|
-
public run() {}
|
|
8
|
+
public override run() {}
|
|
9
9
|
}
|
|
@@ -8,7 +8,7 @@ import type { Message } from 'discord.js';
|
|
|
8
8
|
description: 'A basic command'
|
|
9
9
|
})
|
|
10
10
|
export class UserCommand extends Command {
|
|
11
|
-
public async messageRun(message: Message) {
|
|
11
|
+
public override async messageRun(message: Message) {
|
|
12
12
|
return message.channel.send('Hello world!');
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{ "category": "interaction-handlers" }
|
|
2
|
+
---
|
|
3
|
+
const { InteractionHandler, InteractionHandlerTypes } = require('@sapphire/framework');
|
|
4
|
+
|
|
5
|
+
class ModalHandler extends InteractionHandler {
|
|
6
|
+
/**
|
|
7
|
+
* @param {InteractionHandler.Context} context
|
|
8
|
+
* @param {InteractionHandler.Options} options
|
|
9
|
+
*/
|
|
10
|
+
constructor(context, options) {
|
|
11
|
+
super(context, {
|
|
12
|
+
...options,
|
|
13
|
+
interactionHandlerType: InteractionHandlerTypes.ModalSubmit
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {import('discord.js').ModalSubmitInteraction} interaction
|
|
19
|
+
*/
|
|
20
|
+
async run(interaction) {
|
|
21
|
+
await interaction.reply({
|
|
22
|
+
content: 'Thank you for submitting the form!',
|
|
23
|
+
ephemeral: true
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {import('discord.js').ModalSubmitInteraction} interaction
|
|
29
|
+
*/
|
|
30
|
+
parse(interaction) {
|
|
31
|
+
if (interaction.customId !== 'hello-popup') return this.none();
|
|
32
|
+
|
|
33
|
+
return this.some();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
ModalHandler
|
|
39
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{ "category": "interaction-handlers" }
|
|
2
|
+
---
|
|
3
|
+
import { ApplyOptions } from '@sapphire/decorators';
|
|
4
|
+
import { InteractionHandler, InteractionHandlerTypes } from '@sapphire/framework';
|
|
5
|
+
import type { ModalSubmitInteraction } from 'discord.js';
|
|
6
|
+
|
|
7
|
+
@ApplyOptions<InteractionHandler.Options>({
|
|
8
|
+
interactionHandlerType: InteractionHandlerTypes.ModalSubmit
|
|
9
|
+
})
|
|
10
|
+
export class ModalHandler extends InteractionHandler {
|
|
11
|
+
public async run(interaction: ModalSubmitInteraction) {
|
|
12
|
+
await interaction.reply({
|
|
13
|
+
content: 'Thank you for submitting the form!',
|
|
14
|
+
ephemeral: true
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public override parse(interaction: ModalSubmitInteraction) {
|
|
19
|
+
if (interaction.customId !== 'hello-popup') return this.none();
|
|
20
|
+
|
|
21
|
+
return this.some();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{ "category": "interaction-handlers" }
|
|
2
|
+
---
|
|
3
|
+
const { InteractionHandler, InteractionHandlerTypes } = require('@sapphire/framework');
|
|
4
|
+
|
|
5
|
+
class MenuHandler extends InteractionHandler {
|
|
6
|
+
/**
|
|
7
|
+
* @param {InteractionHandler.Context} context
|
|
8
|
+
* @param {InteractionHandler.Options} options
|
|
9
|
+
*/
|
|
10
|
+
constructor(context, options) {
|
|
11
|
+
super(context, {
|
|
12
|
+
...options,
|
|
13
|
+
interactionHandlerType: InteractionHandlerTypes.SelectMenu
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {import('discord.js').StringSelectMenuInteraction} interaction
|
|
19
|
+
*/
|
|
20
|
+
async run(interaction) {
|
|
21
|
+
await interaction.reply({
|
|
22
|
+
// Remember how we can have multiple values? Let's get the first one!
|
|
23
|
+
content: `You selected: ${interaction.values[0]}`
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {import('discord.js').StringSelectMenuInteraction} interaction
|
|
29
|
+
*/
|
|
30
|
+
parse(interaction) {
|
|
31
|
+
if (interaction.customId !== 'my-echo-select') return this.none();
|
|
32
|
+
|
|
33
|
+
return this.some();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
MenuHandler
|
|
39
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{ "category": "interaction-handlers" }
|
|
2
|
+
---
|
|
3
|
+
import { ApplyOptions } from '@sapphire/decorators';
|
|
4
|
+
import { InteractionHandler, InteractionHandlerTypes } from '@sapphire/framework';
|
|
5
|
+
import type { StringSelectMenuInteraction } from 'discord.js';
|
|
6
|
+
|
|
7
|
+
@ApplyOptions<InteractionHandler.Options>({
|
|
8
|
+
interactionHandlerType: InteractionHandlerTypes.SelectMenu
|
|
9
|
+
})
|
|
10
|
+
export class MenuHandler extends InteractionHandler {
|
|
11
|
+
public override async run(interaction: StringSelectMenuInteraction) {
|
|
12
|
+
await interaction.reply({
|
|
13
|
+
// Remember how we can have multiple values? Let's get the first one!
|
|
14
|
+
content: `You selected: ${interaction.values[0]}`
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public override parse(interaction: StringSelectMenuInteraction) {
|
|
19
|
+
if (interaction.customId !== 'my-echo-select') return this.none();
|
|
20
|
+
|
|
21
|
+
return this.some();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -27,11 +27,14 @@
|
|
|
27
27
|
"preconditions": {
|
|
28
28
|
"type": "string"
|
|
29
29
|
},
|
|
30
|
+
"interaction-handlers": {
|
|
31
|
+
"type": "string"
|
|
32
|
+
},
|
|
30
33
|
"routes": {
|
|
31
34
|
"type": "string"
|
|
32
35
|
}
|
|
33
36
|
},
|
|
34
|
-
"required": ["base", "arguments", "commands", "listeners", "preconditions"]
|
|
37
|
+
"required": ["base", "arguments", "commands", "listeners", "preconditions", "interaction-handlers"]
|
|
35
38
|
},
|
|
36
39
|
"customFileTemplates": {
|
|
37
40
|
"description": "Settings about custom component (piece) templates",
|