Added alot of functions

This commit is contained in:
Xeovalyte 2023-08-11 11:14:59 +02:00
parent 0f54fbf07e
commit 6f24616c81
15 changed files with 421 additions and 49 deletions

View File

@ -11,11 +11,12 @@ module.exports = {
.setDescription('The user to add')),
async execute(interaction) {
const userId = interaction.options.getUser('user') ? interaction.options.getUser('user').id : interaction.user.id;
const user = interaction.options.getUser('user') ? interaction.options.getUser('user') : interaction.user;
try {
await Users.create({
id: userId,
id: user.id,
rawUsername: user.globalName,
});
await interaction.reply({ embeds: [simpleEmbed('Added user to the system')], ephemeral: true });

View File

@ -0,0 +1,49 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
const { Users } = require('../functions/models.js');
const { client } = require('../index.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ban')
.setDescription('Ban a user')
.setDefaultMemberPermissions(0)
.addUserOption(option => option
.setName('user')
.setDescription('The user to ban')
.setRequired(true))
.addStringOption(option => option
.setName('reason')
.setDescription('Why ban the user')
.setRequired(true)),
async execute(interaction) {
const member = interaction.options.getMember('user');
const reason = interaction.options.getString('reason');
try {
await member.ban({ reason });
} catch (error) {
console.error(error);
return await interaction.reply({ embeds: [simpleEmbed(`Error while banning ${member}`)], ephemeral: true });
}
const userInstance = await Users.findOne({ where: { id: member.id } });
if (!userInstance) return await interaction.reply({ embeds: [simpleEmbed('Error while getting user information')], ephemeral: true });
if (userInstance.minecraftUuid) {
await fetch(process.env.MINECRAFT_HOST + '/console', {
method: 'POST',
headers: {
'content-type': 'text/plain',
},
body: `ban ${userInstance.minecraftUuid} ${reason}`,
});
}
const channel = client.channels.cache.get(process.env.MOD_LOG_CHANNEL_ID);
await channel.send({ embeds: [simpleEmbed(`${interaction.user} banned ${member}, reason: **${reason}**`)] });
await interaction.reply({ embeds: [simpleEmbed(`Banned ${member}`)], ephemeral: true });
},
};

View File

@ -12,15 +12,15 @@ module.exports = {
try {
const user = await Users.findOne({ where: { id: interaction.user.id } });
if (!user.minecraftUUID) return await interaction.reply({ embeds: [simpleEmbed('You are not whitelisted')], ephemeral: true });
if (!user.minecraftUuid) return await interaction.reply({ embeds: [simpleEmbed('You are not whitelisted')], ephemeral: true });
await Minecraft.destroy({ where: { uuid: user.minecraftUUID } });
user.minecraftUUID = '';
await user.save();
await Minecraft.destroy({ where: { uuid: user.minecraftUuid } });
await applyUsername(user, interaction.member);
const role = await interaction.guild.roles.fetch(process.env.MINECRAFT_ROLE_ID);
await interaction.member.roles.remove(role);
await interaction.reply({ embeds: [simpleEmbed('Successfully removed you from the whitelist')], ephemeral: true });
} catch (error) {
console.error(error);

View File

@ -0,0 +1,49 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
const { Users } = require('../functions/models.js');
const { client } = require('../index.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('suspend')
.setDescription('Suspend a user')
.setDefaultMemberPermissions(0)
.addUserOption(option => option
.setName('user')
.setDescription('The user to suspend')
.setRequired(true))
.addNumberOption(option => option
.setName('time')
.setDescription('The amount of time to suspend the user in minutes')
.setRequired(true))
.addStringOption(option => option
.setName('reason')
.setDescription('Why suspend the user')
.setRequired(true)),
async execute(interaction) {
const time = interaction.options.getNumber('time');
const member = interaction.options.getMember('user');
const reason = interaction.options.getString('reason');
await member.timeout(time * 60 * 1000, reason);
const user = await Users.findOne({ where: { id: member.id } });
if (!user) return await interaction.reply({ embeds: [simpleEmbed('Error while getting user information')], ephemeral: true });
if (user.minecraftUuid) {
await fetch(process.env.MINECRAFT_HOST + '/console', {
method: 'POST',
headers: {
'content-type': 'text/plain',
},
body: `tempban ${user.minecraftUuid} ${time}m ${reason}`,
});
}
const channel = client.channels.cache.get(process.env.MOD_LOG_CHANNEL_ID);
await channel.send({ embeds: [simpleEmbed(`${interaction.user} suspended ${member} for **${time}** minutes, reason: **${reason}**`)] });
await interaction.reply({ embeds: [simpleEmbed(`Suspended ${member} for **${time}** minutes`)], ephemeral: true });
},
};

208
discordbot/commands/team.js Normal file
View File

@ -0,0 +1,208 @@
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: [] });
});
}
},
};

