feat(polish): Adds EmbedLibrary

This commit is contained in:
Michel Fedde 2025-06-24 21:59:55 +02:00
parent cf9c88a2d6
commit b3d0b3a90c
12 changed files with 240 additions and 136 deletions

View file

@ -5,9 +5,11 @@ import {
GuildMember,
GuildMemberRoleManager,
InteractionReplyOptions,
MessageFlags, PermissionFlagsBits,
MessageFlags,
PermissionFlagsBits,
roleMention,
SlashCommandBuilder, Snowflake,
SlashCommandBuilder,
Snowflake,
time,
userMention
} from "discord.js";
@ -23,7 +25,6 @@ import {PlaydateRepository} from "../../Database/Repositories/PlaydateRepository
import {Nullable} from "../../types/Nullable";
import {MenuRenderer} from "../../Menu/MenuRenderer";
import {MenuItemType} from "../../Menu/MenuRenderer.types";
import {ConfigurationMenuHandler} from "../../Configuration/Groups/ConfigurationMenuHandler";
import {MenuTraversal} from "../../Menu/MenuTraversal";
import {ConfigurationHandler} from "../../Configuration/ConfigurationHandler";
import {GroupConfigurationProvider} from "../../Configuration/Groups/GroupConfigurationProvider";
@ -31,6 +32,7 @@ import {MenuHandler} from "../../Configuration/MenuHandler";
import {ServerConfigurationProvider} from "../../Configuration/Server/ServerConfigurationProvider";
import {ServerConfigurationRepository} from "../../Database/Repositories/ServerConfigurationRepository";
import {PermissionError} from "../PermissionError";
import {EmbedLibrary, EmbedType} from "../EmbedLibrary";
export class GroupCommand implements Command, ChatInteractionCommand, AutocompleteCommand {
private static GOODBYE_MESSAGES: string[] = [
@ -155,7 +157,16 @@ export class GroupCommand implements Command, ChatInteractionCommand, Autocomple
Container.get<GroupRepository>(GroupRepository.name).create(group);
interaction.reply({content: `:white_check_mark: Created group \`${name}\``, flags: MessageFlags.Ephemeral})
interaction.reply({
embeds: [
EmbedLibrary.base(
'Created group',
`:white_check_mark: Created group \`${name}\``,
EmbedType.Success
)
],
flags: MessageFlags.Ephemeral
})
}
private allowedCreate(interaction: ChatInputCommandInteraction): boolean {
@ -192,8 +203,7 @@ export class GroupCommand implements Command, ChatInteractionCommand, Autocomple
const playdateRepo = Container.get<PlaydateRepository>(PlaydateRepository.name);
const embed = new EmbedBuilder()
.setTitle("Your groups on this server:")
const embed = EmbedLibrary.base("Your groups on this server:", '', EmbedType.Info)
.setFields(
groups.map(group => {
const nextPlaydate = playdateRepo.getNextPlaydateForGroup(group);
@ -236,16 +246,14 @@ export class GroupCommand implements Command, ChatInteractionCommand, Autocomple
}
repo.deleteGroup(group);
const embed = new EmbedBuilder()
.setTitle("Group deleted.")
.setDescription(
`:x: Deleted \`${group.name}\`. ${ArrayUtils.chooseRandom(GroupCommand.GOODBYE_MESSAGES)}`
)
await interaction.reply({
embeds: [
embed
EmbedLibrary.base(
"Group deleted",
`:x: Deleted \`${group.name}\`. ${ArrayUtils.chooseRandom(GroupCommand.GOODBYE_MESSAGES)}`,
EmbedType.Success
)
],
flags: MessageFlags.Ephemeral,
})
@ -332,7 +340,9 @@ export class GroupCommand implements Command, ChatInteractionCommand, Autocomple
),
'Group Configuration',
"This UI allows you to change settings for your group."
)
),
null,null,
group.name
)
menu.display(interaction);
@ -358,17 +368,14 @@ export class GroupCommand implements Command, ChatInteractionCommand, Autocomple
group.leader.memberid = newLeader.id
repo.update(group);
const embed = new EmbedBuilder()
.setTitle("Leadership transferred")
.setDescription(
`Leadership was successfully transferred to ${userMention(newLeader.user.id)}`
)
await interaction.reply({
embeds: [
embed
EmbedLibrary.base(
'Leadership transferred',
`Leadership was successfully transferred to ${userMention(newLeader.user.id)}`,
EmbedType.Success
)
],
flags: MessageFlags.Ephemeral,
})

