-
Notifications
You must be signed in to change notification settings - Fork 320
Description
require('dotenv').config();
const {
Client,
GatewayIntentBits,
REST,
Routes,
SlashCommandBuilder,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
ModalBuilder,
TextInputBuilder,
TextInputStyle,
ChannelType,
PermissionFlagsBits,
EmbedBuilder,
} = require('discord.js');
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
});
// Registrar comandos
const commands = [
new SlashCommandBuilder()
.setName('create-ticket')
.setDescription('Cria uma mensagem com botão para abrir tickets'),
new SlashCommandBuilder()
.setName('close')
.setDescription('Exclui o canal se ele for um ticket criado pelo bot')
.setDefaultMemberPermissions(PermissionFlagsBits.ManageChannels),
new SlashCommandBuilder()
.setName('add')
.setDescription('Adiciona um membro ao ticket')
.addUserOption((option) =>
option.setName('user').setDescription('Usuário a ser adicionado').setRequired(true)
)
.setDefaultMemberPermissions(PermissionFlagsBits.ManageChannels),
new SlashCommandBuilder()
.setName('rename')
.setDescription('Renomeia o canal atual')
.addStringOption((option) =>
option.setName('new_name').setDescription('Novo nome do canal').setRequired(true)
)
.setDefaultMemberPermissions(PermissionFlagsBits.ManageChannels),
new SlashCommandBuilder()
.setName('sms')
.setDescription('Envia uma mensagem direta ao usuário com o link do canal atual')
.addUserOption((option) =>
option.setName('user').setDescription('Usuário a ser notificado').setRequired(true)
)
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
new SlashCommandBuilder()
.setName('vsms')
.setDescription('Envia uma mensagem específica para o usuário com um link fixo')
.addUserOption((option) =>
option.setName('user').setDescription('Usuário a ser notificado').setRequired(true)
)
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
];
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
(async () => {
try {
console.log('Registrando comandos...');
await rest.put(
Routes.applicationGuildCommands(process.env.CLIENT_ID, process.env.GUILD_ID),
{ body: commands.map((command) => command.toJSON()) }
);
console.log('Comandos registrados com sucesso!');
} catch (error) {
console.error('Erro ao registrar comandos:', error);
}
})();
client.once('ready', () => {
console.log(Bot online como: ${client.user.tag});
});
client.on('interactionCreate', async (interaction) => {
try {
if (interaction.isChatInputCommand()) {
const { commandName } = interaction;
if (commandName === 'create-ticket') {
const embed = {
color: 0xffffff,
title: 'Zapshop Ticket',
description: 'Caso queira comprar algo, abra um ticket aqui!',
footer: {
text: 'Zapshop - Single Server Ticket',
icon_url: 'https://upload.wikimedia.org/wikipedia/commons/a/ac/No_image_available.svg',
},
};
const button = new ButtonBuilder()
.setCustomId('create_ticket')
.setLabel('📨 Criar Ticket')
.setStyle(ButtonStyle.Primary);
const row = new ActionRowBuilder().addComponents(button);
// Envia mensagem visível a todos no canal
await interaction.channel.send({
embeds: [embed],
components: [row],
});
await interaction.reply({
content: 'Mensagem de criação de ticket enviada com sucesso!',
ephemeral: true,
});
}
if (commandName === 'close') {
const channel = interaction.channel;
if (!channel) {
await interaction.reply({
content: 'Não foi possível encontrar o canal.',
ephemeral: true,
});
return;
}
await interaction.reply('Fechando o canal em 3 segundos...');
setTimeout(() => channel.delete(), 3000);
}
if (commandName === 'add') {
const user = interaction.options.getUser('user');
const channel = interaction.channel;
await channel.permissionOverwrites.edit(user.id, {
ViewChannel: true,
SendMessages: true,
});
await interaction.reply({
content: `Usuário ${user.tag} foi adicionado ao ticket.`,
ephemeral: true,
});
}
if (commandName === 'rename') {
const newName = interaction.options.getString('new_name');
const channel = interaction.channel;
await channel.setName(newName);
await interaction.reply({
content: `Canal renomeado para: ${newName}`,
ephemeral: true,
});
}
if (commandName === 'sms') {
const user = interaction.options.getUser('user');
const channelLink = `https://discord.com/channels/${interaction.guild.id}/${interaction.channel.id}`;
await user.send(
`Alguém está te chamando no ticket: [Clique aqui para acessar o ticket](${channelLink}).`
);
await interaction.reply({
content: `Mensagem enviada para ${user.tag}.`,
ephemeral: true,
});
}
if (commandName === 'vsms') {
const user = interaction.options.getUser('user');
const mensagem = `**${user.tag} Muito obrigado por comprar na zap'shop.**\n\nCaso tenha gostado da compra, nos avalie com a mensagem abaixo:\n\nVouch <@916302724281290782> em zap'shop. R$ por rbx\n\n👆 Mande em https://discord.com/channels/1257195351010709515/1257198570084499517\n\nMuito obrigado. Caso queira comprar mais ou tenha alguma dúvida, crie um ticket em https://discord.com/channels/1257195351010709515/1323408674797912154`;
await user.send(mensagem);
await interaction.reply({
content: `Mensagem enviada para ${user.tag}.`,
ephemeral: true,
});
}
}
if (interaction.isButton() && interaction.customId === 'create_ticket') {
const modal = new ModalBuilder()
.setCustomId('ticket_form')
.setTitle('Preencha as informações abaixo');
const question1 = new TextInputBuilder()
.setCustomId('question1')
.setLabel('Nome ou link da Gamepass')
.setPlaceholder('Ex: dragon perm ┃ https://www.roblox.com/game-pass/abc')
.setStyle(TextInputStyle.Short)
.setRequired(true);
const question2 = new TextInputBuilder()
.setCustomId('question2')
.setLabel('Nome do Jogo:')
.setPlaceholder('Ex: blox fruit')
.setStyle(TextInputStyle.Paragraph)
.setRequired(true);
const question3 = new TextInputBuilder()
.setCustomId('question3')
.setLabel('Custo em Robux:')
.setPlaceholder('Ex: 5000')
.setStyle(TextInputStyle.Short)
.setRequired(true);
const question4 = new TextInputBuilder()
.setCustomId('question4')
.setLabel('Seu Nickname:')
.setPlaceholder('Ex: joao123')
.setStyle(TextInputStyle.Short)
.setRequired(true);
const question5 = new TextInputBuilder()
.setCustomId('question5')
.setLabel('Informação extra:')
.setPlaceholder('Opcional')
.setStyle(TextInputStyle.Paragraph)
.setRequired(false);
modal.addComponents(
new ActionRowBuilder().addComponents(question1),
new ActionRowBuilder().addComponents(question2),
new ActionRowBuilder().addComponents(question3),
new ActionRowBuilder().addComponents(question4),
new ActionRowBuilder().addComponents(question5)
);
await interaction.showModal(modal);
}
if (interaction.isModalSubmit() && interaction.customId === 'ticket_form') {
const question1 = interaction.fields.getTextInputValue('question1');
const question2 = interaction.fields.getTextInputValue('question2');
const question3 = interaction.fields.getTextInputValue('question3');
const question4 = interaction.fields.getTextInputValue('question4');
const question5 = interaction.fields.getTextInputValue('question5') || 'Nenhuma informação extra';
const ticketCategoryId = process.env.TICKETCATEGORY_ID;
if (!ticketCategoryId) {
await interaction.reply({
content: 'O ID da categoria de tickets não foi configurado no arquivo .env.',
ephemeral: true,
});
return;
}
const ticketCategory = interaction.guild.channels.cache.get(ticketCategoryId);
if (!ticketCategory || ticketCategory.type !== ChannelType.GuildCategory) {
await interaction.reply({
content: 'Categoria de tickets inválida ou não encontrada.',
ephemeral: true,
});
return;
}
const ticketCost = question3.match(/\d+/)?.[0] || 'ticket';
const ticketName = `${ticketCost}rbx`;
const ticketChannel = await interaction.guild.channels.create({
name: ticketName,
type: ChannelType.GuildText,
parent: ticketCategory.id,
permissionOverwrites: [
{
id: interaction.guild.id,
deny: [PermissionFlagsBits.ViewChannel],
},
{
id: interaction.user.id,
allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.SendMessages],
},
],
});
const embed = new EmbedBuilder()
.setColor(0xD7DF01)
.setTitle("ZAP'SHOP - ticket")
.setDescription(
`📦 **Nome da Gamepass:**\n${question1}\n\n` +
`🎮 **Nome do Jogo:**\n${question2}\n\n` +
`💰 **Custo em Robux:**\n${question3}rbx\n\n` +
`👤 **Nickname:**\n${question4}\n\n` +
`📝 **Informação Extra:**\n${question5}`
)
.setFooter({
text: 'use /preçorbx para ver quantos R$ que custa',
iconURL: 'https://cdn.discordapp.com/attachments/1323567092498174076/1328866681615024298/new.png',
})
.setThumbnail('https://cdn.discordapp.com/attachments/1323567092498174076/1328866681615024298/new.png');
const ticketMessage = await ticketChannel.send({ embeds: [embed] });
await ticketMessage.pin();
const notificationMessage = `🎟️ **Novo Ticket Criado** 🎟️\n\n👤 **Usuário:** ${interaction.user.tag}\n📦 **Nome da Gamepass:** ${question1}\n🎮 **Nome do Jogo:** ${question2}\n💰 **Custo em Robux:** ${question3}rbx\n👤 **Nickname:** ${question4}\n📝 **Informação Extra:** ${question5}\n🔗 **Acesse o Ticket:** [Clique aqui](https://discord.com/channels/${interaction.guild.id}/${ticketChannel.id})`;
const zapUser = await client.users.fetch(process.env.ZAP_ID);
const mtUser = await client.users.fetch(process.env.MT_ID);
await zapUser.send(notificationMessage);
await mtUser.send(notificationMessage);
await interaction.reply({
content: `Ticket criado com sucesso! [Clique aqui para acessar o ticket](https://discord.com/channels/${interaction.guild.id}/${ticketChannel.id})`,
ephemeral: true,
});
}
} catch (error) {
console.error('Erro ao processar interação:', error);
if (!interaction.replied) {
await interaction.reply({
content: 'Ocorreu um erro ao processar a interação.',
ephemeral: true,
});
}
}
});
// Inicializar o cliente
client.login(process.env.DISCORD_TOKEN);