const { ContainerBuilder, EmbedBuilder, ComponentType, MessageFlags } = require('discord.js'); const APPLICATION_QUESTIONS = [ "What is your full name and age?", "What timezone are you in and what are your typical online hours?", "Do you have any previous moderation or staff experience? If yes, please describe.", "Why do you want to become a staff member on this server?", "How would you handle a situation where two members are arguing in chat?", "What would you do if you caught a friend breaking server rules?", "How many hours per week can you dedicate to staff duties?", "Is there anything else you'd like us to know about you or your application?" ]; async function startApplicationProcess(user, client, applicationId) { try { const dmChannel = await user.createDM(); const startContainer = new ContainerBuilder() .setAccentColor(0x00FF00) .addTextDisplayComponents( textDisplay => textDisplay .setContent('# šŸ“ **STAFF APPLICATION PROCESS**\n\n**━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━**') ) .addSectionComponents( section => section .addTextDisplayComponents( textDisplay => textDisplay .setContent('šŸŽ‰ **Welcome to the staff application process!**'), textDisplay => textDisplay .setContent(`**Application ID:** \`${applicationId}\`\n**Total Questions:** \`${APPLICATION_QUESTIONS.length}\`\n**Estimated Time:** \`15-20 minutes\``) ) ) .addSeparatorComponents( separator => separator ) .addSectionComponents( section => section .addTextDisplayComponents( textDisplay => textDisplay .setContent('**Instructions:**\n• Answer each question thoughtfully and honestly\n• Take your time - there\'s no rush\n• You can type "cancel" at any time to stop\n• Your responses will be reviewed by our HR team') ) ) .addTextDisplayComponents( textDisplay => textDisplay .setContent('**━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━**\n\n*Ready to begin? The first question will appear shortly...*') ); await dmChannel.send({ components: [startContainer], flags: MessageFlags.IsComponentsV2 }); setTimeout(async () => { await askQuestions(dmChannel, user, client, applicationId); }, 3000); return true; } catch (error) { console.error('Error starting application process:', error); return false; } } async function askQuestions(dmChannel, user, client, applicationId) { const responses = []; const startTime = Date.now(); for (let i = 0; i < APPLICATION_QUESTIONS.length; i++) { try { const questionContainer = new ContainerBuilder() .setAccentColor(0x3498DB) .addTextDisplayComponents( textDisplay => textDisplay .setContent(`# šŸ“‹ Question ${i + 1} of ${APPLICATION_QUESTIONS.length}`) ) .addSectionComponents( section => section .addTextDisplayComponents( textDisplay => textDisplay .setContent(`**${APPLICATION_QUESTIONS[i]}**`) ) ) .addTextDisplayComponents( textDisplay => textDisplay .setContent(`*Application ID: ${applicationId} | Type "cancel" to stop*`) ); await dmChannel.send({ components: [questionContainer], flags: MessageFlags.IsComponentsV2 }); const filter = (message) => message.author.id === user.id; const collector = dmChannel.createMessageCollector({ filter, max: 1, time: 300000 }); const response = await new Promise((resolve, reject) => { collector.on('collect', (message) => { if (message.content.toLowerCase() === 'cancel') { resolve('CANCELLED'); } else { resolve(message.content); } }); collector.on('end', (collected, reason) => { if (reason === 'time' && collected.size === 0) { resolve('TIMEOUT'); } }); }); if (response === 'CANCELLED') { const cancelContainer = new ContainerBuilder() .setAccentColor(0xFF0000) .addTextDisplayComponents( textDisplay => textDisplay .setContent('# āŒ **APPLICATION CANCELLED**\n\n**━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━**') ) .addSectionComponents( section => section .addTextDisplayComponents( textDisplay => textDisplay .setContent('šŸ›‘ **Your application has been cancelled**'), textDisplay => textDisplay .setContent(`**Application ID:** \`${applicationId}\`\n**Questions Completed:** \`${i} of ${APPLICATION_QUESTIONS.length}\``) ) ) .addTextDisplayComponents( textDisplay => textDisplay .setContent('**━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━**\n\nYou can start a new application anytime by using the application button in the server.\n\n*Thank you for your interest!*') ); await dmChannel.send({ components: [cancelContainer], flags: MessageFlags.IsComponentsV2 }); return; } if (response === 'TIMEOUT') { const timeoutContainer = new ContainerBuilder() .setAccentColor(0xFFA500) .addTextDisplayComponents( textDisplay => textDisplay .setContent('# ā° **APPLICATION TIMEOUT**\n\n**━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━**') ) .addSectionComponents( section => section .addTextDisplayComponents( textDisplay => textDisplay .setContent('ā±ļø **Your application has timed out**'), textDisplay => textDisplay .setContent(`**Application ID:** \`${applicationId}\`\n**Questions Completed:** \`${i} of ${APPLICATION_QUESTIONS.length}\``) ) ) .addTextDisplayComponents( textDisplay => textDisplay .setContent('**━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━**\n\nYou can start a new application anytime by using the application button in the server.\n\n*Thank you for your interest!*') ); await dmChannel.send({ components: [timeoutContainer], flags: MessageFlags.IsComponentsV2 }); return; } responses.push({ question: APPLICATION_QUESTIONS[i], answer: response, questionNumber: i + 1 }); const confirmContainer = new ContainerBuilder() .setAccentColor(0x00FF00) .addSectionComponents( section => section .addTextDisplayComponents( textDisplay => textDisplay .setContent('āœ… **Answer Recorded**'), textDisplay => textDisplay .setContent(`Progress: **${i + 1}/${APPLICATION_QUESTIONS.length}** questions completed`) ) ) .addTextDisplayComponents( textDisplay => textDisplay .setContent('Your response has been saved. Please wait for the next question...') ); await dmChannel.send({ components: [confirmContainer], flags: MessageFlags.IsComponentsV2 }); if (i < APPLICATION_QUESTIONS.length - 1) { await new Promise(resolve => setTimeout(resolve, 2000)); } } catch (error) { console.error(`Error on question ${i + 1}:`, error); const errorContainer = new ContainerBuilder() .setAccentColor(0xFF0000) .addTextDisplayComponents( textDisplay => textDisplay .setContent('# āŒ **ERROR**') ) .addTextDisplayComponents( textDisplay => textDisplay .setContent('There was an error processing your response. Please try starting a new application.') ); await dmChannel.send({ components: [errorContainer], flags: MessageFlags.IsComponentsV2 }); return; } } await completeApplication(dmChannel, user, client, applicationId, responses, startTime); } async function completeApplication(dmChannel, user, client, applicationId, responses, startTime) { const completionTime = Date.now(); const timeSpent = Math.floor((completionTime - startTime) / 1000 / 60); try { const completionContainer = new ContainerBuilder() .setAccentColor(0x00FF00) .addTextDisplayComponents( textDisplay => textDisplay .setContent('# šŸŽ‰ **APPLICATION COMPLETED!**\n\n**━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━**') ) .addSectionComponents( section => section .addTextDisplayComponents( textDisplay => textDisplay .setContent('āœ… **Your staff application has been successfully submitted!**'), textDisplay => textDisplay .setContent(`**Application ID:** \`${applicationId}\`\n**Questions Completed:** \`${responses.length}/${APPLICATION_QUESTIONS.length}\`\n**Time Spent:** \`${timeSpent} minutes\``) ) ) .addSeparatorComponents( separator => separator ) .addSectionComponents( section => section .addTextDisplayComponents( textDisplay => textDisplay .setContent('**What happens next?**\n• Your application will be reviewed by our HR team\n• You\'ll receive an update within 5-7 business days\n• Check <#1322304705031966800> for general updates') ) ) .addTextDisplayComponents( textDisplay => textDisplay .setContent('**━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━**\n\n*Thank you for applying! • HR Team*') ); await dmChannel.send({ components: [completionContainer], flags: MessageFlags.IsComponentsV2 }); await submitToHR(client, user, applicationId, responses, timeSpent); } catch (error) { console.error('Error completing application:', error); } } async function submitToHR(client, user, applicationId, responses, timeSpent) { try { const HR_CHANNEL_ID = 'YOUR_HR_CHANNEL_ID'; const hrChannel = client.channels.cache.get(HR_CHANNEL_ID); if (!hrChannel) return; const embed = new EmbedBuilder() .setTitle('šŸ“‹ **NEW STAFF APPLICATION**') .setColor(0xFFD700) .setAuthor({ name: user.tag, iconURL: user.displayAvatarURL() }) .addFields( { name: 'Application Details', value: `**ID:** \`${applicationId}\`\n**Time Spent:** \`${timeSpent} minutes\`\n**Status:** 🟔 PENDING REVIEW`, inline: false } ) .setThumbnail(user.displayAvatarURL()) .setTimestamp() .setFooter({ text: 'Staff Application System' }); for (let i = 0; i < Math.min(responses.length, 20); i++) { const response = responses[i]; let value = response.answer; if (value.length > 1024) { value = value.substring(0, 1021) + '...'; } embed.addFields({ name: `${response.questionNumber}. ${response.question}`, value: value, inline: false }); } await hrChannel.send({ embeds: [embed] }); } catch (error) { console.error('Error submitting to HR:', error); } } module.exports = { startApplicationProcess, APPLICATION_QUESTIONS };