Files
SupportBot/Addons/TempVC.js
T
2026-07-26 20:33:00 +01:00

228 lines
9.2 KiB
JavaScript

const Discord = require("discord.js");
const { Event } = require("../Structures/Addon.js");
const fs = require("fs");
const yaml = require("js-yaml");
const tempVCConfig = yaml.load(fs.readFileSync("./Addons/Configs/tempvc.yml", "utf8"));
const tempChannels = new Map();
const voiceStateUpdate = new Event("voiceStateUpdate", async (client, oldState, newState) => {
if (!tempVCConfig.Enabled) return;
const member = newState.member;
const guild = newState.guild;
if (newState.channelId === tempVCConfig.JoinToCreateChannelID) {
console.log(`[TempVC] ${member.user.tag} joined the Join-to-Create channel.`);
}
if (newState.channelId === tempVCConfig.JoinToCreateChannelID) {
try {
const parentCategory = tempVCConfig.CategoryID || newState.channel.parentId;
const channelName = tempVCConfig.ChannelNamePattern.replace("{user}", member.user.username);
const newChannel = await guild.channels.create({
name: channelName,
type: Discord.ChannelType.GuildVoice,
parent: parentCategory,
permissionOverwrites: [
{
id: member.id,
allow: [Discord.PermissionFlagsBits.ManageChannels, Discord.PermissionFlagsBits.MoveMembers],
},
],
});
tempChannels.set(newChannel.id, member.id);
await member.voice.setChannel(newChannel);
console.log(`[TempVC] Created channel "${channelName}" for ${member.user.tag}`);
if (tempVCConfig.Hub.Enabled && tempVCConfig.Hub.SendOnCreate) {
try {
const { ActionRowBuilder, ButtonBuilder, EmbedBuilder, MessageFlags, ButtonStyle } = Discord;
const layoutStyle = tempVCConfig.Hub.LayoutStyle || "classic";
if (layoutStyle === "classic") {
const config = tempVCConfig.Hub.Classic;
const embed = new EmbedBuilder()
.setTitle(config.Title)
.setDescription(config.Description)
.setColor(config.Color);
const buttons = new ActionRowBuilder().addComponents(
new ButtonBuilder().setCustomId("tempvc_lock").setLabel("Lock").setEmoji("🔒").setStyle(ButtonStyle.Secondary),
new ButtonBuilder().setCustomId("tempvc_unlock").setLabel("Unlock").setEmoji("🔓").setStyle(ButtonStyle.Secondary),
new ButtonBuilder().setCustomId("tempvc_rename").setLabel("Rename").setEmoji("✏️").setStyle(ButtonStyle.Secondary),
new ButtonBuilder().setCustomId("tempvc_limit").setLabel("Limit").setEmoji("👥").setStyle(ButtonStyle.Secondary),
new ButtonBuilder().setCustomId("tempvc_claim").setLabel("Claim Ownership").setEmoji("👑").setStyle(ButtonStyle.Primary)
);
await newChannel.send({ embeds: [embed], components: [buttons] });
} else {
const config = tempVCConfig.Hub.Modern;
const colorInt = parseInt(config.Color.replace("#", ""), 16);
const container = {
type: 11,
accent_color: colorInt,
children: [
{
type: 12,
children: [
{ type: 13, content: `## ${config.Title}` },
{ type: 13, content: config.Body }
]
},
{
type: 15,
divider: true
},
{
type: 1,
components: [
{ type: 2, custom_id: "tempvc_lock", label: "Lock", emoji: { name: "🔒" }, style: 2 },
{ type: 2, custom_id: "tempvc_unlock", label: "Unlock", emoji: { name: "🔓" }, style: 2 },
{ type: 2, custom_id: "tempvc_rename", label: "Rename", emoji: { name: "✏️" }, style: 2 },
{ type: 2, custom_id: "tempvc_limit", label: "Limit", emoji: { name: "👥" }, style: 2 }
]
},
{
type: 1,
components: [
{ type: 2, custom_id: "tempvc_claim", label: "Claim Ownership", emoji: { name: "👑" }, style: 1 }
]
}
]
};
await newChannel.send({
flags: MessageFlags.IsComponentsV2,
components: [container]
});
}
} catch (hubError) {
console.error("[TempVC] Error sending Hub:", hubError);
}
}
} catch (error) {
console.error("[TempVC] Error creating temporary channel:", error);
}
}
if (oldState.channelId && tempChannels.has(oldState.channelId)) {
const oldChannel = oldState.channel;
if (oldChannel && oldChannel.members.size === 0) {
try {
await oldChannel.delete();
tempChannels.delete(oldState.channelId);
console.log(`[TempVC] Deleted empty temporary channel "${oldChannel.name}"`);
} catch (error) {
if (error.code !== 10003) {
console.error("[TempVC] Error deleting temporary channel:", error);
}
tempChannels.delete(oldState.channelId);
}
}
}
});
const interactionEvent = new Event("interactionCreate", async (client, interaction) => {
if (!interaction.isButton() && !interaction.isModalSubmit()) return;
if (!interaction.customId.startsWith("tempvc_")) return;
const channel = interaction.channel;
if (!tempChannels.has(channel.id)) {
return interaction.reply({ content: "This channel is no longer a temporary voice channel.", flags: Discord.MessageFlags.Ephemeral });
}
const ownerId = tempChannels.get(channel.id);
const isOwner = interaction.user.id === ownerId || interaction.member.permissions.has(Discord.PermissionFlagsBits.Administrator);
if (interaction.customId === "tempvc_claim") {
const currentOwnerInVC = channel.members.has(ownerId);
if (currentOwnerInVC && interaction.user.id !== ownerId) {
return interaction.reply({ content: "The owner is still in the voice channel!", flags: Discord.MessageFlags.Ephemeral });
}
tempChannels.set(channel.id, interaction.user.id);
await channel.permissionOverwrites.edit(interaction.user.id, {
ManageChannels: true,
MoveMembers: true,
});
return interaction.reply({ content: "You are now the owner of this voice channel!", flags: Discord.MessageFlags.Ephemeral });
}
if (!isOwner) {
return interaction.reply({ content: "Only the channel owner can use these controls.", flags: Discord.MessageFlags.Ephemeral });
}
try {
switch (interaction.customId) {
case "tempvc_lock":
await channel.permissionOverwrites.edit(interaction.guild.id, { Connect: false });
await interaction.reply({ content: "Channel locked! 🔒", flags: Discord.MessageFlags.Ephemeral });
break;
case "tempvc_unlock":
await channel.permissionOverwrites.edit(interaction.guild.id, { Connect: null });
await interaction.reply({ content: "Channel unlocked! 🔓", flags: Discord.MessageFlags.Ephemeral });
break;
case "tempvc_rename":
const modal = new Discord.ModalBuilder()
.setCustomId("tempvc_modal_rename")
.setTitle("Rename Channel")
.addComponents(
new Discord.ActionRowBuilder().addComponents(
new Discord.TextInputBuilder()
.setCustomId("name")
.setLabel("New Name")
.setStyle(Discord.TextInputStyle.Short)
.setPlaceholder(channel.name)
.setRequired(true)
)
);
await interaction.showModal(modal);
break;
case "tempvc_limit":
const limitModal = new Discord.ModalBuilder()
.setCustomId("tempvc_modal_limit")
.setTitle("Set User Limit")
.addComponents(
new Discord.ActionRowBuilder().addComponents(
new Discord.TextInputBuilder()
.setCustomId("limit")
.setLabel("Limit (0-99)")
.setStyle(Discord.TextInputStyle.Short)
.setPlaceholder("0 for no limit")
.setRequired(true)
)
);
await interaction.showModal(limitModal);
break;
}
if (interaction.isModalSubmit()) {
if (interaction.customId === "tempvc_modal_rename") {
const newName = interaction.fields.getTextInputValue("name");
await channel.setName(newName);
await interaction.reply({ content: `Channel renamed to **${newName}**!`, flags: Discord.MessageFlags.Ephemeral });
} else if (interaction.customId === "tempvc_modal_limit") {
const limit = parseInt(interaction.fields.getTextInputValue("limit"));
if (isNaN(limit) || limit < 0 || limit > 99) {
return interaction.reply({ content: "Please enter a valid number between 0 and 99.", flags: Discord.MessageFlags.Ephemeral });
}
await channel.setUserLimit(limit);
await interaction.reply({ content: `User limit set to **${limit === 0 ? "Unlimited" : limit}**!`, flags: Discord.MessageFlags.Ephemeral });
}
}
} catch (error) {
console.error("[TempVC] Error handling interaction:", error);
if (!interaction.replied) await interaction.reply({ content: "An error occurred.", flags: Discord.MessageFlags.Ephemeral });
}
});
module.exports = [voiceStateUpdate, interactionEvent];