Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const {
- Client,
- GatewayIntentBits,
- EmbedBuilder,
- ButtonBuilder,
- ButtonStyle,
- ActionRowBuilder,
- ChannelType,
- Partials
- } = require('discord.js');
- const config = require('./config.json');
- const RECRUITER_ROLE_ID = '1393350418683396198';
- const PB_STAFF_ROLE_ID = '1393326980006678669';
- const HEAD_OF_RECRUITMENT_ROLE_ID = '1393326540028252210';
- const LIVERY_CREATOR_ROLE_ID = '1393552424316305448';
- const CLOTHING_CREATOR_ROLE_ID = '1393552487629197378';
- const claimPermissions = {
- application: [RECRUITER_ROLE_ID, HEAD_OF_RECRUITMENT_ROLE_ID, PB_STAFF_ROLE_ID],
- support_recruiter_app: [HEAD_OF_RECRUITMENT_ROLE_ID, PB_STAFF_ROLE_ID],
- support_report: [PB_STAFF_ROLE_ID],
- support_other: [PB_STAFF_ROLE_ID],
- support_livery: [LIVERY_CREATOR_ROLE_ID, PB_STAFF_ROLE_ID],
- support_clothing: [CLOTHING_CREATOR_ROLE_ID, PB_STAFF_ROLE_ID]
- };
- const closePermissions = {
- application: [HEAD_OF_RECRUITMENT_ROLE_ID, PB_STAFF_ROLE_ID],
- support_recruiter_app: [HEAD_OF_RECRUITMENT_ROLE_ID, PB_STAFF_ROLE_ID],
- support_report: [PB_STAFF_ROLE_ID],
- support_other: [PB_STAFF_ROLE_ID],
- support_livery: [LIVERY_CREATOR_ROLE_ID, PB_STAFF_ROLE_ID],
- support_clothing: [CLOTHING_CREATOR_ROLE_ID, PB_STAFF_ROLE_ID]
- };
- function getThreadType(name) {
- if (name.startsWith('[APP]-')) return 'application';
- if (name.startsWith('[R-APP]-')) return 'support_recruiter_app';
- if (name.startsWith('[REP]-')) return 'support_report';
- if (name.startsWith('[OTH]-')) return 'support_other';
- if (name.startsWith('[LIV]-')) return 'support_livery';
- if (name.startsWith('[CCL]-')) return 'support_clothing';
- return null;
- }
- const client = new Client({
- intents: [
- GatewayIntentBits.Guilds,
- GatewayIntentBits.GuildMessages,
- GatewayIntentBits.MessageContent,
- GatewayIntentBits.GuildMembers
- ],
- partials: [Partials.Channel]
- });
- client.once('ready', async () => {
- console.log(`✅ Logged in as ${client.user.tag}`);
- // registrační slash příkazů
- await client.application.commands.set([
- {
- name: 'pb-trial',
- description: 'Send a trial message to the current channel',
- options: [
- {
- name: 'days',
- description: 'Number of trial days',
- type: 4, // INTEGER
- required: true
- }
- ]
- },
- {
- name: 'pb-notrial',
- description: 'Send acceptance message to the current channel'
- }
- ]);
- // inicializační embed pro aplikace
- const appChannel = await client.channels.fetch(config.channelId).catch(() => null);
- if (appChannel) {
- const appEmbed = new EmbedBuilder()
- .setTitle('Peaky Blinders Application')
- .setDescription(
- "**Ready to join the ranks of the fiercest crew in town?**\n" +
- "Click **\"Join\"** below to open your private application ticket. 📝\n\n" +
- "*Our Recruiters will be watching closely and will meet you there shortly to guide you through the trials ahead.* 🔥\n\n" +
- "**Remember — this isn’t just a crew, it’s a family.**\n" +
- "*Show us what you’re made of.* 💥\n\n" +
- "**Good luck, and may the razor be sharp.** ✂️"
- )
- .setColor(0xFF0000);
- const appRow = new ActionRowBuilder().addComponents(
- new ButtonBuilder().setCustomId('apply_join').setLabel('Join').setStyle(ButtonStyle.Danger)
- );
- const msgs = await appChannel.messages.fetch({ limit: 10 });
- const existing = msgs.find(m => m.author.id === client.user.id && m.components.length > 0);
- if (existing) await existing.edit({ embeds: [appEmbed], components: [appRow] });
- else await appChannel.send({ embeds: [appEmbed], components: [appRow] });
- }
- // inicializační embed pro support systém
- if (config.channelIdSupport) {
- const supportChannel = await client.channels.fetch(config.channelIdSupport).catch(() => null);
- if (supportChannel) {
- const supportEmbed = new EmbedBuilder()
- .setTitle('✍️ Peaky Blinders Support System')
- .setDescription(
- "**[OTH]** *Other Issues* 🛠️\n" +
- "**[REP]** *Reporting a Member* 📝\n" +
- "**[R-APP]** *Recruiter Application* 🎩\n" +
- "**[LIV]** *Livery Creation & Suggest* 🎨\n" +
- "**[CCL]** *Clothing Creation & Suggest* 👔\n\n" +
- "*Click the button below to open your ticket.*"
- )
- .setColor(0x00f3ff)
- .setFooter({ text: 'Peaky Blinders Support System' })
- .setTimestamp();
- const buttons = [
- ['support_other', 'Other 🛠️', ButtonStyle.Success],
- ['support_report', 'Report 📝', ButtonStyle.Danger],
- ['support_recruiter_app', 'Recruiter App 🎩', ButtonStyle.Primary],
- ['support_livery', 'Livery 🎨', ButtonStyle.Secondary],
- ['support_clothing', 'Clothing 👔', ButtonStyle.Secondary]
- ].map(([id, label, style]) => new ButtonBuilder().setCustomId(id).setLabel(label).setStyle(style));
- const supportRow = new ActionRowBuilder().addComponents(...buttons);
- const msgs = await supportChannel.messages.fetch({ limit: 10 });
- const existing = msgs.find(m => m.author.id === client.user.id && m.components.length > 0);
- if (existing) await existing.edit({ embeds: [supportEmbed], components: [supportRow] });
- else await supportChannel.send({ embeds: [supportEmbed], components: [supportRow] });
- }
- }
- });
- client.on('interactionCreate', async interaction => {
- // 🌟 slash příkazy
- if (interaction.isChatInputCommand()) {
- const member = await interaction.guild.members.fetch(interaction.user.id).catch(() => null);
- if (!member)
- return interaction.reply({ content: '❌ Unable to fetch your member data.', ephemeral: true });
- const allowed = [
- RECRUITER_ROLE_ID,
- PB_STAFF_ROLE_ID,
- HEAD_OF_RECRUITMENT_ROLE_ID
- ];
- if (!allowed.some(r => member.roles.cache.has(r)))
- return interaction.reply({ content: '❌ You do not have permission to use this command.', ephemeral: true });
- if (interaction.commandName === 'pb-trial') {
- const days = interaction.options.getInteger('days');
- const embed = new EmbedBuilder()
- .setColor(0xffd700)
- .setTitle('📌 Trial Notice')
- .setDescription(
- "*Starting today, your trial period officially begins.*\n" +
- `*This trial will last for **${days} days**, during which we’ll evaluate your activity, behavior, communication, and overall fit with the crew.*\n\n` +
- "*We're not expecting perfection but we do expect presence, respect, and effort.*\n\n" +
- "**🧠 Make sure to read everything written [here](https://discord.com/channels/1206571308456878100/1393329313100595381) carefully.**\n" +
- "*There are no excuses for missing important details during trial.*\n\n" +
- "*Use this time to prove you belong here.*\n" +
- "*Welcome aboard, and good luck.*\n\n" +
- "***By order of the crew.***"
- );
- return interaction.reply({ embeds: [embed] });
- }
- if (interaction.commandName === 'pb-notrial') {
- const embed = new EmbedBuilder()
- .setColor(0x3498db)
- .setTitle('🎩 You’ve Been Accepted')
- .setDescription(
- "***By Order of the Crew 🔱***\n\n" +
- "*As of today, you’re no longer just on trial*\n" +
- "*You’re now a** full member** of the crew. 🎩💼*\n" +
- "*You made it through because you showed **loyalty, presence, and discipline** — traits we don’t take lightly.*\n\n" +
- "*But don’t get comfortable. 🥃*\n" +
- "**Wearing the tag means something now.**\n" +
- "*You carry the name, the rep, and the weight that comes with it.*\n" +
- "*Every word, every move, every mistake — it reflects on all of us. 🕶️*\n\n" +
- "***We don’t recruit numbers.***\n" +
- "***We build a unit.***\n" +
- "**We stand for:**\n" +
- "***⚔️ Loyalty***\n" +
- "***🩸 Brotherhood***\n" +
- "***💼 Respect***\n" +
- "***🎯 Precision***\n\n" +
- "*If you're here to **ghost, slack, or chase clout** — this ain’t your place.*\n" +
- "*But if you’re here to ride with us, to earn respect and move like a brotherhood...*\n" +
- "***Then welcome to the real game. 🔥***\n\n" +
- "***Stick with the crew. Protect the name.***\n" +
- "*We win together — or we don’t win at all.*\n\n" +
- "***By Order of the Peaky Blinders 🥃***"
- );
- return interaction.reply({ embeds: [embed] });
- }
- }
- // 🚪 tlačítka a thready
- if (!interaction.isButton()) return;
- const member = await interaction.guild.members.fetch(interaction.user.id).catch(() => null);
- if (!member) return interaction.reply({ content: '❌ Unable to fetch your member data.', ephemeral: true });
- const supportTypes = {
- support_other: {
- namePrefix: '[OTH]-',
- pingRoles: [PB_STAFF_ROLE_ID],
- embedColor: 0x2ECC71,
- embedTitle: '🛠️ Other Issues',
- embedDesc:
- "This is your ticket for other support-related matters.\n" +
- "Describe your issue clearly and our staff will help you shortly."
- },
- support_report: {
- namePrefix: '[REP]-',
- pingRoles: [PB_STAFF_ROLE_ID],
- embedColor: 0xE74C3C,
- embedTitle: '📝 Reporting a Member',
- embedDesc:
- "Use this form to report behavior that violates the rules.\n" +
- "Include evidence if possible (screenshots, video, etc.)."
- },
- support_recruiter_app: {
- namePrefix: '[R-APP]-',
- pingRoles: [HEAD_OF_RECRUITMENT_ROLE_ID, PB_STAFF_ROLE_ID],
- embedColor: 0xE67E22,
- embedTitle: '🎩 Recruiter Application',
- embedDesc:
- "This is your recruiter application support ticket.\n" +
- "Our recruitment team will assist you shortly."
- },
- support_livery: {
- namePrefix: '[LIV]-',
- pingRoles: [LIVERY_CREATOR_ROLE_ID],
- embedColor: 0x3498DB,
- embedTitle: '🎨 Livery Creation',
- embedDesc:
- "Need help with liveries or want to suggest one?\n" +
- "Let our creation team know here."
- },
- support_clothing: {
- namePrefix: '[CCL]-',
- pingRoles: [CLOTHING_CREATOR_ROLE_ID],
- embedColor: 0x9B59B6,
- embedTitle: '👔 Clothing Creation & Suggest',
- embedDesc:
- "Looking to customize clothing or suggest a design?\n" +
- "Our creators are here to help."
- }
- };
- if (interaction.customId === 'apply_join') {
- const thread = await interaction.channel.threads.create({
- name: `[APP]-${interaction.user.username}`,
- autoArchiveDuration: 1440,
- type: ChannelType.PrivateThread,
- reason: `Application by ${interaction.user.tag}`
- });
- const embed1 = new EmbedBuilder()
- .setTitle('📥 Welcome to your Peaky Blinders Crew application!')
- .setDescription(
- "Please fill out the application form below carefully and follow the instructions to proceed."
- )
- .setColor(0x5865F2);
- const embed2 = new EmbedBuilder()
- .setTitle('📝 Application Form')
- .setDescription(
- "1️⃣ **In-game Level:**\n" +
- "2️⃣ **In-game Name:**\n" +
- "3️⃣ **Age:**\n" +
- "4️⃣ **Activity Level:** (Active / Semi-Active / Not Much)\n" +
- "5️⃣ **Working Mic?** (Yes/No)\n" +
- "6️⃣ **Understanding of CNR Rules?** (Yes/No)\n" +
- "7️⃣ **Ban History:** (Provide your record from CNR Staff)"
- )
- .setColor(0x3498db);
- const embed3 = new EmbedBuilder()
- .setTitle('📛 Ban History & Final Steps')
- .setDescription(
- "**Cops and Robbers Discord:** [Click Here](https://discord.com/invite/6mvRUxF)\n" +
- "**Ban History Request:** [Click Here](https://discord.com/channels/738534756538384499/814776227537747970)\n\n" +
- "Please send us a photo of your Ban History and ping your recruiter inside the thread.\n\n" +
- "🧠 **Easier Way:**\n" +
- "Go to the #support channel → Click on \"Thread\" → Choose \"Other\" → Request your Ban History.\n" +
- "You’ll usually get it within 1–60 minutes.\n\n" +
- "*A recruiter will be with you shortly.*"
- )
- .setImage('https://cdn.discordapp.com/attachments/1393574770720903243/1393574830900777010/Snimek_obrazovky_2025-07-12_144809.png')
- .setColor(0xe74c3c)
- .setFooter({ text: `Requested by ${interaction.user.tag}` })
- .setTimestamp();
- const claimButton = new ButtonBuilder().setCustomId('claim_ticket').setLabel('Claim').setStyle(ButtonStyle.Success);
- const closeButton = new ButtonBuilder().setCustomId('close_ticket').setLabel('Close').setStyle(ButtonStyle.Danger);
- const row = new ActionRowBuilder().addComponents(claimButton, closeButton);
- const mentions = [`<@${interaction.user.id}>`, `<@&${RECRUITER_ROLE_ID}>`, `<@&${PB_STAFF_ROLE_ID}>`].join(' ');
- await thread.send({ content: `||${mentions}||`, embeds: [embed1, embed2, embed3], components: [row] });
- return await interaction.reply({ content: '✅ Your application thread has been created!', ephemeral: true });
- }
- if (interaction.customId.startsWith('support_')) {
- const type = supportTypes[interaction.customId];
- if (!type) return interaction.reply({ content: '❌ Unknown support type.', ephemeral: true });
- const thread = await interaction.channel.threads.create({
- name: `${type.namePrefix}${interaction.user.username}`,
- autoArchiveDuration: 1440,
- type: ChannelType.PrivateThread,
- reason: `Support Ticket by ${interaction.user.tag}`
- });
- const embed = new EmbedBuilder()
- .setTitle(type.embedTitle)
- .setDescription(type.embedDesc)
- .setColor(type.embedColor)
- .setFooter({ text: `Requested by ${interaction.user.tag}` })
- .setTimestamp();
- const row = new ActionRowBuilder().addComponents(
- new ButtonBuilder().setCustomId('claim_ticket').setLabel('Claim').setStyle(ButtonStyle.Success),
- new ButtonBuilder().setCustomId('close_ticket').setLabel('Close').setStyle(ButtonStyle.Danger)
- );
- const mentions = [
- `<@${interaction.user.id}>`,
- ...type.pingRoles.map(r => `<@&${r}>`)
- ].join(' ');
- await thread.send({ content: `||${mentions}||`, embeds: [embed], components: [row] });
- await interaction.reply({ content: '✅ Your support ticket thread has been created!', ephemeral: true });
- return;
- }
- // Claim ticket
- if (interaction.customId === 'claim_ticket') {
- const thread = interaction.channel;
- const threadType = getThreadType(thread.name || '');
- const allowed = claimPermissions[threadType] || [];
- const hasPerm = allowed.some(r => member.roles.cache.has(r));
- if (!hasPerm) return interaction.reply({ content: '❌ You do not have permission to claim this ticket.', ephemeral: true });
- const msg = interaction.message;
- const row = msg.components[0];
- const already = row.components.find(c => c.customId === 'claim_ticket')?.data.disabled;
- if (already) return interaction.reply({ content: '❌ Ticket already claimed.', ephemeral: true });
- const newRow = new ActionRowBuilder();
- for (const comp of row.components) {
- newRow.addComponents(ButtonBuilder.from(comp).setDisabled(comp.customId === 'claim_ticket'));
- }
- await interaction.update({
- content: `✅ Claimed by <@${interaction.user.id}>.`,
- components: [newRow]
- });
- }
- // Close ticket
- if (interaction.customId === 'close_ticket') {
- const thread = interaction.channel;
- const threadType = getThreadType(thread.name || '');
- const allowed = closePermissions[threadType] || [];
- const hasPerm = allowed.some(r => member.roles.cache.has(r));
- if (!hasPerm) return interaction.reply({ content: '❌ You do not have permission to close this ticket.', ephemeral: true });
- await interaction.reply({ content: '🔒 Ticket has been closed.' });
- if (thread.isThread()) {
- await thread.setLocked(true);
- await thread.setArchived(true);
- }
- }
- });
- client.login(config.token);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement