slash commands integrated

* sample env and late version incr

* added slash command compatibility

* updated command name

* updated environment sample

* updated interaction comment
This commit is contained in:
Kevin Dang
2024-01-31 10:25:45 -08:00
committed by Kevin Dang
parent b94ff55449
commit 89c19990fa
16 changed files with 311 additions and 192 deletions

View File

@@ -5,6 +5,7 @@ import Events from './events/index.js'
// Import keys/tokens
import Keys from './keys.js'
// initialize the client with the following permissions when logging in
const client = new Client({
intents: [
@@ -32,8 +33,8 @@ const messageHistory = [
registerEvents(client, Events, messageHistory, Keys)
// Try to log in the client
client.login(Keys.clientToken)
.catch((error) => {
console.error('[Login Error]', error);
process.exit(1);
});
await client.login(Keys.clientToken)
.catch((error) => {
console.error('[Login Error]', error)
process.exit(1)
})

6
src/commands/index.ts Normal file
View File

@@ -0,0 +1,6 @@
import { SlashCommand } from '../utils/commands.js'
import { ThreadCreate } from './threadCreate.js'
export default [
ThreadCreate
] as SlashCommand[]

View File

@@ -0,0 +1,28 @@
import { ChannelType, Client, CommandInteraction, TextChannel } from 'discord.js'
import { SlashCommand } from '../utils/commands.js'
export const ThreadCreate: SlashCommand = {
name: 'thread',
description: 'creates a thread and mentions user',
// Query for server information
run: async (client: Client, interaction: CommandInteraction) => {
// fetch the channel
const channel = await client.channels.fetch(interaction.channelId)
if (!channel || channel.type !== ChannelType.GuildText) return
const thread = await (channel as TextChannel).threads.create({
name: `support-${Date.now()}`,
reason: `Support ticket ${Date.now()}`
})
// Send a message in the thread
thread.send(`**User:** ${interaction.user}`)
// user only reply
return interaction.reply({
content: 'I can help you in the Thread below.',
ephemeral: true
})
}
}

View File

@@ -1,9 +1,11 @@
import { Event } from '../utils/index.js'
import interactionCreate from './interactionCreate.js'
import messageCreate from './messageCreate.js'
import ready from './ready.js'
// Centralized export for all events
export default [
ready,
messageCreate
messageCreate,
interactionCreate
] as Event[] // staticly is better ts practice, dynamic exporting is possible

View File

@@ -0,0 +1,19 @@
import { event, Events } from '../utils/index.js'
import commands from '../commands/index.js'
/**
* Interaction creation listener for the client
* @param interaction the interaction received from the server
*/
export default event(Events.InteractionCreate, async ({ log, client }, interaction) => {
if (!interaction.isCommand() || !interaction.isChatInputCommand()) return
log(`Interaction called \'${interaction.commandName}\' from ${interaction.client.user.tag}.`)
// ensure command exists, otherwise kill event
const command = commands.find(command => command.name === interaction.commandName)
if (!command) return
// the command exists, execute it
command.run(client, interaction)
})

View File

@@ -14,7 +14,7 @@ export default event(Events.MessageCreate, async ({ log, msgHist, tokens }, mess
if (message.author.tag === message.client.user.tag) return
// Only respond if message mentions the bot
if (!message.mentions.has(tokens.botUid)) return
if (!message.mentions.has(tokens.clientUid)) return
// push user response
msgHist.push({

View File

@@ -1,6 +1,17 @@
import { event, Events } from '../utils/index.js'
import { event, Events, registerCommands } from '../utils/index.js'
import { ActivityType } from 'discord.js'
import commands from '../commands/index.js'
// Log when the bot successfully logs in and export it
export default event(Events.ClientReady, ({ log }, client) => {
return log(`Logged in as ${client.user.username}.`)
log(`Logged in as ${client.user.username}.`)
// Register the commands associated with the bot upon loggin in
registerCommands(client, commands)
// set status of the bot
client.user.setActivity({
name: 'Powered by Ollama',
type: ActivityType.Custom
})
})

View File

@@ -4,7 +4,8 @@ export const Keys = {
clientToken: getEnvVar('CLIENT_TOKEN'),
channel: getEnvVar('CHANNEL_ID'),
model: getEnvVar('MODEL'),
botUid: getEnvVar('BOT_UID')
clientUid: getEnvVar('CLIENT_UID'),
guildId: getEnvVar('GUILD_ID')
} as const // readonly keys
export default Keys

22
src/utils/commands.ts Normal file
View File

@@ -0,0 +1,22 @@
import { CommandInteraction, ChatInputApplicationCommandData, Client } from 'discord.js'
/**
* interface for how slash commands should be run
*/
export interface SlashCommand extends ChatInputApplicationCommandData {
run: (client: Client, interaction: CommandInteraction) => void
}
/**
* register the command to discord for the channel
* @param client the bot reference
* @param commands commands to register to the bot
*/
export function registerCommands(client: Client, commands: SlashCommand[]): void {
// ensure the bot is online before registering
if (!client.application) return
// iterate through all commands and register them with the bot
for (const command of commands)
client.application.commands.create(command)
}

View File

@@ -14,7 +14,7 @@ export interface EventProps {
tokens: {
channel: string,
model: string,
botUid: string
clientUid: string
}
}
export type EventCallback<T extends EventKeys> = (
@@ -39,7 +39,7 @@ export function registerEvents(
tokens: {
channel: string,
model: string,
botUid: string
clientUid: string
}
): void {
for (const { key, callback } of events) {

View File

@@ -2,4 +2,5 @@
export * from './env.js'
export * from './events.js'
export * from './messageEmbed.js'
export * from './messageNormal.js'
export * from './messageNormal.js'
export * from './commands.js'