Skip to content

Commit

Permalink
Add Multiple Interaction Types to Discord Module
Browse files Browse the repository at this point in the history
  • Loading branch information
GaryCraft committed Apr 24, 2024
1 parent b97b4ff commit 79c1683
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 24 deletions.
51 changes: 46 additions & 5 deletions src/modules/discord/extendedclient.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useImporterRecursive } from "@src/engine/utils/Importing";
import { warn } from "@src/engine/utils/Logger";
import { getModulePath } from "@src/engine/utils/Runtime";
import { ChatInputCommandInteraction, Client, ClientOptions, Interaction, Message } from "discord.js";
import { ApplicationCommandOptionData, ChatInputCommandInteraction, Client, ClientOptions, Interaction, Message, MessageContextMenuCommandInteraction, MessageInteraction, UserContextMenuCommandInteraction, UserSelectMenuInteraction } from "discord.js";
import { Parseable, ValidateProperty, objectSchemaFrom, validateObject } from "parzival";

@Parseable()
Expand All @@ -23,7 +23,7 @@ export class DSCommand {
}

@Parseable()
export class DSInteraction<T extends Interaction> {
export class BaseDSInteraction<T extends Interaction> {
@ValidateProperty({
type: "string"
})
Expand All @@ -32,6 +32,24 @@ export class DSInteraction<T extends Interaction> {
type: "string"
})
description!: string;

@ValidateProperty({
type: "string"
})
type!: "chat" | "user" | "message";

@ValidateProperty({
type: "string",
optional: true
})
registerTo!: "app" | "guild";

@ValidateProperty({
type: "string",
optional: true
})
options?: ApplicationCommandOptionData[];

@ValidateProperty({
type: "function",
validateArguments: false,
Expand All @@ -43,9 +61,32 @@ export class DSInteraction<T extends Interaction> {
) => void;
}

type ChatDSInteraction = BaseDSInteraction<ChatInputCommandInteraction> & {
type: "chat";
options?: ApplicationCommandOptionData[];
}

type UserDSInteraction = BaseDSInteraction<UserContextMenuCommandInteraction> & {
type: "user";
}

type MessageDSInteraction = BaseDSInteraction<MessageContextMenuCommandInteraction> & {
type: "message";
}

type AnyDSInteraction = ChatDSInteraction | UserDSInteraction | MessageDSInteraction;

type AutoDSInteraction<T extends AnyDSInteraction['type']> =
T extends "chat" ? ChatDSInteraction :
T extends "user" ? UserDSInteraction :
T extends "message" ? MessageDSInteraction :
AnyDSInteraction;

export type DSInteraction = AutoDSInteraction<AnyDSInteraction['type']>;

export default class ExtendedClient extends Client {
commands: Map<string, DSCommand>;
interactions: Map<string, DSInteraction<Interaction>>;
interactions: Map<string, DSInteraction>;
constructor(opts: ClientOptions) {
super(opts);
this.commands = new Map();
Expand All @@ -66,9 +107,9 @@ export default class ExtendedClient extends Client {
async (i, f, d) => {
this.commands.set(i.default.name, i.default);
});
const interactionSchema = objectSchemaFrom(DSInteraction);
const interactionSchema = objectSchemaFrom(BaseDSInteraction);
useImporterRecursive(`${getModulePath("discord")}/interactions`,
function validator(i: any, f, d): i is { default: DSInteraction<Interaction> } {
function validator(i: any, f, d): i is { default: DSInteraction } {
if (!i?.default) {
warn(`Interaction ${f} from ${d} has no default export`);
return false;
Expand Down
37 changes: 19 additions & 18 deletions src/modules/discord/hooks/legacy/interactionCreate.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import { Interaction } from "discord.js";
import ExtendedClient from "../../extendedclient";
import ExtendedClient, { DSInteraction } from "../../extendedclient";
import { error, warn } from "@src/engine/utils/Logger";


export default async (client: ExtendedClient, interaction:Interaction) => {

if(interaction.isButton()) return client.emit(interaction.customId.split("|")[0], {interaction});
export default async (client: ExtendedClient, interaction: Interaction) => {

let inter = null;
if(interaction.isAnySelectMenu()) {
inter = client.interactions.get(interaction.customId.split("|")[0]);
if (!inter) warn(`${client.shard?.ids[0] ?? "Discord Client"}`, `No interaction found for Menu ${interaction.customId}`);
if (interaction.isButton()) return client.emit(interaction.customId.split("|")[0], { interaction });

let execInter: DSInteraction | undefined;
if (interaction.isAnySelectMenu()) {
execInter = client.interactions.get(interaction.customId.split("|")[0]);
if (!execInter) warn(`${client.shard?.ids[0] ?? "Discord Client"}`, `No interaction found for Menu ${interaction.customId}`);
}
if(interaction.isChatInputCommand() || interaction.isContextMenuCommand()){
inter = client.interactions.get(interaction.commandName.replace(/\s/g, "_"));
if (!inter) warn(`${client.shard?.ids[0] ?? "Discord Client"}`, `No interaction found for Command ${interaction.commandName}`);
if (interaction.isChatInputCommand() || interaction.isContextMenuCommand()) {
execInter = client.interactions.get(interaction.commandName.replace(/\s/g, "_"));
if (!execInter) warn(`${client.shard?.ids[0] ?? "Discord Client"}`, `No interaction found for Command ${interaction.commandName}`);
}
if(interaction.isModalSubmit()) {
inter = client.interactions.get(interaction.customId.split("|")[0]);
if (!inter) warn(`${client.shard?.ids[0] ?? "Discord Client"}`, `No interaction found for Modal ${interaction.customId}`);
if (interaction.isModalSubmit()) {
execInter = client.interactions.get(interaction.customId.split("|")[0]);
if (!execInter) warn(`${client.shard?.ids[0] ?? "Discord Client"}`, `No interaction found for Modal ${interaction.customId}`);
}
if(!inter) return;
try{
await inter.execute(client, interaction);
}catch(e){
if (!execInter) return;
try {
// @ts-expect-error Interaction should be still a valid type, but got reduced to never because conflicting ApplicationCommandTypes
await execInter.execute(client, interaction);
} catch (e) {
error(`${client.shard?.ids[0] ?? "Discord Client"}`, "", e);
}
};
4 changes: 3 additions & 1 deletion src/modules/discord/interactions/chat/ping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { DSInteraction } from "../../extendedclient";
export default {
name: "ping",
description: "Ping!",
type: "chat",
registerTo: "app",
async execute(client, interaction) {
interaction.reply("Pong!");
},
} satisfies DSInteraction<ChatInputCommandInteraction>;
} satisfies DSInteraction;

0 comments on commit 79c1683

Please sign in to comment.