implement first interaction handling
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { config } from "config";
|
||||
import { Routes } from "discord.js";
|
||||
import getCommands from "entitites/commands";
|
||||
import { logger } from "lib/common-logger";
|
||||
import { discordRestClient } from "lib/rest-client";
|
||||
|
||||
export const publishCommands = async () => {
|
||||
@@ -11,8 +12,8 @@ export const publishCommands = async () => {
|
||||
body: getCommands(),
|
||||
},
|
||||
);
|
||||
console.log("Successfully added commands");
|
||||
logger.info("successfully added commands");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
logger.error("failed to add commands:", e);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,6 +2,6 @@ import { logChannelService } from "features/log-channel/log-channel.service";
|
||||
import { logger } from "lib/common-logger";
|
||||
|
||||
export const handleShutdown = async () => {
|
||||
logger.info("Bot is shutting down...");
|
||||
await logChannelService.sendLogMessage("Bot is shutting down...");
|
||||
logger.info("bot is shutting down...");
|
||||
await logChannelService.sendLogMessage("bot is shutting down...");
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ export const ConfigSchema = z.object({
|
||||
reactionRoles: z.object({
|
||||
allowedMessageIds: z.array(z.string()),
|
||||
}),
|
||||
serverId: z.string(),
|
||||
guildId: z.string(),
|
||||
version: z.number(),
|
||||
discord: z.object({
|
||||
token: z.string(),
|
||||
|
||||
@@ -6,12 +6,12 @@ export const config: z.output<typeof ConfigSchema> = {
|
||||
channelMapping: {
|
||||
text: {
|
||||
bot: "1317253291633279026",
|
||||
log: "1321972449365065728",
|
||||
bump: "1330310075759329412",
|
||||
feedback: "1321626600185266176",
|
||||
help: "1321860125127872605",
|
||||
introduction: "1321473655523246171",
|
||||
news: "1321953521435934741",
|
||||
notification: "1321972449365065728",
|
||||
"off-topic": "1316153372507639855",
|
||||
rules: "1316153372507639849",
|
||||
testing: "1451310086864507112",
|
||||
@@ -40,7 +40,7 @@ export const config: z.output<typeof ConfigSchema> = {
|
||||
"1321491461111283722", // Example message ID for reaction roles
|
||||
],
|
||||
},
|
||||
serverId: "1316153371899592774",
|
||||
guildId: "1316153371899592774",
|
||||
version: 1,
|
||||
discord: {
|
||||
token: env.DISCORD_TOKEN,
|
||||
|
||||
@@ -6,117 +6,6 @@ import {
|
||||
import client from "lib/client";
|
||||
|
||||
export default class DiscordController extends EventEmitter {
|
||||
private waterMeController: WaterMeController = waterMeController;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
let channelListeners = new Map();
|
||||
|
||||
client.on(
|
||||
Events.VoiceStateUpdate,
|
||||
async (oldState: VoiceState, newState: VoiceState) => {
|
||||
// check if user joined a vc
|
||||
if (
|
||||
(!oldState.channelId && newState.channelId) ||
|
||||
oldState.channelId !== newState.channelId
|
||||
) {
|
||||
// check if right vc
|
||||
if (
|
||||
newState.channelId === config.discord.vchannelIdForTwo ||
|
||||
newState.channelId === config.discord.vchannelIdForThree ||
|
||||
newState.channelId === config.discord.vchannelIdForFour ||
|
||||
newState.channelId === config.discord.vchannelIdForGroup
|
||||
) {
|
||||
const channel = newState.channel;
|
||||
if (!channel) {
|
||||
console.error("channel not found");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const newChannel =
|
||||
await this.dynamicVChannelService.createVChannel(
|
||||
newState,
|
||||
channel,
|
||||
);
|
||||
// move user in new channel
|
||||
await newState.setChannel(newChannel);
|
||||
// create specific listener for channel
|
||||
const channelListener = async (
|
||||
oldState: VoiceState,
|
||||
newState: VoiceState,
|
||||
) => {
|
||||
channelListeners =
|
||||
await this.dynamicVChannelService.deleteVChannel(
|
||||
oldState,
|
||||
newState,
|
||||
newChannel,
|
||||
channelListeners,
|
||||
channelListener,
|
||||
);
|
||||
};
|
||||
// save listener in map
|
||||
channelListeners.set(newChannel.id, channelListener);
|
||||
// add listener
|
||||
client.on(Events.VoiceStateUpdate, channelListener);
|
||||
} catch (error) {
|
||||
console.error("error while duplicating channel", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
console.log(
|
||||
`----------------\nversion ${config.discord.version}\n----------------`,
|
||||
);
|
||||
}
|
||||
|
||||
async setActivity(state: number) {
|
||||
switch (state) {
|
||||
case 0:
|
||||
client.user?.setActivity(" ", { type: 0 });
|
||||
console.log("set activity");
|
||||
client.user?.setPresence({
|
||||
status: "invisible",
|
||||
});
|
||||
break;
|
||||
default:
|
||||
client.user?.setActivity("spielt sudoku", { type: 0 });
|
||||
console.log("set activity");
|
||||
client.user?.setPresence({
|
||||
status: "online",
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async handleInteraction(interaction: Interaction<CacheType>) {
|
||||
if (interaction.isModalSubmit()) {
|
||||
await this.handleModalSubmit(interaction);
|
||||
return;
|
||||
}
|
||||
|
||||
if (interaction.isChatInputCommand()) {
|
||||
await this.handleChatInputCommand(interaction);
|
||||
return;
|
||||
}
|
||||
if (interaction.isButton()) {
|
||||
await this.handleButton(interaction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
async handleButton(interaction: ButtonInteraction<CacheType>) {
|
||||
const { customId } = interaction;
|
||||
console.log(interaction.customId);
|
||||
|
||||
if (customId.toLowerCase().includes("moreWater")) {
|
||||
await this.waterMeService.handleInteraction(interaction);
|
||||
}
|
||||
if (customId.toLowerCase().includes("medication")) {
|
||||
await this.medicationService.handleInteraction(interaction);
|
||||
}
|
||||
}
|
||||
|
||||
async handleChatInputCommand(
|
||||
interaction: ChatInputCommandInteraction<CacheType>,
|
||||
) {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import type { VoiceChannelsServiceInterface } from "@avocadi/bot-core/entities/channels/voice/voice-channels.service";
|
||||
import { config } from "config";
|
||||
import { ChannelType, type VoiceChannel } from "discord.js";
|
||||
import client from "lib/client";
|
||||
|
||||
export class VoiceChannelsService
|
||||
implements VoiceChannelsServiceInterface<VoiceChannel>
|
||||
{
|
||||
async getVoiceChannelById(channelId: string) {
|
||||
const channel = await client.channels.fetch(channelId);
|
||||
|
||||
if (!channel) {
|
||||
throw new Error(`Channel with id ${channelId} not found`);
|
||||
}
|
||||
|
||||
if (channel.type !== ChannelType.GuildVoice) {
|
||||
throw new Error(`Channel with id ${channelId} is not a voice channel`);
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
async createVoiceChannel(name: string) {
|
||||
const guild = await client.guilds.fetch(config.guildId);
|
||||
const channel = await guild.channels.create({
|
||||
name,
|
||||
type: ChannelType.GuildVoice,
|
||||
});
|
||||
return channel;
|
||||
}
|
||||
|
||||
async cloneVoiceChannel(
|
||||
channel: VoiceChannel,
|
||||
options?: { name?: string; position?: number },
|
||||
) {
|
||||
const clonedChannel = await channel.clone({
|
||||
name: options?.name,
|
||||
position: options?.position,
|
||||
});
|
||||
return clonedChannel;
|
||||
}
|
||||
|
||||
async deleteVoiceChannel(channelId: string) {
|
||||
const channel = await this.getVoiceChannelById(channelId);
|
||||
|
||||
await channel.delete();
|
||||
}
|
||||
}
|
||||
|
||||
export const voiceChannelsService = new VoiceChannelsService();
|
||||
@@ -0,0 +1,30 @@
|
||||
import { VoiceChannels } from "@avocadi/bot-core/entities/channels/channels.schema";
|
||||
import { DynamicVoiceChannelsService } from "@avocadi/bot-core/features/dynamic-voice-channels/dynamic-voice-channels.service";
|
||||
import { config } from "config";
|
||||
import { voiceChannelsService } from "entitites/channels/voice/voice-channels.service";
|
||||
|
||||
export const dynamicVoiceChannelService = new DynamicVoiceChannelsService(
|
||||
voiceChannelsService,
|
||||
[
|
||||
{
|
||||
channelId: config.channelMapping.voice["for-two"],
|
||||
key: VoiceChannels.enum["for-two"],
|
||||
size: 2,
|
||||
},
|
||||
{
|
||||
channelId: config.channelMapping.voice["for-three"],
|
||||
key: VoiceChannels.enum["for-three"],
|
||||
size: 3,
|
||||
},
|
||||
{
|
||||
channelId: config.channelMapping.voice["for-four"],
|
||||
key: VoiceChannels.enum["for-four"],
|
||||
size: 4,
|
||||
},
|
||||
{
|
||||
channelId: config.channelMapping.voice["for-group"],
|
||||
key: VoiceChannels.enum["for-group"],
|
||||
size: 99,
|
||||
},
|
||||
],
|
||||
);
|
||||
@@ -3,7 +3,7 @@ import client from "lib/client";
|
||||
import { logger } from "lib/common-logger";
|
||||
|
||||
export class LogChannelService {
|
||||
private logChannelId = config.channelMapping.text.bot;
|
||||
private logChannelId = config.channelMapping.text.log;
|
||||
|
||||
async getLogChannel() {
|
||||
const logChannel = await client.channels.fetch(this.logChannelId);
|
||||
|
||||
@@ -2,8 +2,10 @@ import type { WaterMeService } from "@avocadi/bot-core/features/water-me/water-m
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
type ButtonInteraction,
|
||||
ButtonStyle,
|
||||
type CacheType,
|
||||
type ChatInputCommandInteraction,
|
||||
type Interaction,
|
||||
} from "discord.js";
|
||||
import { waterMeService } from "./water-me.service";
|
||||
@@ -15,7 +17,9 @@ class WaterMeController {
|
||||
this.waterMeService = waterMeService;
|
||||
}
|
||||
|
||||
async handleInteraction(interaction: Interaction<CacheType>) {
|
||||
async handleInteraction(
|
||||
interaction: ButtonInteraction | ChatInputCommandInteraction,
|
||||
) {
|
||||
const result = this.waterMeService.waterMe();
|
||||
|
||||
const moreButton = new ButtonBuilder()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { publishCommands } from "actions/publish-commands";
|
||||
import "./listeners";
|
||||
|
||||
// Publish commands when the application starts
|
||||
await publishCommands();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import "./ready.listener";
|
||||
import "./guild-member-add.listener";
|
||||
import "./stop.listener";
|
||||
import "./guild-members/guild-members.listener";
|
||||
import "./voice-state/voice-state.listener";
|
||||
import "./message-reaction-add.listener";
|
||||
import "./message-reaction-remove.listener";
|
||||
import "./interactions/interactions.listener";
|
||||
import "./reactions/reactions.listener";
|
||||
import "./messages/messages.listener";
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { ButtonInteraction } from "discord.js";
|
||||
import { waterMeController } from "features/water-me/water-me.controller";
|
||||
|
||||
export const handleButtonInteraction = async (
|
||||
interaction: ButtonInteraction,
|
||||
) => {};
|
||||
) => {
|
||||
waterMeController.handleInteraction(interaction);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { ChatInputCommandInteraction } from "discord.js";
|
||||
import { waterMeController } from "features/water-me/water-me.controller";
|
||||
|
||||
export const handleChatInputCommandInteraction = async (
|
||||
interaction: ChatInputCommandInteraction,
|
||||
) => {};
|
||||
) => {
|
||||
waterMeController.handleInteraction(interaction);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { config } from "config";
|
||||
import { messagesService } from "entitites/messages/messages.service";
|
||||
import client from "lib/client";
|
||||
|
||||
client.on("messageCreate", async (message) => {
|
||||
messagesService.logMessage(message);
|
||||
if (
|
||||
message.channel.id !== config.channelMapping.text.log &&
|
||||
message.channel.id !== config.channelMapping.text.bot
|
||||
) {
|
||||
messagesService.logMessage(message);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
import { config } from "config";
|
||||
import { activityService } from "features/activity/activity.service";
|
||||
import { logChannelService } from "features/log-channel/log-channel.service";
|
||||
import client from "lib/client";
|
||||
import { logger } from "lib/common-logger";
|
||||
|
||||
client.once("ready", async () => {
|
||||
const channels = client.channels;
|
||||
const logChannel = channels.cache.get(config.channelMapping.text.bot);
|
||||
client.once("clientReady", async () => {
|
||||
await logChannelService.sendLogMessage("wieder online!!!");
|
||||
|
||||
if (logChannel?.isTextBased() && logChannel?.isSendable()) {
|
||||
try {
|
||||
logger.info("bot is online");
|
||||
await logChannel.send("wieder online!!!");
|
||||
} catch (error) {
|
||||
logger.error("failed to send online message:", error);
|
||||
}
|
||||
} else {
|
||||
logger.error("log channel is not valid or sendable.");
|
||||
}
|
||||
await activityService.set("playing");
|
||||
logger.info("ready");
|
||||
logger.info("bot is online");
|
||||
|
||||
await activityService.set("competing");
|
||||
logger.info("finished ready procedure");
|
||||
});
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { VoiceState } from "discord.js";
|
||||
import { dynamicVoiceChannelService } from "features/dynamic-voice-channel/dynamic-voice-channel.service";
|
||||
import { logger } from "lib/common-logger";
|
||||
|
||||
export const handleDynamicVoiceChannelCreation = async (
|
||||
oldState: VoiceState,
|
||||
newState: VoiceState,
|
||||
) => {
|
||||
const userJoinedChannel = !oldState.channelId && newState.channelId;
|
||||
const userSwitchedChannel = oldState.channelId !== newState.channelId;
|
||||
|
||||
if (userJoinedChannel || userSwitchedChannel) {
|
||||
const channel = newState.channel;
|
||||
|
||||
if (!channel) {
|
||||
logger.error("Channel not found for VoiceStateUpdate event");
|
||||
return;
|
||||
}
|
||||
|
||||
// New channel is created if user joined one of the specific channels (e.g. "Join to Create") or switched to one of them
|
||||
const newChannel =
|
||||
await dynamicVoiceChannelService.createDynamicVoiceChannel(channel.id);
|
||||
|
||||
if (newChannel) {
|
||||
await newState.setChannel(newChannel);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
import type { VoiceState } from "discord.js";
|
||||
import { voiceChannelsService } from "entitites/channels/voice/voice-channels.service";
|
||||
import { dynamicVoiceChannelService } from "features/dynamic-voice-channel/dynamic-voice-channel.service";
|
||||
|
||||
export const handleDynamicVoiceChannelDeletion = async (
|
||||
oldState: VoiceState,
|
||||
newState: VoiceState,
|
||||
) => {
|
||||
// Check if user left a channel that was created by the bot and delete it if it's empty
|
||||
if (oldState.channelId && !newState.channelId) {
|
||||
const channelId = oldState.channelId;
|
||||
|
||||
if (dynamicVoiceChannelService.createdChannelIdsSet.has(channelId)) {
|
||||
const channel = await voiceChannelsService.getVoiceChannelById(channelId);
|
||||
|
||||
if (channel.members.size === 0) {
|
||||
await dynamicVoiceChannelService.deleteDynamicVoiceChannel(channelId);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,11 @@
|
||||
import { Events } from "discord.js";
|
||||
import client from "lib/client";
|
||||
import { handleDynamicVoiceChannelCreation } from "./handle-dynamic-voice-channel-creation";
|
||||
import { handleDynamicVoiceChannelDeletion } from "./handle-dynamic-voice-channel-deletion";
|
||||
|
||||
client.on(Events.VoiceStateUpdate, async (oldState, newState) => {
|
||||
// TODO: handle updates
|
||||
await Promise.allSettled([
|
||||
handleDynamicVoiceChannelCreation(oldState, newState),
|
||||
handleDynamicVoiceChannelDeletion(oldState, newState),
|
||||
]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user