Stryker-SC/Discord-Bot-VCMaster-JavaScript-Revamped
0
1const { SlashCommandBuilder, PermissionFlagsBits, MessageFlags, ActivityType } = require('discord.js');2const { getChannelName } = require('../../utils/voiceUtils');3 4module.exports = {5 data: new SlashCommandBuilder()6 .setName('vc')7 .setDescription('Manage your temporary voice channel')8 .addSubcommand(subcommand =>9 subcommand10 .setName('name')11 .setDescription('Change the name of your channel')12 .addStringOption(option => option.setName('name').setDescription('New name (leave empty for auto-detect)').setRequired(false)))13 .addSubcommand(subcommand =>14 subcommand15 .setName('limit')16 .setDescription('Set a user limit')17 .addIntegerOption(option => option.setName('user_limit').setDescription('Max users (0 = unlimited)').setRequired(true)))18 .addSubcommand(subcommand =>19 subcommand.setName('lock').setDescription('Lock the channel (@everyone cannot join)')20 .addRoleOption(option => option.setName('role').setDescription('Role to allow (others denied)').setRequired(false)))21 .addSubcommand(subcommand =>22 subcommand.setName('unlock').setDescription('Unlock the channel'))23 .addSubcommand(subcommand =>24 subcommand.setName('claim').setDescription('Claim ownership of the channel if owner left'))25 .addSubcommand(subcommand =>26 subcommand.setName('permit').setDescription('Allow a user to join')27 .addUserOption(option => option.setName('user').setDescription('User to permit').setRequired(true)))28 .addSubcommand(subcommand =>29 subcommand.setName('reject').setDescription('Kick and ban a user from the channel')30 .addUserOption(option => option.setName('user').setDescription('User to reject').setRequired(true))),31 32 async execute(interaction, client) {33 const { member, guild } = interaction;34 const voiceChannel = member.voice.channel;35 36 if (!voiceChannel) {37 return interaction.reply({ content: '❌ You must be in a voice channel to use this command.', flags: MessageFlags.Ephemeral });38 }39 40 // Check if this is a monitored temp channel41 const tempChannelData = await client.db.getTempChannel(voiceChannel.id);42 if (!tempChannelData) {43 return interaction.reply({ content: '❌ This is not a temporary channel managed by me.', flags: MessageFlags.Ephemeral });44 }45 46 const subcommand = interaction.options.getSubcommand();47 48 // Special case for 'claim' - does not require being owner49 if (subcommand === 'claim') {50 if (tempChannelData.owner_id === member.id) {51 return interaction.reply({ content: 'You are already the owner.', flags: MessageFlags.Ephemeral });52 }53 // Check if owner is present54 const ownerMember = voiceChannel.members.get(tempChannelData.owner_id);55 if (ownerMember) {56 return interaction.reply({ content: '❌ The current owner is still in the channel.', flags: MessageFlags.Ephemeral });57 }58 59 // Update Owner in DB/Memory60 // Need a method to update owner.61 // client.db.updateOwner(voiceChannel.id, member.id); // Assuming this exists or I'll implement valid update62 // Since updateOwner isn't in db.js yet, I'll use a raw query or add it. I'll add a helper now? 63 // Or just delete and add? No, addTempChannel inserts. I need update.64 // I will assume I can fix db.js or just do a delete/add hack if keys collide? No, PK collision.65 // Let's hold on 'claim' logic optimization. Checking DB methods... valid update needed.66 // I'll skip claim for a second and check other commands which require ownership.67 // Actually, I should update db.js to support updateOwner.68 }69 70 // For all other commands, check ownership71 if (subcommand !== 'claim' && tempChannelData.owner_id !== member.id) {72 return interaction.reply({ content: '❌ You do not own this channel.', flags: MessageFlags.Ephemeral });73 }74 75 await interaction.deferReply({ flags: MessageFlags.Ephemeral });76 77 try {78 switch (subcommand) {79 case 'name':80 const lastRenamed = tempChannelData.last_renamed || 0;81 const cooldown = 10 * 60 * 1000;82 if (Date.now() - lastRenamed < cooldown) {83 const mins = Math.ceil((cooldown - (Date.now() - lastRenamed)) / 60000);84 return interaction.editReply({ content: `❌ Rename cooldown! Wait ${mins} minutes.` });85 }86 87 let newName = interaction.options.getString('name');88 if (!newName) {89 newName = getChannelName(member);90 }91 92 try {93 await voiceChannel.setName(newName);94 await client.db.updateTempChannelRenameTime(voiceChannel.id, Date.now());95 await interaction.editReply({ content: `✅ Channel name changed to **${newName}**` });96 } catch (e) {97 console.error(e);98 await interaction.editReply({ content: `❌ Rate limited or missing access.` });99 }100 break;101 102 case 'limit':103 const limit = interaction.options.getInteger('user_limit');104 await voiceChannel.setUserLimit(limit);105 await interaction.editReply({ content: `✅ User limit set to **${limit === 0 ? 'Unlimited' : limit}**` });106 break;107 108 109 case 'lock':110 const roleToPermit = interaction.options.getRole('role');111 await voiceChannel.permissionOverwrites.edit(guild.id, { Connect: false });112 113 let replyMsg = `🔒 Channel locked for @everyone.`;114 if (roleToPermit) {115 await voiceChannel.permissionOverwrites.edit(roleToPermit.id, { Connect: true });116 replyMsg += `\n✅ Allowed role: **${roleToPermit.name}**`;117 }118 119 await interaction.editReply({ content: replyMsg });120 break;121 122 case 'unlock':123 await voiceChannel.permissionOverwrites.edit(guild.id, { Connect: true });124 await interaction.editReply({ content: `🔓 Channel unlocked.` });125 break;126 127 case 'permit':128 const memberToPermit = interaction.options.getMember('user');129 const userToPermitId = memberToPermit ? memberToPermit.id : interaction.options.getUser('user').id;130 const permitDisplayName = memberToPermit ? memberToPermit.displayName : interaction.options.getUser('user').username;131 await voiceChannel.permissionOverwrites.edit(userToPermitId, { Connect: true });132 await interaction.editReply({ content: `✅ **${permitDisplayName}** has been permitted to join.` });133 break;134 135 case 'reject':136 const memberToReject = interaction.options.getMember('user');137 const userToRejectId = memberToReject ? memberToReject.id : interaction.options.getUser('user').id;138 const rejectDisplayName = memberToReject ? memberToReject.displayName : interaction.options.getUser('user').username;139 140 // Kick from channel if in it141 if (memberToReject && memberToReject.voice.channelId === voiceChannel.id) {142 await memberToReject.voice.disconnect();143 }144 await voiceChannel.permissionOverwrites.edit(userToRejectId, { Connect: false });145 await interaction.editReply({ content: `🚫 **${rejectDisplayName}** has been rejected from the channel.` });146 break;147 148 case 'claim':149 try {150 const previousOwnerId = tempChannelData.owner_id;151 await client.db.updateTempChannelOwner(voiceChannel.id, member.id);152 153 await voiceChannel.permissionOverwrites.delete(previousOwnerId).catch(() => {});154 await voiceChannel.permissionOverwrites.edit(member.id, {155 Connect: true,156 ManageChannels: true,157 MoveMembers: true158 });159 160 if (tempChannelData.text_channel_id) {161 const textChannel = guild.channels.cache.get(tempChannelData.text_channel_id);162 if (textChannel) {163 await textChannel.permissionOverwrites.delete(previousOwnerId).catch(() => {});164 await textChannel.permissionOverwrites.edit(member.id, {165 ViewChannel: true,166 SendMessages: true,167 ManageChannels: true168 });169 }170 }171 172 await interaction.editReply({ content: `👑 You are now the owner of this channel!` });173 } catch (err) {174 console.error(err);175 await interaction.editReply({ content: 'Failed to claim channel.' });176 }177 break;178 }179 } catch (error) {180 console.error(error);181 await interaction.editReply({ content: '❌ API Error: Check permissions or wait for rate limits.' });182 }183 },184};185 