2024-02-11 01:04:12 +00:00
|
|
|
import {
|
|
|
|
ChannelType,
|
|
|
|
Events,
|
|
|
|
GuildMember,
|
|
|
|
GuildChannelManager,
|
|
|
|
GuildChannel,
|
2024-02-28 20:19:20 +00:00
|
|
|
VoiceState,
|
2024-03-23 21:43:21 +00:00
|
|
|
PermissionsBitField
|
2024-02-11 01:04:12 +00:00
|
|
|
} from 'discord.js';
|
2024-04-04 06:59:37 +00:00
|
|
|
import { VoiceChannels } from '../../database.js';
|
2024-01-28 17:33:22 +00:00
|
|
|
|
2024-02-11 01:04:12 +00:00
|
|
|
/**
|
|
|
|
* Function that either creates a new custom channel or gets an existing one registered in the database.
|
|
|
|
* @param {GuildMember} member The member that caused this event.
|
|
|
|
* @param {GuildChannelManager} guildChs All channels in this guild.
|
|
|
|
* @param {GuildChannel} channel The channel the member joined for this event to trigger.
|
|
|
|
* @returns {Promise<GuildChannel>} The channel, whether it's newly created or not.
|
|
|
|
*/
|
2024-02-09 21:59:11 +00:00
|
|
|
const getChannel = async (member, guildChs, channel) => {
|
2024-02-07 19:04:16 +00:00
|
|
|
// Check database for existing channel
|
2024-04-04 07:55:14 +00:00
|
|
|
/** @type {import('../../models/voiceChannels.js').VoiceChannel|null} */
|
2024-04-04 06:59:37 +00:00
|
|
|
const ownCh = await VoiceChannels.findOne({
|
2024-02-07 19:04:16 +00:00
|
|
|
where: {
|
2024-02-28 20:18:14 +00:00
|
|
|
owner: member.id
|
2024-02-07 19:04:16 +00:00
|
|
|
}
|
|
|
|
});
|
2024-02-28 20:12:38 +00:00
|
|
|
if (ownCh !== null) return await guildChs.fetch(ownCh.id);
|
2024-02-07 19:04:16 +00:00
|
|
|
|
|
|
|
// Create private channel with all permissions
|
|
|
|
const name = member.user.username;
|
2024-02-07 21:02:02 +00:00
|
|
|
const chName = `${name}${name.toLowerCase().endsWith('s') ? "'" : "'s"} channel`;
|
2024-02-09 21:59:11 +00:00
|
|
|
const privCh = await guildChs.create({
|
2024-02-07 19:04:16 +00:00
|
|
|
name: chName,
|
2024-02-09 21:59:11 +00:00
|
|
|
parent: channel.parent,
|
2024-03-23 21:43:21 +00:00
|
|
|
type: ChannelType.GuildVoice
|
2024-02-07 19:04:16 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// Save newly created channel
|
2024-04-04 06:59:37 +00:00
|
|
|
await VoiceChannels.create({
|
2024-02-07 19:04:16 +00:00
|
|
|
id: privCh.id,
|
2024-02-28 20:18:14 +00:00
|
|
|
owner: member.id
|
2024-02-08 20:11:56 +00:00
|
|
|
});
|
2024-02-07 19:04:16 +00:00
|
|
|
|
|
|
|
return privCh;
|
|
|
|
};
|
|
|
|
|
2024-02-11 01:04:12 +00:00
|
|
|
/**
|
|
|
|
* Function to delete the voice channel, if and only if the user is currently leaving and it was a custom channel.
|
|
|
|
* @param {VoiceState} state The previous voice state the user was in.
|
|
|
|
*/
|
2024-02-08 17:12:10 +00:00
|
|
|
const leftVoiceChat = async (state) => {
|
|
|
|
const { channel } = state;
|
|
|
|
|
|
|
|
// Isn't this always false?
|
|
|
|
if (!channel) return;
|
|
|
|
|
|
|
|
// Get active members from channel
|
|
|
|
const members = Array.from(channel.members);
|
|
|
|
if (members.length > 0) return;
|
|
|
|
|
2024-02-08 19:13:12 +00:00
|
|
|
// Find channel by id, return if not registered as custom
|
2024-04-04 07:55:14 +00:00
|
|
|
/** @type {import('../../models/voiceChannels.js').VoiceChannel|null} */
|
2024-04-04 06:59:37 +00:00
|
|
|
const custom = await VoiceChannels.findOne({
|
2024-02-08 19:13:12 +00:00
|
|
|
where: {
|
|
|
|
id: channel.id,
|
|
|
|
create: false
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (custom === null) return;
|
|
|
|
|
2024-02-08 17:12:10 +00:00
|
|
|
// Delete channel from guild
|
|
|
|
await channel.guild.channels.delete(channel.id);
|
|
|
|
console.info(`[INFO] Custom VC with ID '${channel.id}' was empty and got deleted.`);
|
|
|
|
};
|
|
|
|
|
2024-01-28 17:33:22 +00:00
|
|
|
export const name = Events.VoiceStateUpdate;
|
2024-02-11 01:04:12 +00:00
|
|
|
/**
|
|
|
|
* @param {VoiceState} oldState
|
|
|
|
* @param {VoiceState} newState
|
|
|
|
*/
|
2024-02-08 17:12:10 +00:00
|
|
|
export async function execute(oldState, newState) {
|
2024-02-28 19:51:59 +00:00
|
|
|
const { channel, member } = newState;
|
2024-02-24 17:46:46 +00:00
|
|
|
let step = 'delete';
|
|
|
|
try {
|
|
|
|
await leftVoiceChat(oldState);
|
|
|
|
if (!channel) return;
|
2024-01-28 17:33:22 +00:00
|
|
|
|
2024-02-24 17:46:46 +00:00
|
|
|
// Find channel by id, return if not registered for customs
|
2024-04-04 07:55:14 +00:00
|
|
|
/** @type {import('../../models/voiceChannels.js').VoiceChannel|null} */
|
2024-04-04 06:59:37 +00:00
|
|
|
const createCh = await VoiceChannels.findOne({
|
2024-02-24 17:46:46 +00:00
|
|
|
where: {
|
|
|
|
id: channel.id,
|
|
|
|
create: true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (createCh === null) return;
|
2024-02-07 18:38:51 +00:00
|
|
|
|
2024-02-24 17:46:46 +00:00
|
|
|
step = 'create';
|
|
|
|
// Extract channel data
|
|
|
|
const channels = newState.guild.channels;
|
2024-02-09 21:59:11 +00:00
|
|
|
const privCh = await getChannel(member, channels, channel);
|
2024-01-28 17:33:22 +00:00
|
|
|
|
2024-03-23 21:43:21 +00:00
|
|
|
step = 'edit permissions for';
|
|
|
|
// Edit permissionOverwrites on channel for user
|
|
|
|
await privCh.permissionOverwrites.set([
|
|
|
|
{
|
|
|
|
id: member.id,
|
|
|
|
allow: [
|
|
|
|
PermissionsBitField.Flags.ViewChannel,
|
|
|
|
PermissionsBitField.Flags.ManageChannels,
|
|
|
|
PermissionsBitField.Flags.ManageRoles
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]);
|
|
|
|
|
2024-02-07 19:04:16 +00:00
|
|
|
step = 'move to';
|
2024-02-07 16:40:29 +00:00
|
|
|
// Move user to private channel
|
2024-02-08 17:12:10 +00:00
|
|
|
await newState.setChannel(privCh);
|
2024-03-23 21:45:10 +00:00
|
|
|
console.info(
|
|
|
|
`[INFO] User with ID '${member.id}' created private channel with ID ${privCh.id}.`
|
|
|
|
);
|
2024-02-07 16:40:29 +00:00
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
2024-02-07 19:04:16 +00:00
|
|
|
await member.send(`Failed to ${step} channel! Please contact server staff.`);
|
2024-02-07 16:40:29 +00:00
|
|
|
}
|
2024-01-28 17:33:22 +00:00
|
|
|
}
|