View File

@ -19,7 +19,7 @@ module.exports = {
const user = await Users.findOne({ where: { id: interaction.user.id } });
if (!user) return await interaction.reply({ embeds: [simpleEmbed('There was an error while finding the user')], ephemeral: true });
if (user.minecraftUUID) return await interaction.reply({ embeds: [simpleEmbed('You are already whitelisted')], ephemeral: true });
if (user.minecraftUuid) return await interaction.reply({ embeds: [simpleEmbed('You are already whitelisted')], ephemeral: true });
try {
const minecraftCol = await Minecraft.findOne({ where: { code: code } });
@ -32,13 +32,16 @@ module.exports = {
minecraftCol.whitelisted = true;
delete minecraftCol.code;
user.minecraftUUID = minecraftCol.uuid;
user.minecraftUuid = minecraftCol.uuid;
await minecraftCol.save();
await user.save();
await applyUsername(user, interaction.member);
const role = await interaction.guild.roles.fetch(process.env.MINECRAFT_ROLE_ID);
await interaction.member.roles.add(role);
await interaction.reply({ embeds: [simpleEmbed('You are successfully whitelisted')], ephemeral: true });
} catch (error) {
console.error(error);

Binary file not shown.

View File

@ -12,13 +12,14 @@ module.exports = {
.setThumbnail(member.user.avatarURL());
const channel = client.channels.cache.get(process.env.LOG_CHANNEL_ID);
channel.send({ embeds: [addMemberEmbed] });
await channel.send({ embeds: [addMemberEmbed] });
try {
await Users.create({
id: member.user.id,
});
} catch (error) {
if (error.name === 'SequelizeUniqueConstraintError') return;
console.error(error);
}
},

View File

@ -3,20 +3,21 @@ const { Events } = require('discord.js');
module.exports = {
name: Events.InteractionCreate,
async execute(interaction) {
if (!interaction.isChatInputCommand()) return;
if (interaction.isChatInputCommand() || interaction.isUserContextMenuCommand()) {
const command = interaction.client.commands.get(interaction.commandName);
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
try {
await command.execute(interaction);
} catch (error) {
console.error(`Error executing ${interaction.commandName}`);
console.error(error);
}
}
try {
await command.execute(interaction);
} catch (error) {
console.error(`Error executing ${interaction.commandName}`);
console.error(error);
}
},
};

View File

@ -0,0 +1,35 @@
const { Events } = require('discord.js');
const { Users } = require('../functions/models.js');
module.exports = {
name: Events.MessageCreate,
async execute(message) {
if (message.channelId === process.env.MINECRAFT_CHANNEL_ID && !message.author.bot) {
try {
const user = await Users.findOne({ where: { id: message.author.id } });
if (!user) return;
const team = await user.getTeam();
let tellraw;
if (!team) {
tellraw = `tellraw @a ["",{"text":"DC","color":"gray"},{"text":" ${user.rawUsername} > ${message.content}"}]`;
} else {
tellraw = `tellraw @a ["",{"text":"DC ","color":"dark_gray"},{"text":"[","color":"gray"},{"text":"${team.name}","color":"${team.color}"},{"text":"]","color":"gray"},{"text":" ${user.rawUsername} "},{"text":"> ${message.content}"}]`;
}
await fetch(process.env.MINECRAFT_HOST + '/console', {
method: 'POST',
headers: {
'content-type': 'text/plain',
},
body: tellraw,
});
} catch (error) {
console.error(error);
}
}
},
};

View File

@ -1,13 +1,13 @@
const { Events } = require('discord.js');
const deployCommands = require('../functions/deployCommands');
const { Users, Teams, Minecraft } = require('../functions/models');
const { Users, Team, Minecraft } = require('../functions/models');
module.exports = {
name: Events.ClientReady,
once: true,
execute(client) {
Users.sync();
Teams.sync();
Team.sync();
Minecraft.sync();
console.log(`Ready! Logged in as ${client.user.tag}`);

View File

@ -1,3 +1,4 @@
const { PartialWebhookMixin } = require('discord.js');
const { sequelize } = require('../index');
const Sequelize = require('sequelize');
@ -7,12 +8,6 @@ const Users = sequelize.define('users', {
primaryKey: true,
unique: true,
},
teamId: {
type: Sequelize.STRING,
},
minecraftUUID: {
type: Sequelize.UUID,
},
useMinecraftUsername: {
type: Sequelize.BOOLEAN,
defaultValue: false,
@ -30,7 +25,7 @@ const Users = sequelize.define('users', {
},
});
const Teams = sequelize.define('teams', {
const Team = sequelize.define('teams', {
name: {
type: Sequelize.STRING,
unique: true,
@ -45,6 +40,12 @@ const Teams = sequelize.define('teams', {
is: /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
},
},
textChannelId: {
type: Sequelize.STRING,
},
voiceChannelId: {
type: Sequelize.STRING,
},
});
const Minecraft = sequelize.define('minecraft', {
@ -63,4 +64,10 @@ const Minecraft = sequelize.define('minecraft', {
},
});
module.exports = { Users, Teams, Minecraft };
Minecraft.hasOne(Users);
Users.belongsTo(Minecraft);
Team.hasMany(Users, { as: 'members' });
Users.belongsTo(Team);
module.exports = { Users, Team, Minecraft };

View File

@ -1,8 +1,10 @@
const applyUsername = async (user, member) => {
await user.reload();
let rawUsername = member.user.globalName;
if (user.useMinecraftUsername && user.minecraftUUID) {
const response = await fetch(`https://sessionserver.mojang.com/session/minecraft/profile/${user.minecraftUUID}`);
if (user.useMinecraftUsername && user.minecraftUuid) {
const response = await fetch(`https://sessionserver.mojang.com/session/minecraft/profile/${user.minecraftUuid}`);
const minecraftProfile = await response.json();
rawUsername = minecraftProfile.name;
@ -10,14 +12,18 @@ const applyUsername = async (user, member) => {
user.rawUsername = rawUsername;
await user.save();
await member.setNickname(rawUsername);
const username = await getUsername(user);
return rawUsername;
await user.save();
await member.setNickname(username.slice(0, 32));
return username;
};
const getUsername = (user) => {
return user.rawUsername;
const getUsername = async (user) => {
const team = await user.getTeam();
return team ? user.rawUsername + ' [' + team.name + ']' : user.rawUsername;
};
module.exports = { applyUsername, getUsername };

View File

@ -14,7 +14,7 @@ router.post('/player', async (req, res) => {
try {
const user = await Users.findOne({ where: { minecraftUUID: uuid } });
const username = getUsername(user);
const username = await getUsername(user);
webhookClient.send({
content,

View File

@ -1,6 +1,5 @@
const express = require('express');
const { Minecraft, Users } = require('../functions/models.js');
const { getUsername } = require('../functions/utils.js');
const router = express.Router();
@ -10,17 +9,30 @@ router.post('/', async (req, res) => {
if (!uuid) return res.status(400).send({ errorMessage: 'UUID is required' });
try {
const minecraftCol = await Minecraft.findOrCreate({
where: { uuid },
defaults: {
code: generateCode().toString(),
},
});
const user = await Users.findOne({ where: { minecraftUUID: uuid } });
const username = getUsername(user);
res.send({ code: minecraftCol[0].code, whitelisted: minecraftCol[0].whitelisted, username, rawUsername: user.rawUsername });
if (!user) {
const minecraftCol = await Minecraft.findOrCreate({
where: { uuid },
defaults: {
code: generateCode().toString(),
},
});
return res.send({ code: minecraftCol[0].code, whitelisted: minecraftCol[0].whitelisted });
}
const team = await user.getTeam();
let username;
if (!team) {
username = user.rawUsername;
} else {
username = '<gray>[</gray>' + `<color:${team.color}>${team.name}</color>` + '<gray>] </gray>' + user.rawUsername;
}
res.send({ whitelisted: true, username, rawUsername: user.rawUsername });
} catch (error) {
console.log(error);