Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
DDB_HOST=localhost
DDB_PORT=5432

DDB_BOT_TOKEN=
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ logs/
.DS_Store
eslint-results.sarif

.env

# Yarn new stuff
.yarn/*
!.yarn/cache
Expand All @@ -22,6 +20,7 @@ eslint-results.sarif
!.yarn/versions

.env*
!.env.local.example
.flaskenv*
!.env.project
!.env.vault
Expand Down
16 changes: 16 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
services:
postgres:
image: postgres:16-alpine
container_name: devden_db
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: password
POSTGRES_DB: database
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped

volumes:
postgres_data:
6 changes: 6 additions & 0 deletions src/Config.prod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ export const config: Config = {
yesEmojiId: "997496973093502986",
noEmojiId: "1012427085798723666",
},
suggest: {
suggestionsChannel: "",
archiveChannel: "",
yesEmojiId: "thumbsup",
noEmojiId: "thumbsdown",
},
pastebin: {
url: "https://paste.developerden.org",
threshold: 20,
Expand Down
6 changes: 6 additions & 0 deletions src/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ export const config: Config = {
yesEmojiId: "thumbsup",
noEmojiId: "thumbsdown",
},
suggest: {
suggestionsChannel: "1407001821674868746",
archiveChannel: "1407001847239016550",
yesEmojiId: "👍",
noEmojiId: "👎",
},
pastebin: prodConfig.pastebin,
branding: {
color: "#ffffff",
Expand Down
6 changes: 6 additions & 0 deletions src/config.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export interface Config {
introductions?: string;
general: string;
};
suggest: {
suggestionsChannel: string;
archiveChannel: string;
yesEmojiId: string;
noEmojiId: string;
};
commands: {
daily: Snowflake;
};
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { initSentry } from "./sentry.js";
import { logger } from "./logging.js";
import { startHealthCheck } from "./healthcheck.js";
import { ModerationModule } from "./modules/moderation/moderation.module.js";
import SuggestModule from "./modules/suggest/suggest.module.js";

const client = new Client({
intents: [
Expand Down Expand Up @@ -56,6 +57,7 @@ export const moduleManager = new ModuleManager(
ShowcaseModule,
TokenScannerModule,
XpModule,
SuggestModule,
ModerationModule,
],
);
Expand Down
115 changes: 115 additions & 0 deletions src/modules/suggest/suggest.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import {
ActionRowBuilder,
ApplicationCommandOptionType,
ApplicationCommandType,
ButtonBuilder,
ButtonStyle,
ChatInputCommandInteraction,
GuildMember,
} from "discord.js";
import { Command } from "djs-slash-helper";
import { config } from "../../Config.js";
import {
createSuggestion,
createSuggestionEmbed,
SUGGESTION_MANAGE_ID,
SUGGESTION_NO_ID,
SUGGESTION_VIEW_VOTES_ID,
SUGGESTION_YES_ID,
} from "./suggest.js";

export const SuggestCommand: Command<ApplicationCommandType.ChatInput> = {
name: "suggest",
description: "Create a suggestion",
type: ApplicationCommandType.ChatInput,
options: [
{
type: ApplicationCommandOptionType.String,
name: "suggestion",
description: "The suggestion",
required: true,
},
],
handle: async (interaction: ChatInputCommandInteraction) => {
if (!interaction.member || !interaction.inGuild()) {
await interaction.reply({
flags: ["Ephemeral"],
content: "We are not in a guild?",
});
}

const member = interaction.member as GuildMember;

await interaction.deferReply({
flags: ["Ephemeral"],
});
// Get the suggestion and optional image
const suggestionText = interaction.options.get("suggestion")
?.value as string;

const suggestionChannel = await interaction.client.channels.fetch(
config.suggest.suggestionsChannel,
);

if (!suggestionChannel) {
await interaction.followUp({
content: "There is no Suggestion channel!",
flags: ["Ephemeral"],
});
return;
}
if (!suggestionChannel.isSendable() || !suggestionChannel.isTextBased()) {
await interaction.followUp({
content:
"The suggestion channel is either not writeable or not a text channel!",
flags: ["Ephemeral"],
});
return;
}

const suggestionId = interaction.id;

const embed = createSuggestionEmbed(suggestionId, member, suggestionText);

const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId(SUGGESTION_YES_ID)
.setStyle(ButtonStyle.Success)
.setEmoji(config.suggest.yesEmojiId),
new ButtonBuilder()
.setCustomId(SUGGESTION_NO_ID)
.setStyle(ButtonStyle.Danger)
.setEmoji(config.suggest.noEmojiId),
new ButtonBuilder()
.setCustomId(SUGGESTION_VIEW_VOTES_ID)
.setStyle(ButtonStyle.Secondary)
.setEmoji("👁")
.setLabel("View Votes"),
new ButtonBuilder()
.setStyle(ButtonStyle.Secondary)
.setCustomId(SUGGESTION_MANAGE_ID)
.setEmoji("🎛"),
);
const response = await suggestionChannel.send({
embeds: [embed],
components: [buttons],
});

await response.startThread({
name: "Suggestion discussion thread",
reason: `User ${member.displayName} created a suggestion`,
});

await interaction.followUp({
content: `Suggestion with the ID \`${suggestionId}\` successfully submitted! See [here](${response.url})`,
flags: ["Ephemeral"],
});

await createSuggestion(
BigInt(suggestionId),
BigInt(member.id),
BigInt(response.id),
suggestionText,
);
},
};
Loading
Loading