Skip to content

Commit fa135d9

Browse files
feat: add survey command
1 parent b979bbf commit fa135d9

File tree

3 files changed

+109
-1
lines changed

3 files changed

+109
-1
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { ActionRowBuilder, ButtonBuilder, HeadingLevel } from "@discordjs/builders";
2+
import { TakesArgument } from "@framework/arguments/ArgumentTypes";
3+
import { ErrorType } from "@framework/arguments/InvalidArgumentError";
4+
import StringArgument from "@framework/arguments/StringArgument";
5+
import type { Buildable } from "@framework/commands/Command";
6+
import { Command } from "@framework/commands/Command";
7+
import type Context from "@framework/commands/Context";
8+
import { ButtonStyle, heading } from "discord.js";
9+
10+
type SurveyCommandArgs = {
11+
name: string;
12+
};
13+
14+
@TakesArgument<SurveyCommandArgs>({
15+
names: ["name"],
16+
types: [StringArgument],
17+
optional: false,
18+
errorMessages: [
19+
{
20+
[ErrorType.Required]: "Please provide a survey name to send!"
21+
}
22+
]
23+
})
24+
class SurveyCommand extends Command {
25+
public override readonly name = "survey";
26+
public override readonly description: string = "Shows a survey form to fill out.";
27+
public override readonly defer = true;
28+
public override readonly usage = ["<name: String>"];
29+
30+
public override build(): Buildable[] {
31+
return [
32+
this.buildChatInput().addStringOption(option =>
33+
option
34+
.setName("name")
35+
.setDescription("The name of the survey to send.")
36+
.setRequired(true)
37+
)
38+
];
39+
}
40+
41+
public override async execute(context: Context, args: SurveyCommandArgs): Promise<void> {
42+
const { name } = args;
43+
44+
const survey = context.config?.survey_system?.surveys[name];
45+
46+
if (!survey) {
47+
await context.error("This survey does not exist.");
48+
return;
49+
}
50+
51+
await context.reply({
52+
ephemeral: true,
53+
content: `${heading(survey.name, HeadingLevel.Two)}\n\n${
54+
survey.description ?? "Please fill out the form by clicking the button below."
55+
}`,
56+
components: [
57+
new ActionRowBuilder<ButtonBuilder>().addComponents(
58+
new ButtonBuilder()
59+
.setCustomId("survey_" + name)
60+
.setLabel("Fill out survey")
61+
.setStyle(ButtonStyle.Secondary)
62+
)
63+
]
64+
});
65+
}
66+
}
67+
68+
export default SurveyCommand;

src/main/typescript/types/GuildConfigSchema.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
import { LoggingSchema } from "@main/types/LoggingSchema";
21+
import { SurveySystemConfig } from "@main/types/SurveySystemConfig";
2122
import { z } from "zod";
2223
import { MessageRuleSchema } from "./MessageRuleSchema";
2324
import { ModerationAction } from "./ModerationAction";
@@ -166,7 +167,8 @@ export const GuildConfigSchema = z.object({
166167
})
167168
.optional()
168169
})
169-
.optional()
170+
.optional(),
171+
survey_system: SurveySystemConfig.optional()
170172
/*
171173
quickmute: z
172174
.object({
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { zSnowflake } from "@main/types/SnowflakeSchema";
2+
import { z } from "zod";
3+
4+
const SurveyQuestion = z.object({
5+
type: z.enum(["paragraph", "short"]),
6+
question: z.string(),
7+
required: z.boolean().default(true),
8+
maxLength: z.number().int().optional(),
9+
minLength: z.number().int().optional(),
10+
placeholder: z.string().optional(),
11+
default_value: z.string().optional()
12+
});
13+
14+
export const SurveySystemConfig = z.object({
15+
enabled: z.boolean().default(false),
16+
default_log_channel: zSnowflake.optional(),
17+
surveys: z
18+
.record(
19+
z.string().regex(/^[a-z0-9_-]+$/i),
20+
z.object({
21+
name: z.string(),
22+
questions: z.array(SurveyQuestion).nonempty(),
23+
required_channels: z.array(zSnowflake).default([]),
24+
required_roles: z.array(zSnowflake).default([]),
25+
required_permissions: z.array(z.string()).default([]),
26+
required_users: z.array(zSnowflake).default([]),
27+
description: z.string().optional(),
28+
end_message: z.string().optional(),
29+
log_channel: zSnowflake.optional()
30+
})
31+
)
32+
.describe(
33+
`
34+
A record of surveys. The key is the interaction custom ID of the survey, and the value is the survey itself.
35+
`
36+
)
37+
.default({})
38+
});

0 commit comments

Comments
 (0)