Discord Bot Documentation
The MyNATCA Discord Bot provides secure member verification, role management, and community integration for NATCA Discord servers.
Overview
The Discord bot serves as the primary interface for NATCA members to verify their identity and gain access to Discord community features. It integrates with Auth0 for secure authentication and automatically manages Discord roles based on member positions.
Key Features
Member Verification System
- OAuth-based Verification: Secure member linking through Auth0
- Automated Role Assignment: Position-based role management
- Real-time Updates: Webhook support for member changes
- Administrative Tools: Manual verification and account management
Role Management
- Position-based Roles: Automatic assignment based on NATCA positions
- Facility Roles: Facility-specific role assignment
- Region Roles: Regional organization role management
- Audit Logging: Comprehensive tracking of role changes
Community Features
- Welcome Messages: Automated member onboarding
- Nickname Management: Automatic nickname updates
- Administrative Commands: Tools for server management
Modular Architecture (90% Reduction in Code Size)
The Discord bot has been completely refactored from a 778-line monolith to a clean 78-line entry point with modular libraries. This represents a 90% reduction in code size while improving maintainability and functionality.
Bot Architecture Overview
Modular Components
1. Core Entry Point (bot.js - 78 lines)
// Clean, minimal entry point focusing on initialization
const config = require('./lib/config');
const HttpServer = require('./lib/httpServer');
const EventHandlers = require('./lib/eventHandlers');
async function initializeBot() {
loadCommands();
const httpServer = new HttpServer(client);
const eventHandlers = new EventHandlers(client);
await client.login(process.env.DISCORD_TOKEN);
}2. Configuration Management (lib/config.js)
Features:
- Environment variable validation
- Production/development logging configuration
- Graceful shutdown handling
- Database table prefix management
Key Methods:
validateEnvironment() // Validates required env vars
setupLogging() // Configures logging levels
logStartupInfo() // Detailed startup diagnostics
setupGracefulShutdown() // SIGTERM/SIGINT handling3. Event Handling (lib/eventHandlers.js)
Features:
- Discord.js event processing
- Automated member validation scheduling
- Command interaction handling
- Member join/leave processing
- Registration help messages in #verify channel (Added October 2025)
Key Events:
ClientReady: Bot initialization completeInteractionCreate: Slash command processingGuildMemberAdd/Remove: Member lifecycle eventsMessageCreate: Registration help detection (Added October 2025)- Scheduled validation (daily at 2:00 AM UTC)
Registration Help Messages (New Feature - October 2025):
The bot now provides automatic assistance in the #verify channel when users make common registration mistakes:
// Event handler detects common registration mistakes
client.on('messageCreate', async (message) => {
// Detect messages in #verify channel that aren't /register command
// Auto-reply with helpful @mention messages
// Messages auto-delete after 30 seconds to keep channel clean
});Detected Patterns:
- Member numbers entered directly (5 digits without /register command)
- Misspelled /register command variations (e.g., "/regsiter", "register")
- Help keywords ("how", "help", "what", "where", "register?")
- Any non-command messages in #verify channel
User Experience:
- Bot sends targeted @mention help message explaining how to use /register
- Help messages automatically delete after 30 seconds
- Keeps #verify channel clean while providing guidance
- Reduces support requests by proactively helping users
4. HTTP Server & Webhooks (lib/httpServer.js)
Features:
- Express.js webhook server
- Health check endpoints
- Platform integration webhooks
- Role assignment webhook handling
Endpoints:
GET /health // Health check
POST /webhook/role-assignment // Role assignment from platform
POST /webhook/member-unlink // Member unlinking from platform5. Member Validation (lib/memberValidator.js)
Features:
- Daily member validation (2:00 AM UTC)
- RNAV member identification logic
- Batch processing with statistics
- Error handling and logging
RNAV Logic Implementation:
// Identifies RNAV members using membertypeid=6 AND status='Retired'
const isRNAVMember = (memberData) => {
return memberData.membertypeid === 6 && memberData.status === 'Retired';
};6. Role Management (lib/roleManager.js)
Features:
- Position-based role assignment including Staff positions
- Facility and region roles
- Nickname management with position-specific formatting
- Role hierarchy enforcement
Staff Position Handling (Updated October 2025):
The role manager now includes comprehensive Staff position support with special handling for Chief of Staff:
// Updated setMemberNickname to accept positions parameter
setMemberNickname(member, memberData, positions) {
const { firstname, lastname } = memberData;
// Chief of Staff gets special designation
const isChiefOfStaff = positions?.some(p =>
p.positiontype === 'staff' && p.position.toLowerCase().includes('chief of staff')
);
// Check for any staff position
const hasStaffPosition = positions?.some(p => p.positiontype === 'staff');
if (isChiefOfStaff) {
nickname = `${firstname} ${lastname} (Chief of Staff)`;
} else if (hasStaffPosition) {
nickname = `${firstname} ${lastname} (Staff)`;
}
// ... other nickname logic (facility/region for regular members)
}Role Assignment Logic:
The role mapping system now includes Staff positions as a recognized position type:
const roleMap = {
'pres': 'NEB', 'evp': 'NEB', 'rvp': 'NEB',
'facrep': 'FacRep', 'arearep': 'FacRep',
'comchair': 'Committee Chair',
'commember': 'Committee Member',
'staff': 'NATCA Staff' // Added October 2025: Staff position support
};
const memberTypeRoles = {
6: 'NATCA Member', // Current Member
8: 'NATCA Staff', // NATCA Staff (member type)
10: 'RNAV Member' // Retired Member
};Key Implementation Details:
- Staff position type ('staff') maps to "NATCA Staff" Discord role
- Chief of Staff receives special "(Chief of Staff)" nickname designation
- Other staff positions receive "(Staff)" nickname designation
- Staff members with
membertypeid=8automatically receive "NATCA Staff" role - Position-based staff detection works independently of member type
7. Production Logging (lib/logger.js)
Features:
- JSON-structured logging for OpenSearch compatibility
- Clean JSON output without emoji or unstructured text
- Timestamp, level, service, message, and context fields
- Environment-aware logging levels
- Error tracking with stack traces
- Startup diagnostics
Log Format: All logs output as structured JSON:
{
"timestamp": "2025-10-01T12:34:56.789Z",
"level": "info",
"service": "discord-bot",
"message": "Bot successfully logged in",
"context": {
"username": "MyNATCA Bot",
"guilds": 1
}
}Logging Methods:
logger.info(message, context) // General information with optional context
logger.error(message, error) // Error logging with stack traces
logger.warn(message, context) // Warning messages
logger.debug(message, context) // Development debugging (only in NODE_ENV=development)OpenSearch Integration: The JSON logging format is designed for seamless integration with OpenSearch for centralized log aggregation:
- Consistent timestamp format (ISO 8601)
- Structured context objects for filtering and analysis
- Service field for multi-service log aggregation
- Stack traces included in error logs for debugging
RNAV Member Identification Logic
The system includes enhanced logic to properly identify and handle RNAV (Retired NATCA Air Traffic Controllers) members using a dual-criteria approach.
RNAV Identification Criteria
RNAV members are identified by:
// RNAV Logic: membertypeid=6 AND status='Retired'
const isRNAVMember = (memberData) => {
return memberData.membertypeid === 6 && memberData.status === 'Retired';
};Member Type Classifications
const memberTypeRoles = {
6: 'NATCA Member', // Current Active Members
8: 'NATCA Staff', // NATCA National Staff
10: 'RNAV Member' // Retired Members (legacy type)
};
// Special case: Type 6 + Status 'Retired' = RNAV Member
// This handles retired members who maintain type 6 in the systemImplementation Across Components
1. Platform Verification (/routes/verify.js)
// Nickname assignment logic
if (memberData.membertypeid === 8) {
// NATCA Staff members
nickname = `${memberData.firstname} ${memberData.lastname} (Staff)`;
} else if (memberData.membertypeid === 6 && memberData.status === 'Retired') {
// RNAV Members (member type 6 + status Retired)
nickname = `${memberData.firstname} ${memberData.lastname} (RNAV)`;
} else {
// Regular Current Members (6) get region/facility formatting
nickname = `${memberData.firstname} ${memberData.lastname} (${regionCode}/${facilityCode})`;
}2. Discord Bot Role Management (lib/roleManager.js)
// Role assignment with RNAV detection
if (memberData.membertypeid === 8) {
// NATCA Staff members
assignedRoles.push('NATCA Staff');
nickname = `${memberData.firstname} ${memberData.lastname} (Staff)`;
} else if (memberData.membertypeid === 6 && memberData.status === 'Retired') {
// RNAV Members (member type 6 + status Retired)
assignedRoles.push('RNAV Member');
nickname = `${memberData.firstname} ${memberData.lastname} (RNAV)`;
console.log(`👤 RNAV member detected (type 6 + Retired) - using RNAV nickname format`);
} else if (memberData.membertypeid === 6) {
// Regular Current Members
assignedRoles.push('NATCA Member');
} else if (memberData.membertypeid === 10) {
// Legacy retired member type
assignedRoles.push('RNAV Member');
}3. Member Validation (lib/memberValidator.js)
// Daily validation includes RNAV status checks
const validMemberTypes = [6, 8, 10]; // Include all valid types
this.validMemberTypes = validMemberTypes;
// Validation process checks both type and status
if (memberData.membertypeid === 6 && memberData.status === 'Retired') {
expectedNickname = `${memberData.firstname} ${memberData.lastname} (RNAV)`;
expectedRoles.push('RNAV Member');
}Database Schema Considerations
The dual-criteria approach is necessary because:
- Historical Data: Some retired members maintain
membertypeid=6in the database - Status Field: The
statusfield provides the current membership status - Legacy Support: Existing
membertypeid=10still supported for legacy retired members
Validation and Sync Process
The sync process from MySQL to Supabase includes RNAV status:
-- Sync includes status field for RNAV identification
SELECT membernumber, firstname, lastname, membertypeid, status,
facility_id, region_id, ...
FROM members
WHERE status IN ('Active', 'Retired')This ensures that both active and retired member statuses are synchronized, enabling proper RNAV identification in the Discord bot and platform.
Verification Flow
The verification process now uses professional EJS templates for user-friendly error and success messaging:
Template-Based Responses:
error.ejs- Professional error pages for expired links, missing member numbers, member not found, already linked accountssuccess.ejs- Success confirmation pages after verification completion- Replaces previous raw JSON error responses
- Provides clear user guidance and next steps
Error Scenarios with Template Rendering:
- Expired Link: Shows time expired and provides re-registration link
- Missing Member Number: Explains requirement and shows registration steps
- Member Not Found: Suggests checking member number or contacting support
- Already Linked: Confirms existing link and provides unlink instructions
- Update Error: Shows technical details and support contact information
Setup and Configuration
Prerequisites
- Node.js 18+ with npm/yarn
- Discord Application with bot token
- Auth0 Account for member verification
- Supabase Project for data storage
Discord Application Setup
Create Discord Application
- Go to Discord Developer Portal (opens in a new tab)
- Click "New Application" and name it "MyNATCA Bot"
- Navigate to "Bot" section
- Click "Add Bot" and confirm
- Copy the bot token for configuration
Bot Permissions
Required permissions for proper functionality:
Text Permissions:
✅ Send Messages
✅ Use Slash Commands
✅ Read Message History
✅ Mention Everyone
General Permissions:
✅ Manage Roles
✅ Manage Nicknames
✅ View Channels
✅ Change NicknameOAuth2 URL Generator
- Go to OAuth2 > URL Generator
- Select scopes:
bot,applications.commands - Select required permissions
- Use generated URL to invite bot to server
Discord Server Configuration
Role Hierarchy Setup
Critical: Bot role must be positioned above managed roles:
Server Role Hierarchy (top to bottom):
1. Server Admin
2. MyNATCA Bot ← Bot role here
3. NEB
4. FacRep
5. Committee Member
6. Regional Rep
7. NATCA Member ← Managed roles below
8. @everyoneRequired Roles
Create these roles in your Discord server:
# Base roles
NATCA Member # All verified members
Verified # Alternative base role name
# Position-based roles
FacRep # Facility Representatives
NEB # National Executive Board
Committee Member # Committee chairs/members
Regional Rep # Regional representatives
# Facility-specific roles (optional)
ZTL # Atlanta TRACON
A90 # Boston TRACON
# ... add other facility codes as needed
# Region-specific roles (optional)
Region 1
Region 2
# ... add other regions as neededEnvironment Configuration
# Discord Configuration
DISCORD_TOKEN=your_discord_bot_token
DISCORD_CLIENT_ID=your_discord_application_id
DISCORD_GUILD_ID=your_discord_server_id
# Auth0 Configuration
AUTH0_DOMAIN=natca-prod.us.auth0.com
AUTH0_CLIENT_ID=your_auth0_client_id
AUTH0_CLIENT_SECRET=your_auth0_client_secret
AUTH0_SECRET=your_auth0_secret_key
AUTH0_BASE_URL=https://discord.mynatca.org
AUTH0_ISSUER_BASE_URL=https://natca-prod.us.auth0.com
AUTH0_SCOPE=openid profile email
# Supabase Configuration
SUPABASE_URL=your_supabase_project_url
SUPABASE_KEY=your_supabase_service_key
# Web Server Configuration
PORT=3003
BASE_URL=https://discord.mynatca.org
NODE_ENV=productionCommands
User Commands
/register
Description: Link Discord account to NATCA member record
Usage: /register member_number:123456
Parameters:
member_number(required): NATCA member number
Process:
- Validates member number exists in database
- Creates verification request in Supabase
- Generates secure verification link
- Sends private message with link to user
- Link expires after 30 minutes
Example:
User: /register member_number:123456
Bot: ✅ Verification link sent! Check your DMs.
Link expires in 30 minutes./status
Description: Check verification status and current roles
Usage: /status
Response: Shows current verification status, assigned roles, and member information
Supported Member Types:
- NATCA Members (membertypeid=6)
- NATCA Staff (membertypeid=8)
- RNAV Members (membertypeid=10)
Implementation:
// Query includes all valid member types
const { data: memberData } = await supabase
.from('members')
.select('*')
.eq('discordid', userId)
.in('membertypeid', [6, 8, 10]) // Changed from .eq('membertypeid', 6)
.single();Example:
✅ Verified Member
Name: John Doe
Member #: 123456
Member Type: NATCA Staff
Roles: NATCA StaffAdministrative Commands
/admin verify
Description: Manually verify a member (Admin only)
Usage: /admin verify member_number:123456 discord_user:@username
Parameters:
member_number(required): NATCA member numberdiscord_user(required): Discord user to verify
Permissions: Requires admin role or position-based permissions
/admin unlink
Description: Unlink Discord account from member record (Admin only)
Usage: /admin unlink discord_user:@username
Parameters:
discord_user(required): Discord user to unlink
Process:
- Removes all NATCA-related roles
- Updates database records
- Logs administrative action
/admin refresh
Description: Refresh member roles based on current database (Admin only)
Usage: /admin refresh discord_user:@username
Parameters:
discord_user(optional): Specific user to refresh, or all if omitted
Process:
- Fetches current member data from database
- Compares with Discord roles
- Adds/removes roles as needed
- Updates nicknames if configured
/admin stats
Description: Display verification and member statistics (Admin only)
Usage: /admin stats
Response: Shows verification rates, member counts, and system health
Role Management
Role Assignment Logic
The bot automatically assigns roles based on member data:
// Role mapping configuration
const positionRoleMap = {
'facrep': 'FacRep',
'comchair': 'Committee Member',
'neb': 'NEB',
'regional': 'Regional Rep'
};
const facilityRoles = {
'ZTL': 'ZTL',
'A90': 'A90',
// ... other facility codes
};
const regionRoles = {
'ASO': 'Region ASO',
'CWP': 'Region CWP',
// ... other region codes
};Role Assignment Process
- Base Role: All verified members receive "NATCA Member" role
- Position Roles: Assigned based on leadership positions
- Facility Roles: Based on member's facility assignment
- Region Roles: Based on member's regional assignment
- Nickname Update: Sets nickname to "First Last" format
Role Hierarchy Enforcement
The bot checks role hierarchy before assignment:
- Bot role must be above all managed roles
- Cannot assign roles higher than bot's position
- Logs warnings for hierarchy issues
Event Handling
Guild Member Events
Member Join
client.on('guildMemberAdd', async (member) => {
// Send welcome message
// Check if member is already verified
// Assign roles if verification exists
});Member Leave
client.on('guildMemberRemove', async (member) => {
// Log member departure
// Clean up verification records if configured
});Role Events
Role Updates
client.on('guildMemberUpdate', async (oldMember, newMember) => {
// Detect role changes
// Log administrative actions
// Sync with database if needed
});Web Interface
Verification Pages
Landing Page (/verify)
- Welcome message and instructions
- Link to start verification process
- Support contact information
Verification Flow (/verify/[id])
- Validates verification request
- Initiates Auth0 OAuth flow
- Renders professional EJS templates for all responses
- Provides user-friendly error and success messaging
Template System:
The verification system uses EJS templates for all user-facing responses:
error.ejs Template:
<!-- Professional error page with dynamic error messages -->
- Expired verification links
- Missing member numbers
- Member not found in database
- Account already linked to another Discord user
- Database update errorssuccess.ejs Template:
<!-- Success confirmation page -->
- Verification completion confirmation
- Member information display
- Discord role assignment confirmation
- Next steps and instructionsBenefits:
- Professional, branded user experience
- Clear error messages with actionable guidance
- Consistent styling across all verification states
- Better user engagement and reduced support requests
- Replaces previous raw JSON error responses
Status Page (/status)
- Member verification status
- Current Discord roles
- Member information display
- Troubleshooting links
API Endpoints
Health Check (/api/health)
{
"status": "healthy",
"bot_status": "online",
"database": "connected",
"auth0": "connected"
}Verification Status (/api/verify/status/[id])
{
"status": "pending",
"discord_id": "123456789012345678",
"member_number": "123456",
"expires_at": "2023-01-01T01:30:00.000Z"
}Monitoring and Logging
Health Monitoring
Bot Status Checks
- Discord API connectivity
- Database connection health
- Auth0 service availability
- Command response times
Performance Metrics
- Verification completion rates
- Role assignment success rates
- Command usage statistics
- Error rates and types
Logging
JSON-Structured Logging for OpenSearch
The Discord bot uses structured JSON logging for compatibility with OpenSearch and centralized log aggregation:
// lib/logger.js - Production logging implementation
const logger = {
info: (message, context = {}) => {
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
level: 'info',
service: 'discord-bot',
message,
context
}));
},
error: (message, error = null) => {
const logEntry = {
timestamp: new Date().toISOString(),
level: 'error',
service: 'discord-bot',
message
};
if (error) {
logEntry.error = {
message: error.message,
stack: error.stack,
code: error.code
};
}
console.error(JSON.stringify(logEntry));
},
warn: (message, context = {}) => {
console.warn(JSON.stringify({
timestamp: new Date().toISOString(),
level: 'warn',
service: 'discord-bot',
message,
context
}));
}
};Log Output Examples:
// Successful operation
{
"timestamp": "2025-10-01T12:00:00.000Z",
"level": "info",
"service": "discord-bot",
"message": "Member verified successfully",
"context": {
"memberId": "12345",
"discordId": "123456789012345678",
"rolesAssigned": ["NATCA Member", "FacRep"]
}
}
// Error with stack trace
{
"timestamp": "2025-10-01T12:00:01.000Z",
"level": "error",
"service": "discord-bot",
"message": "Failed to assign roles",
"error": {
"message": "Missing permissions",
"stack": "Error: Missing permissions\n at RoleManager.assignRoles...",
"code": "MISSING_PERMISSIONS"
}
}OpenSearch Configuration
To send Discord bot logs to OpenSearch:
- Configure log shipping (Filebeat, Fluentd, or direct streaming):
# filebeat.yml example
filebeat.inputs:
- type: container
paths:
- '/var/lib/docker/containers/*/*.log'
json.keys_under_root: true
json.add_error_key: true
processors:
- add_docker_metadata:
host: "unix:///var/run/docker.sock"
output.elasticsearch:
hosts: ["opensearch:9200"]
index: "discord-bot-logs-%{+yyyy.MM.dd}"- Create OpenSearch index pattern for Discord bot logs with fields:
timestamp(date)level(keyword)service(keyword)message(text)context.*(nested object)error.message(text)error.stack(text)
Audit Trail
All structured logs automatically create an audit trail:
- All verification attempts with member and Discord user context
- Role assignments and removals with before/after states
- Administrative actions with admin user context
- Error occurrences with full stack traces and error codes
- Command executions with user, guild, and command details
Alerting
Critical Alerts
- Bot offline/disconnected
- Database connection failures
- High error rates
- Auth0 service issues
Warning Alerts
- Verification failures
- Role hierarchy issues
- Performance degradation
- Unusual activity patterns
Security Considerations
Token Security
- Discord bot token stored securely
- Regular token rotation
- Environment variable protection
- No hardcoded credentials
Access Control
- Role-based command permissions
- Admin action logging
- Rate limiting on commands
- Input validation and sanitization
Data Protection
- Minimal data collection
- Secure data transmission
- Regular security audits
- Compliance with privacy policies
Command Development Best Practices
Guild Access Pattern
All Discord commands that interact with guild resources must use the guild access fallback pattern to prevent null reference errors.
Problem
In some cases, interaction.guild can be null even when commands are executed in a guild context, causing errors like:
Cannot read properties of null (reading 'members')Solution: Guild Access Fallback Pattern
// CORRECT: Use fallback pattern
const guild = interaction.guild || interaction.client.guilds.cache.first();
if (!guild) {
return interaction.reply({
content: 'This command can only be used in a server.',
ephemeral: true
});
}
// Now safely access guild resources
const member = await guild.members.fetch(userId);Implementation Example from /refresh command:
// commands/refresh.js
async execute(interaction) {
// Guild access with fallback
const guild = interaction.guild || interaction.client.guilds.cache.first();
if (!guild) {
return interaction.reply({
content: 'Unable to access guild. Please try again.',
ephemeral: true
});
}
// Safely access guild members
const member = await guild.members.fetch(userId);
// ... rest of command logic
}Applied To Commands
This pattern has been applied to all commands that interact with guild resources:
/refresh user- Refresh specific user roles/refresh member- Refresh by member number/refresh all- Refresh all verified members- All administrative commands requiring guild access
DM Permission Protection
Commands that require guild context should explicitly disable DM usage to prevent errors:
// Command definition with DM protection
const { SlashCommandBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('refresh')
.setDescription('Refresh member roles')
.setDMPermission(false), // Prevent DM usage
async execute(interaction) {
// Guild access is guaranteed
const guild = interaction.guild || interaction.client.guilds.cache.first();
// ... command logic
}
};Why This Matters:
- Prevents confusing error messages for users
- Improves user experience by hiding unavailable commands in DMs
- Reduces error logging from invalid command contexts
- Ensures guild-dependent features work reliably
Command Testing
Test Suite Overview
The Discord bot includes a comprehensive test suite (test-commands.js) that validates all slash commands without requiring a live Discord connection.
Features:
- Mock Discord objects for reliable testing
- Tests all 7 slash commands
- 18 test cases covering various scenarios
- Validates Staff and RNAV member handling
- Tests command permissions and error handling
Running Tests:
# Run all command tests
npm test
# Run tests with detailed stack traces
npm run test:verboseTest Coverage (Updated October 2025):
The comprehensive test suite validates all Discord bot functionality including the new Staff and RNAV member support:
-
Registration Commands
/registerwith valid member number/registerwith invalid member number- Registration error handling
-
Status Commands (Enhanced for Staff/RNAV)
/statusfor NATCA Members (membertypeid=6)/statusfor Staff members (membertypeid=8) - New Test Case/statusfor RNAV members (membertypeid=10) - New Test Case- Unverified user handling
-
Administrative Commands
/verifymanual verification/unlinkaccount unlinking/refreshrole synchronization- Permission validation
-
Member Type Handling (Enhanced October 2025)
- Staff member role assignment with "NATCA Staff" role
- RNAV member detection and role assignment
- Position-based nickname formatting (Staff, Chief of Staff)
- Role hierarchy validation
Test Implementation:
The test suite (discord/test-commands.js) includes 18 test cases covering all member types:
- Tests use mock Discord objects for reliability
- Mock Supabase responses for each member type (6, 8, 10)
- Validates response formats and error handling
- Ensures Staff and RNAV members receive correct roles
Test Output Example:
Testing Discord Bot Commands
✓ /register command works
✓ /status command works for NATCA Members (membertypeid=6)
✓ /status command works for Staff (membertypeid=8)
✓ /status command works for RNAV (membertypeid=10)
✓ /verify command works
✓ /unlink command works
✓ /refresh command works
✓ Staff position nickname formatting
✓ Chief of Staff designation
All 18 command tests passed!Running Tests:
# Run all command tests
npm test
# Run tests with detailed stack traces
npm run test:verboseTroubleshooting
Common Issues
Guild Access Errors
Symptoms:
Cannot read properties of null (reading 'members')TypeError: interaction.guild is null- Commands fail silently or with generic errors
Root Cause:
Discord.js may return null for interaction.guild in certain edge cases, even when the command is executed in a guild context.
Solution:
-
Use guild access fallback pattern in all commands:
const guild = interaction.guild || interaction.client.guilds.cache.first(); -
Add DM permission protection to command definitions:
.setDMPermission(false) -
Always validate guild exists before accessing guild resources:
if (!guild) { return interaction.reply({ content: 'Error accessing guild', ephemeral: true }); }
Bot Not Responding
- Check bot permissions in Discord
- Verify bot role hierarchy
- Check Discord token validity
- Confirm guild ID is correct
- Verify commands are deployed with
npm run deploy
Verification Failures
- Check Auth0 configuration
- Verify database connectivity
- Validate callback URLs
- Review error logs
Role Assignment Issues
- Check role hierarchy
- Verify bot permissions
- Review member data
- Test role mapping logic
Debug Commands
# Test Discord connectivity
npm run test:discord
# Check database connection
npm run test:database
# Validate Auth0 integration
npm run test:auth0
# Run full system check
npm run test:integrationThis comprehensive Discord bot documentation provides all necessary information for setup, configuration, and maintenance of the MyNATCA Discord integration.