Adds Deletion
This commit is contained in:
parent
a0b668cb90
commit
0d9cf6a370
8 changed files with 174 additions and 35 deletions
34
source/Database/tables/GroupConfiguration.ts
Normal file
34
source/Database/tables/GroupConfiguration.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import {DatabaseDefinition} from "../DatabaseDefinition";
|
||||
|
||||
export type DBGroup = {
|
||||
id: number;
|
||||
groupid: number;
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
const dbDefinition: DatabaseDefinition = {
|
||||
name: "groups",
|
||||
columns: [
|
||||
{
|
||||
name: "id",
|
||||
type: "INTEGER",
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: "groupid",
|
||||
type: "VARCHAR(32)",
|
||||
},
|
||||
{
|
||||
name: "key",
|
||||
type: "VARCHAR(32)",
|
||||
},
|
||||
{
|
||||
name: "value",
|
||||
type: "VARCHAR(128)",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export default dbDefinition;
|
||||
|
|
@ -2,7 +2,7 @@ import {
|
|||
AutocompleteInteraction,
|
||||
ChatInputCommandInteraction,
|
||||
CommandInteraction,
|
||||
GuildMember,
|
||||
GuildMember, SlashCommandIntegerOption,
|
||||
SlashCommandStringOption
|
||||
} from "discord.js";
|
||||
import {Container} from "../../Container/Container";
|
||||
|
|
@ -11,32 +11,32 @@ import {GroupModel} from "../../Models/GroupModel";
|
|||
import {UserError} from "../UserError";
|
||||
|
||||
export class GroupSelection {
|
||||
public static createOptionSetup(): SlashCommandStringOption {
|
||||
return new SlashCommandStringOption()
|
||||
public static createOptionSetup(): SlashCommandIntegerOption {
|
||||
return new SlashCommandIntegerOption()
|
||||
.setName("group")
|
||||
.setDescription("Defines the group you want to manage the playdates for")
|
||||
.setRequired(true)
|
||||
.setAutocomplete(true)
|
||||
}
|
||||
|
||||
public static async handleAutocomplete(interaction: AutocompleteInteraction): Promise<void> {
|
||||
public static async handleAutocomplete(interaction: AutocompleteInteraction, onlyLeaders: boolean = false): Promise<void> {
|
||||
const value = interaction.options.getFocused();
|
||||
const repo = Container.get<GroupRepository>(GroupRepository.name);
|
||||
const groups = repo.findGroupsByMember(<GuildMember>interaction.member);
|
||||
let groups = repo.findGroupsByMember(<GuildMember>interaction.member, onlyLeaders);
|
||||
await interaction.respond(
|
||||
groups
|
||||
.filter((group) => group.name.startsWith(value))
|
||||
.map((group) => ({name: group.name, value: group.name }))
|
||||
.map((group) => ({name: group.name, value: group.id }))
|
||||
)
|
||||
}
|
||||
|
||||
public static getGroup(interaction: CommandInteraction): GroupModel {
|
||||
const groupname = interaction.options.get("group");
|
||||
const groupname = interaction.options.get("group", true);
|
||||
if (!groupname) {
|
||||
throw new UserError("No group name provided");
|
||||
}
|
||||
|
||||
const group = Container.get<GroupRepository>(GroupRepository.name).findGroupByName((groupname.value ?? '').toString());
|
||||
const group = Container.get<GroupRepository>(GroupRepository.name).getById(<number>(groupname.value ?? 0));
|
||||
if (!group) {
|
||||
throw new UserError("No group found");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,25 @@ import {
|
|||
Interaction,
|
||||
CommandInteraction,
|
||||
ChatInputCommandInteraction,
|
||||
MessageFlags, GuildMemberRoleManager, InteractionReplyOptions, GuildMember
|
||||
MessageFlags, GuildMemberRoleManager, InteractionReplyOptions, GuildMember, EmbedBuilder, AutocompleteInteraction
|
||||
} from "discord.js";
|
||||
import {ChatInteractionCommand, Command} from "./Command";
|
||||
import {AutocompleteCommand, ChatInteractionCommand, Command} from "./Command";
|
||||
import {GroupModel} from "../../Models/GroupModel";
|
||||
import {GroupRepository} from "../../Repositories/GroupRepository";
|
||||
import {DatabaseConnection} from "../../Database/DatabaseConnection";
|
||||
import {Container} from "../../Container/Container";
|
||||
import {GroupSelection} from "../CommandPartials/GroupSelection";
|
||||
import {UserError} from "../UserError";
|
||||
import {ArrayUtils} from "../../Utilities/ArrayUtils";
|
||||
|
||||
export class GroupCommand implements Command, ChatInteractionCommand, AutocompleteCommand {
|
||||
private static GOODBYE_MESSAGES: string[] = [
|
||||
'Sad to see you go.',
|
||||
'May your next adventure be fruitful.',
|
||||
'I hope, I served you well.',
|
||||
'I wish you, good luck on your next adventures.',
|
||||
]
|
||||
|
||||
export class GroupCommand implements Command, ChatInteractionCommand {
|
||||
definition(): SlashCommandBuilder {
|
||||
// @ts-ignore
|
||||
return new SlashCommandBuilder()
|
||||
|
|
@ -35,8 +45,17 @@ export class GroupCommand implements Command, ChatInteractionCommand {
|
|||
listCommand
|
||||
.setName("list")
|
||||
.setDescription("Displays the groups you are apart of.")
|
||||
)
|
||||
.addSubcommand(command => command
|
||||
.setName('config')
|
||||
.setDescription("Starts the config manager for the group.")
|
||||
.addIntegerOption(GroupSelection.createOptionSetup())
|
||||
)
|
||||
.addSubcommand(command => command
|
||||
.setName("remove")
|
||||
.setDescription("Deletes a group you are the leader for.")
|
||||
.addIntegerOption(GroupSelection.createOptionSetup())
|
||||
);
|
||||
|
||||
}
|
||||
execute(interaction: ChatInputCommandInteraction): Promise<void> {
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
|
|
@ -46,6 +65,11 @@ export class GroupCommand implements Command, ChatInteractionCommand {
|
|||
case "list":
|
||||
this.list(interaction);
|
||||
break;
|
||||
case "remove":
|
||||
this.remove(interaction);
|
||||
break;
|
||||
case "config":
|
||||
this.runConfigurator(interaction);
|
||||
default:
|
||||
throw new Error("Unsupported command");
|
||||
}
|
||||
|
|
@ -79,22 +103,65 @@ export class GroupCommand implements Command, ChatInteractionCommand {
|
|||
const repo = Container.get<GroupRepository>(GroupRepository.name);
|
||||
const groups = repo.findGroupsByMember(<GuildMember>interaction.member);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("Your groups on this server:")
|
||||
.setFields(
|
||||
groups.map(group => {
|
||||
return {
|
||||
name: group.name,
|
||||
value: `
|
||||
Role: <@&${group.role.roleid}>
|
||||
`
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const reply: InteractionReplyOptions = {
|
||||
embeds: [
|
||||
{
|
||||
title: "Your groups on this server:",
|
||||
|
||||
fields: groups.map((group) => {
|
||||
return {
|
||||
name: group.name,
|
||||
value: ""
|
||||
}
|
||||
})
|
||||
}
|
||||
embed
|
||||
],
|
||||
allowedMentions: { roles: [] },
|
||||
flags: MessageFlags.Ephemeral
|
||||
}
|
||||
|
||||
interaction.reply(reply);
|
||||
}
|
||||
|
||||
private async remove(interaction: ChatInputCommandInteraction) {
|
||||
const group = GroupSelection.getGroup(interaction);
|
||||
|
||||
const repo = Container.get<GroupRepository>(GroupRepository.name);
|
||||
if (group.leader.memberid != interaction.member?.user.id) {
|
||||
throw new UserError("Can't remove group. You are not the leader.");
|
||||
}
|
||||
|
||||
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
|
||||
],
|
||||
flags: MessageFlags.Ephemeral,
|
||||
})
|
||||
}
|
||||
|
||||
async handleAutocomplete(interaction: AutocompleteInteraction): Promise<void> {
|
||||
const option = interaction.options.getFocused(true);
|
||||
if (option.name == "group") {
|
||||
await GroupSelection.handleAutocomplete(interaction, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private runConfigurator(interaction: ChatInputCommandInteraction) {
|
||||
const group = GroupSelection.getGroup(interaction);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
|
|||
.addSubcommand((subcommand) => subcommand
|
||||
.setName("create")
|
||||
.setDescription("Creates a new playdate")
|
||||
.addStringOption(GroupSelection.createOptionSetup())
|
||||
.addIntegerOption(GroupSelection.createOptionSetup())
|
||||
.addStringOption((option) => option
|
||||
.setName("from")
|
||||
.setDescription("Defines the start date & time. Format: YYYY-MM-DD HH:mm")
|
||||
|
|
@ -48,12 +48,12 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
|
|||
.addSubcommand((subcommand) => subcommand
|
||||
.setName("list")
|
||||
.setDescription("Lists all playdates")
|
||||
.addStringOption(GroupSelection.createOptionSetup())
|
||||
.addIntegerOption(GroupSelection.createOptionSetup())
|
||||
)
|
||||
.addSubcommand((subcommand) => subcommand
|
||||
.setName("remove")
|
||||
.setDescription("Removes a playdate")
|
||||
.addStringOption(GroupSelection.createOptionSetup())
|
||||
.addIntegerOption(GroupSelection.createOptionSetup())
|
||||
.addIntegerOption((option) => option
|
||||
.setName("playdate")
|
||||
.setDescription("Selects a playdate")
|
||||
|
|
@ -179,8 +179,6 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
|
|||
throw new UserError("No playdate found");
|
||||
}
|
||||
|
||||
console.log(selected, group);
|
||||
|
||||
if (selected.group?.id != group.id) {
|
||||
throw new UserError("No playdate found");
|
||||
}
|
||||
|
|
|
|||
8
source/Models/GroupConfigurationModel.ts
Normal file
8
source/Models/GroupConfigurationModel.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import {Model} from "./Model";
|
||||
import {GroupModel} from "./GroupModel";
|
||||
|
||||
export interface GroupConfigurationModel extends Model {
|
||||
group: GroupModel;
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@ import Groups, {DBGroup} from "../Database/tables/Groups";
|
|||
import {DatabaseConnection} from "../Database/DatabaseConnection";
|
||||
import {CacheType, CacheTypeReducer, Guild, GuildMember, GuildMemberRoleManager} from "discord.js";
|
||||
import {Nullable} from "../types/Nullable";
|
||||
import {PlaydateRepository} from "./PlaydateRepository";
|
||||
import {Container} from "../Container/Container";
|
||||
|
||||
export class GroupRepository extends Repository<GroupModel, DBGroup> {
|
||||
|
||||
|
|
@ -43,12 +45,31 @@ export class GroupRepository extends Repository<GroupModel, DBGroup> {
|
|||
return dbResult.map((result) => this.convertToModelType(result));
|
||||
}
|
||||
|
||||
public findGroupsByMember(member: GuildMember) {
|
||||
public findGroupsByMember(member: GuildMember, onlyLeader: boolean = false) {
|
||||
if (!member) {
|
||||
throw new Error("Can't find member for guild: none given");
|
||||
}
|
||||
|
||||
return this.findGroupsByRoles(member.guild.id, [...member.roles.cache.keys()])
|
||||
const groups = this.findGroupsByRoles(member.guild.id, [...member.roles.cache.keys()])
|
||||
|
||||
if (!onlyLeader) {
|
||||
return groups;
|
||||
}
|
||||
|
||||
return groups.filter((group: GroupModel) => {
|
||||
return group.leader.memberid === member.id;
|
||||
})
|
||||
}
|
||||
|
||||
public deleteGroup(group: GroupModel): void {
|
||||
this.delete(group.id);
|
||||
|
||||
debugger
|
||||
const repo = Container.get<PlaydateRepository>(PlaydateRepository.name);
|
||||
const playdates = repo.findFromGroup(group, true)
|
||||
playdates.forEach((playdate) => {
|
||||
repo.delete(playdate.id);
|
||||
})
|
||||
}
|
||||
|
||||
protected convertToModelType(intermediateModel: DBGroup | undefined): GroupModel {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {DatabaseConnection} from "../Database/DatabaseConnection";
|
|||
import {GroupRepository} from "./GroupRepository";
|
||||
import {GroupModel} from "../Models/GroupModel";
|
||||
import {Nullable} from "../types/Nullable";
|
||||
import playdate from "../Database/tables/Playdate";
|
||||
|
||||
export class PlaydateRepository extends Repository<PlaydateModel, DBPlaydate> {
|
||||
|
||||
|
|
@ -19,16 +18,22 @@ export class PlaydateRepository extends Repository<PlaydateModel, DBPlaydate> {
|
|||
);
|
||||
}
|
||||
|
||||
findFromGroup(group: GroupModel) {
|
||||
findFromGroup(group: GroupModel, all = false) {
|
||||
let sql = `SELECT * FROM ${this.schema.name} WHERE groupid = ?`;
|
||||
const params = [group.id];
|
||||
|
||||
if (!all) {
|
||||
sql += " AND time_from > ?"
|
||||
params.push(new Date().getTime())
|
||||
}
|
||||
|
||||
const finds = this.database.fetchAll<number, DBPlaydate>(
|
||||
`SELECT * FROM ${this.schema.name} WHERE groupid = ? AND time_from > ?`,
|
||||
group.id,
|
||||
new Date().getTime()
|
||||
sql,
|
||||
...params
|
||||
);
|
||||
|
||||
return finds.map((playdate) => this.convertToModelType(playdate, group));
|
||||
}
|
||||
|
||||
protected convertToModelType(intermediateModel: DBPlaydate | undefined, fixedGroup: Nullable<GroupModel> = null): PlaydateModel {
|
||||
if (!intermediateModel) {
|
||||
throw new Error("Unable to convert the playdate model");
|
||||
|
|
|
|||
6
source/Utilities/ArrayUtils.ts
Normal file
6
source/Utilities/ArrayUtils.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export class ArrayUtils {
|
||||
public static chooseRandom<T>(array: Array<T>):T {
|
||||
const index = Math.floor(Math.random() * array.length);
|
||||
return array[index];
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue