209 lines
8.3 KiB
JavaScript
209 lines
8.3 KiB
JavaScript
const { SlashCommandBuilder, ModalBuilder, TextInputStyle, TextInputBuilder, ActionRowBuilder, ChannelType, PermissionsBitField, ButtonBuilder, ButtonStyle, ComponentType } = require('discord.js');
|
|
const { simpleEmbed } = require('../functions/embeds.js');
|
|
const { Users, Team } = require('../functions/models.js');
|
|
const { applyUsername } = require('../functions/utils.js');
|
|
const { client } = require('../index.js');
|
|
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('team')
|
|
.setDescription('Team command')
|
|
.addSubcommand(subcommand => subcommand
|
|
.setName('create')
|
|
.setDescription('Create a team'))
|
|
.addSubcommand(subcommand => subcommand
|
|
.setName('invite')
|
|
.setDescription('Invite an user')
|
|
.addUserOption(option => option
|
|
.setName('user')
|
|
.setDescription('The user to invite')
|
|
.setRequired(true)))
|
|
.addSubcommand(subcommand => subcommand
|
|
.setName('leave')
|
|
.setDescription('Leave your team')),
|
|
|
|
async execute(interaction) {
|
|
const user = await Users.findOne({ where: { id: interaction.user.id } });
|
|
if (!user) return await interaction.reply({ embeds: [simpleEmbed('Error while getting user information')], ephemeral: true });
|
|
|
|
if (interaction.options.getSubcommand() === 'create') {
|
|
if (user.teamId) return await interaction.reply({ embeds: [simpleEmbed('You are already in a team')], ephemeral: true });
|
|
|
|
const modal = new ModalBuilder()
|
|
.setCustomId('teamCreate')
|
|
.setTitle('Create team');
|
|
|
|
const nameInput = new TextInputBuilder()
|
|
.setCustomId('nameInput')
|
|
.setLabel('Team name')
|
|
.setMinLength(3)
|
|
.setMaxLength(16)
|
|
.setStyle(TextInputStyle.Short);
|
|
|
|
const colorInput = new TextInputBuilder()
|
|
.setCustomId('colorInput')
|
|
.setLabel('Team color (hex)')
|
|
.setStyle(TextInputStyle.Short)
|
|
.setPlaceholder('#00ff00');
|
|
|
|
const firstActionRow = new ActionRowBuilder().addComponents(nameInput);
|
|
const secondActionRow = new ActionRowBuilder().addComponents(colorInput);
|
|
|
|
modal.addComponents(firstActionRow, secondActionRow);
|
|
|
|
await interaction.showModal(modal);
|
|
|
|
try {
|
|
const filter = (filterInteraction) => filterInteraction.customId === 'teamCreate';
|
|
const modalInteraction = await interaction.awaitModalSubmit({ filter, time: 10 * 60 * 1000 });
|
|
|
|
const teamName = modalInteraction.fields.getTextInputValue('nameInput');
|
|
const teamColor = modalInteraction.fields.getTextInputValue('colorInput');
|
|
|
|
if (!/^[a-zA-Z0-9]+$/.test(teamName)) return await modalInteraction.reply({ embeds: [simpleEmbed('Team name can only include alphanumeric characters')], ephemeral: true });
|
|
if (!/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(teamColor)) return await modalInteraction.reply({ embeds: [simpleEmbed('Team color must be a valid hex code. [Color Picker](https://htmlcolorcodes.com/color-picker/)')], ephemeral: true });
|
|
|
|
|
|
const guild = await client.guilds.fetch(process.env.GUILD_ID);
|
|
const category = await guild.channels.fetch(process.env.TEAM_CATEGORY_ID);
|
|
|
|
const textChannel = await guild.channels.create({
|
|
name: teamName,
|
|
type: ChannelType.GuildText,
|
|
parent: category,
|
|
permissionOverwrites: [
|
|
{
|
|
id: guild.id,
|
|
deny: [PermissionsBitField.Flags.ViewChannel],
|
|
},
|
|
{
|
|
id: interaction.member.id,
|
|
allow: [PermissionsBitField.Flags.ViewChannel],
|
|
},
|
|
],
|
|
});
|
|
|
|
const voiceChannel = await guild.channels.create({
|
|
name: teamName,
|
|
type: ChannelType.GuildVoice,
|
|
parent: category,
|
|
permissionOverwrites: [
|
|
{
|
|
id: guild.id,
|
|
deny: [PermissionsBitField.Flags.ViewChannel],
|
|
},
|
|
{
|
|
id: interaction.member.id,
|
|
allow: [PermissionsBitField.Flags.ViewChannel],
|
|
},
|
|
],
|
|
});
|
|
|
|
const team = await Team.create({
|
|
name: teamName,
|
|
color: teamColor,
|
|
textChannelId: textChannel.id,
|
|
voiceChannelId: voiceChannel.id,
|
|
});
|
|
|
|
await team.addMembers([ user ]);
|
|
|
|
await applyUsername(user, interaction.member);
|
|
|
|
await modalInteraction.reply({ embeds: [simpleEmbed(`Successfully created team **${teamName}**`)], ephemeral: true });
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
} else if (interaction.options.getSubcommand() === 'leave') {
|
|
if (!user.teamId) return await interaction.reply({ embeds: [simpleEmbed('You are not in a team')], ephemeral: true });
|
|
|
|
const team = await user.getTeam();
|
|
await team.removeMember(user);
|
|
|
|
const guild = await client.guilds.fetch(process.env.GUILD_ID);
|
|
|
|
const textChannel = await guild.channels.fetch(team.textChannelId);
|
|
const voiceChannel = await guild.channels.fetch(team.voiceChannelId);
|
|
|
|
|
|
if (await team.countMembers() <= 0) {
|
|
await textChannel.delete();
|
|
await voiceChannel.delete();
|
|
|
|
await team.destroy();
|
|
} else {
|
|
await textChannel.permissionOverwrites.delete(interaction.member);
|
|
await voiceChannel.permissionOverwrites.delete(interaction.member);
|
|
}
|
|
|
|
await applyUsername(user, interaction.member);
|
|
|
|
await interaction.reply({ embeds: [simpleEmbed('Successfully left team')], ephemeral: true });
|
|
} else if (interaction.options.getSubcommand() === 'invite') {
|
|
if (!user.teamId) return await interaction.reply({ embeds: [simpleEmbed('You are not in a team')], ephemeral: true });
|
|
|
|
const invitedUser = interaction.options.getUser('user');
|
|
if (interaction.user.id === invitedUser.id) return await interaction.reply({ embeds: [simpleEmbed('You cannot invite yourself')], ephemeral: true });
|
|
|
|
const invitedUserInstance = await Users.findOne({ where: { id: invitedUser.id } });
|
|
if (invitedUserInstance.teamId) return await interaction.reply({ embeds: [simpleEmbed('The user you are trying already is in a team')], ephemeral: true });
|
|
|
|
const team = await user.getTeam();
|
|
|
|
const acceptButton = new ButtonBuilder()
|
|
.setCustomId('accept')
|
|
.setLabel('Accept')
|
|
.setStyle(ButtonStyle.Success);
|
|
|
|
const denyButton = new ButtonBuilder()
|
|
.setCustomId('deny')
|
|
.setLabel('Deny')
|
|
.setStyle(ButtonStyle.Danger);
|
|
|
|
const row = new ActionRowBuilder()
|
|
.addComponents(acceptButton, denyButton);
|
|
|
|
const inviteMessage = await invitedUser.send({
|
|
embeds: [simpleEmbed(`**${user.rawUsername}** invited you to join team **${team.name}**`)],
|
|
components: [row],
|
|
});
|
|
|
|
await interaction.reply({ embeds: [simpleEmbed(`Successfully invited ${invitedUser} to your team`)], ephemeral: true });
|
|
|
|
const collector = inviteMessage.createMessageComponentCollector({ componentType: ComponentType.Button, time: 60 * 60 * 1000 });
|
|
|
|
collector.on('collect', async i => {
|
|
try {
|
|
if (i.customId === 'accept') {
|
|
await invitedUserInstance.reload();
|
|
if (invitedUserInstance.teamId) return await i.message.edit({ embeds: [simpleEmbed('You are already in a team')], components: [] });
|
|
|
|
await team.addMember(i.user.id);
|
|
|
|
const guild = await client.guilds.fetch(process.env.GUILD_ID);
|
|
const member = await guild.members.fetch(i.user.id);
|
|
|
|
const textChannel = await guild.channels.fetch(team.textChannelId);
|
|
const voiceChannel = await guild.channels.fetch(team.voiceChannelId);
|
|
|
|
await textChannel.permissionOverwrites.edit(member, { ViewChannel: true });
|
|
await voiceChannel.permissionOverwrites.edit(member, { ViewChannel: true });
|
|
|
|
await applyUsername(invitedUserInstance, member);
|
|
|
|
await i.message.edit({ embeds: [simpleEmbed(`Successfully joined team **${team.name}**`)], components: [] });
|
|
} else if (i.customId === 'deny') {
|
|
await i.message.edit({ embeds: [simpleEmbed(`Successfully denied the request to join team **${team.name}**`)], components: [] });
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
});
|
|
|
|
collector.on('end', async () => {
|
|
inviteMessage.edit({ embeds: [simpleEmbed('Confirmation not received within 1 hour, cancelling')], components: [] });
|
|
});
|
|
}
|
|
},
|
|
};
|