View file

@ -1,13 +1,13 @@
import {
SlashCommandBuilder,
CommandInteraction,
AutocompleteInteraction,
EmbedBuilder,
MessageFlags,
ChatInputCommandInteraction,
time,
AttachmentBuilder,
GuildMember
AutocompleteInteraction,
ChatInputCommandInteraction,
CommandInteraction,
EmbedBuilder,
GuildMember,
MessageFlags,
SlashCommandBuilder,
time
} from "discord.js";
import {AutocompleteCommand, ChatInteractionCommand, Command} from "./Command";
import {Container} from "../../Container/Container";
@ -20,9 +20,15 @@ import * as ics from 'ics';
import ical from 'node-ical';
import {GroupConfigurationRepository} from "../../Database/Repositories/GroupConfigurationRepository";
import {GroupRepository} from "../../Database/Repositories/GroupRepository";
import {GroupConfigurationProvider} from "../../Configuration/Groups/GroupConfigurationProvider";
import { ConfigurationHandler } from "../../Configuration/ConfigurationHandler";
import {
GroupConfigurationProvider,
RuntimeGroupConfiguration
} from "../../Configuration/Groups/GroupConfigurationProvider";
import {ConfigurationHandler} from "../../Configuration/ConfigurationHandler";
import {PermissionError} from "../PermissionError";
import {EmbedLibrary, EmbedType} from "../EmbedLibrary";
import {GroupConfigurationModel} from "../../Database/Models/GroupConfigurationModel";
import parser from "any-date-parser";
export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInteractionCommand {
definition(): SlashCommandBuilder {
@ -36,11 +42,11 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
.addIntegerOption(GroupSelection.createOptionSetup())
.addStringOption((option) => option
.setName("from")
.setDescription("Defines the start date & time. Format: YYYY-MM-DD HH:mm")
.setDescription("Defines the start date & time. Your desired format is probably support.")
)
.addStringOption((option) => option
.setName("to")
.setDescription("Defines the end date & time. Format: YYYY-MM-DD HH:mm")
.setDescription("Defines the end date & time. Your desired format is probably support.")
)
)
.addSubcommand((subcommand) => subcommand
@ -117,18 +123,18 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
)
}
const fromDate = Date.parse(<string>interaction.options.get("from")?.value ?? '');
const toDate = Date.parse(<string>interaction.options.get("to")?.value ?? '');
const fromDate = parser.fromString(<string>interaction.options.get("from")?.value ?? '');
const toDate = parser.fromString(<string>interaction.options.get("to")?.value ?? '');
if (isNaN(fromDate)) {
if (!fromDate.isValid()) {
throw new UserError("No date or invalid date format for the from parameter.");
}
if (isNaN(toDate)) {
if (!fromDate.isValid()) {
throw new UserError("No date or invalid date format for the to parameter.");
}
if (fromDate > toDate) {
if (fromDate.getTime() > toDate.getTime()) {
throw new UserError("The to-date can't be earlier than the from-date");
}
@ -141,22 +147,21 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
const playdate: Partial<PlaydateModel> = {
group: group,
from_time: new Date(fromDate),
to_time: new Date(toDate),
from_time: fromDate,
to_time: toDate,
}
playdateRepo.create(playdate);
const embed = new EmbedBuilder()
.setTitle("Created a play-date.")
.setDescription(":white_check_mark: Your playdate has been created! You and your group get notified, when its time.")
.setFields({
const embed = EmbedLibrary.playdate(
group,
"Created a play-date.",
":white_check_mark: Your playdate has been created! You and your group get notified, when its time.",
EmbedType.Success
).setFields({
name: "Created playdate",
value: `${time(new Date(fromDate), 'F')} - ${time(new Date(toDate), 'F')}`,
})
.setFooter({
text: `Group: ${group.name}`
})
})
await interaction.reply({
embeds: [
@ -193,20 +198,20 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
private async list(interaction: ChatInputCommandInteraction, group: GroupModel) {
const playdates = Container.get<PlaydateRepository>(PlaydateRepository.name).findFromGroup(group);
const embed = new EmbedBuilder()
.setTitle("The next playdates:")
.setFields(
playdates.map((playdate) => {
return {
name: `${time(playdate.from_time, 'F')} - ${time(playdate.to_time, 'F')}`,
value: `${time(playdate.from_time, 'R')}`
}
})
)
.setFooter({
text: `Group: ${group.name}`
const embed = EmbedLibrary.playdate(
group,
"Created a play-date.",
null,
EmbedType.Info
).setFields(
playdates.map((playdate) => {
return {
name: `${time(playdate.from_time, 'F')} - ${time(playdate.to_time, 'F')}`,
value: `${time(playdate.from_time, 'R')}`
}
})
)
await interaction.reply({
embeds: [
embed
@ -236,16 +241,13 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
}
repo.delete(playdateId);
const embed = new EmbedBuilder()
.setTitle("Playdate deleted")
.setDescription(
`:x: Deleted \`${selected.from_time.toLocaleString()} - ${selected.to_time.toLocaleString()}\``
)
.setFooter({
text: `Group: ${group.name}`
})
const embed = EmbedLibrary.playdate(
group,
"Playdate deleted",
`:x: Deleted ${time(selected.from_time, 'F')} - ${time(selected.to_time, 'F')}`,
EmbedType.Success
);
await interaction.reply({
embeds: [
embed
@ -294,16 +296,15 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
});
}
const embed = new EmbedBuilder()
.setTitle("Imported play-dates.")
.setDescription(`:white_check_mark: Your ${playdates.length} playdates has been created! You and your group get notified, when its time.`)
.setFields({
name: "Created playdates",
value: playdates.map((playdate) => `${time(playdate.from_time, 'F')} - ${time(playdate.to_time, 'F')}`).join('\n')
})
.setFooter({
text: `Group: ${group.name}`
})
const embed = EmbedLibrary.playdate(
group,
"Imported play-dates",
`:white_check_mark: Your ${playdates.length} playdates has been created! You and your group get notified, when its time.`,
EmbedType.Success
).setFields({
name: "Created playdates",
value: playdates.map((playdate) => `${time(playdate.from_time, 'F')} - ${time(playdate.to_time, 'F')}`).join('\n')
})
interaction.followUp({
embeds: [embed],
@ -312,7 +313,10 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
}
private async export(interaction: ChatInputCommandInteraction, group: GroupModel): Promise<void> {
const groupConfig = new ConfigurationHandler(
const groupConfig = new ConfigurationHandler<
GroupConfigurationModel,
RuntimeGroupConfiguration
>(
new GroupConfigurationProvider(
Container.get<GroupConfigurationRepository>(GroupConfigurationRepository.name),
group

View file

@ -60,7 +60,7 @@ export class ServerCommand implements Command, ChatInteractionCommand {
children: [
{
traversalKey: "allowEveryone",
label: "Group Creation",
label: "Allow Anyone",
description: "Defines if all members are allowed to create groups.",
}
]
@ -71,7 +71,10 @@ export class ServerCommand implements Command, ChatInteractionCommand {
),
'Server Configuration',
"This UI allows you to change settings for your server."
)
),
null,
null,
"Server"
)
menu.display(interaction);