Skip to content

Commit

Permalink
Add command to submit anonymous feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
LamboCreeper committed Aug 6, 2024
1 parent 3ce2d88 commit f88e59f
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 0 deletions.
70 changes: 70 additions & 0 deletions src/commands/FeedbackCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Discord, ModalComponent, Slash } from "discordx";
import {
ActionRowBuilder,
CommandInteraction,
EmbedBuilder,
ModalBuilder,
ModalSubmitInteraction, TextChannel,
TextInputBuilder
} from "discord.js";
import getConfigValue from "../utils/getConfigValue";

@Discord()
class FeedbackCommand {
@Slash({
name: "feedback",
description: "Leave anonymous feedback around the community"
})
async onInteract(
interaction: CommandInteraction
): Promise<void> {
const modal = new ModalBuilder()
.setTitle("Anonymous Feedback")
.setCustomId("feedback-form");

const feedbackInput = new TextInputBuilder()
.setCustomId("feedback-input")
.setLabel("Your Feedback")
.setStyle(2);

modal.addComponents(
new ActionRowBuilder<TextInputBuilder>().addComponents(
feedbackInput
)
);

await interaction.showModal(modal);
}

@ModalComponent({
id: "feedback-form"
})
async onModalSubmit(interaction: ModalSubmitInteraction): Promise<void> {
const [feedbackInput] = ["feedback-input"].map(id => interaction.fields.getTextInputValue(id));

const feedbackChannelId = getConfigValue<string>("FEEDBACK_CHANNEL");
const feedbackChannel = await interaction.guild?.channels.fetch(feedbackChannelId) as TextChannel;

const embed = new EmbedBuilder()

embed.setTitle("New Anonymous Feedback");
embed.setDescription(feedbackInput);

const message = await feedbackChannel?.send({
embeds: [embed]
});

await message.startThread({
name: "Discuss Anonymous Feedback",
});

await interaction.reply({
content: `Thank you, the following feedback has been submitted:`,
ephemeral: true,
embeds: [embed]
});
}
}


export default FeedbackCommand;
1 change: 1 addition & 0 deletions src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"SHOWCASE_CHANNEL_ID": "240892912186032129",
"AUTHENTICATION_MESSAGE_ID": "592316062796873738",
"AUTHENTICATION_MESSAGE_CHANNEL": "592087564295471105",
"FEEDBACK_CHANNEL": "1270488816070692884",
"INSTANT_ANSWER_HIGHLIGHTS": [
"javascript",
"html",
Expand Down
114 changes: 114 additions & 0 deletions test/commands/FeedbackCommandTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import {createSandbox, SinonSandbox, SinonStub} from "sinon";
import FeedbackCommand from "../../src/commands/FeedbackCommand";
import {CommandInteraction, ModalSubmitInteraction} from "discord.js";
import {expect} from "chai";

describe("FeedbackCommand", () => {
let sandbox: SinonSandbox;
let command: FeedbackCommand;

beforeEach(() => {
sandbox = createSandbox();
command = new FeedbackCommand();
});

afterEach(() => sandbox.restore());

describe("onInteract()", () => {
it("sends a feedback modal to the user", async () => {
const showModalMock = sandbox.stub();

await command.onInteract({
showModal: showModalMock
} as unknown as CommandInteraction);

expect(showModalMock.calledOnce).to.be.true;
expect(JSON.stringify(showModalMock.args[0][0])).to.equal(JSON.stringify({
title: "Anonymous Feedback",
custom_id: "feedback-form",
components: [
{
type: 1,
components: [
{
type: 4,
custom_id: "feedback-input",
label: "Your Feedback",
style: 2
}
]
}
]
}));
});
});

describe("onModalSubmit()", () => {
let interaction: ModalSubmitInteraction;
let startThreadMock: SinonStub;
let sendMock: SinonStub;
let replyMock: SinonStub;
let fetchMock: SinonStub;

beforeEach(() => {
startThreadMock = sandbox.stub();
replyMock = sandbox.stub();

sendMock = sandbox.stub().resolves({
startThread: startThreadMock
});

fetchMock = sandbox.stub().resolves({
send: sendMock
});

interaction = {
fields: {
getTextInputValue: (_id: string) => 'Feedback submitted goes here'
},
guild: {
channels: {
fetch: fetchMock
}
},
reply: replyMock
} as unknown as ModalSubmitInteraction
})

it("sends a copy of the feedback to the feedback channel and creates a thread", async () => {
await command.onModalSubmit(interaction);

expect(fetchMock.calledOnce).to.be.true;

expect(sendMock.calledOnce).to.be.true;
expect(JSON.stringify(sendMock.args[0][0])).to.equal(JSON.stringify({
embeds: [
{
title: "New Anonymous Feedback",
description: "Feedback submitted goes here"
}
]
}));

expect(startThreadMock.calledOnce).to.be.true;
});

it("sends a copy of the feedback to the submitter", async () => {
await command.onModalSubmit(interaction);

expect(fetchMock.calledOnce).to.be.true;

expect(replyMock.calledOnce).to.be.true;
expect(JSON.stringify(replyMock.args[0][0])).to.equal(JSON.stringify({
content: "Thank you, the following feedback has been submitted:",
ephemeral: true,
embeds: [
{
title: "New Anonymous Feedback",
description: "Feedback submitted goes here"
}
]
}));
});
});
});

0 comments on commit f88e59f

Please sign in to comment.