Introduce several new slash commands including ban, kick, timeout, and userinfo. Enhance existing commands like config and rank with new features and configurations. Add new listeners for welcome and goodbye messages. Implement XP tracking for user leveling and integrate it with role rewards. Update documentation to reflect these changes. Replit-Commit-Author: Agent Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261 Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: 1be8d824-5029-4875-bed8-0bd1d810892d Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/SQxsvtx Replit-Helium-Checkpoint-Created: true
120 lines
4.5 KiB
JavaScript
120 lines
4.5 KiB
JavaScript
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
|
|
|
|
const BADGE_INFO = {
|
|
'verified': { emoji: '✅', name: 'Verified', description: 'Linked Discord to AeThex' },
|
|
'early_adopter': { emoji: '🌟', name: 'Early Adopter', description: 'Joined during early access' },
|
|
'contributor': { emoji: '💎', name: 'Contributor', description: 'Contributed to the community' },
|
|
'creator': { emoji: '🎨', name: 'Creator', description: 'Published projects on Studio' },
|
|
'supporter': { emoji: '❤️', name: 'Supporter', description: 'Donated to the Foundation' },
|
|
'level_10': { emoji: '🔟', name: 'Level 10', description: 'Reached level 10' },
|
|
'level_25': { emoji: '🏆', name: 'Level 25', description: 'Reached level 25' },
|
|
'level_50': { emoji: '👑', name: 'Level 50', description: 'Reached level 50' },
|
|
'streak_7': { emoji: '🔥', name: 'Week Streak', description: '7 day daily claim streak' },
|
|
'streak_30': { emoji: '💪', name: 'Month Streak', description: '30 day daily claim streak' },
|
|
'helpful': { emoji: '🤝', name: 'Helpful', description: 'Helped 10+ community members' },
|
|
'bug_hunter': { emoji: '🐛', name: 'Bug Hunter', description: 'Reported a valid bug' },
|
|
};
|
|
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('badges')
|
|
.setDescription('View your earned badges across all platforms')
|
|
.addUserOption(option =>
|
|
option.setName('user')
|
|
.setDescription('User to view (defaults to yourself)')
|
|
.setRequired(false)
|
|
),
|
|
|
|
async execute(interaction, supabase, client) {
|
|
if (!supabase) {
|
|
return interaction.reply({ content: 'Database not configured.', ephemeral: true });
|
|
}
|
|
|
|
const target = interaction.options.getUser('user') || interaction.user;
|
|
await interaction.deferReply();
|
|
|
|
try {
|
|
const { data: link } = await supabase
|
|
.from('discord_links')
|
|
.select('user_id')
|
|
.eq('discord_id', target.id)
|
|
.single();
|
|
|
|
if (!link) {
|
|
return interaction.editReply({
|
|
embeds: [
|
|
new EmbedBuilder()
|
|
.setColor(0xff6b6b)
|
|
.setDescription(`${target.id === interaction.user.id ? 'You are' : `${target.tag} is`} not linked to AeThex.`)
|
|
]
|
|
});
|
|
}
|
|
|
|
const { data: profile } = await supabase
|
|
.from('user_profiles')
|
|
.select('username, avatar_url, badges, xp, daily_streak')
|
|
.eq('id', link.user_id)
|
|
.single();
|
|
|
|
let earnedBadges = [];
|
|
|
|
if (profile?.badges) {
|
|
earnedBadges = typeof profile.badges === 'string'
|
|
? JSON.parse(profile.badges)
|
|
: profile.badges;
|
|
}
|
|
|
|
earnedBadges.push('verified');
|
|
|
|
const xp = profile?.xp || 0;
|
|
const level = Math.floor(Math.sqrt(xp / 100));
|
|
if (level >= 10) earnedBadges.push('level_10');
|
|
if (level >= 25) earnedBadges.push('level_25');
|
|
if (level >= 50) earnedBadges.push('level_50');
|
|
|
|
const streak = profile?.daily_streak || 0;
|
|
if (streak >= 7) earnedBadges.push('streak_7');
|
|
if (streak >= 30) earnedBadges.push('streak_30');
|
|
|
|
earnedBadges = [...new Set(earnedBadges)];
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setColor(0x7c3aed)
|
|
.setTitle(`${profile?.username || target.tag}'s Badges`)
|
|
.setThumbnail(profile?.avatar_url || target.displayAvatarURL())
|
|
.setTimestamp();
|
|
|
|
if (earnedBadges.length > 0) {
|
|
const badgeDisplay = earnedBadges.map(key => {
|
|
const info = BADGE_INFO[key];
|
|
if (info) {
|
|
return `${info.emoji} **${info.name}**\n${info.description}`;
|
|
}
|
|
return `🏅 **${key}**`;
|
|
}).join('\n\n');
|
|
|
|
embed.setDescription(badgeDisplay);
|
|
embed.addFields({ name: 'Total Badges', value: `${earnedBadges.length}`, inline: true });
|
|
} else {
|
|
embed.setDescription('No badges earned yet. Keep engaging to earn badges!');
|
|
}
|
|
|
|
const allBadgeKeys = Object.keys(BADGE_INFO);
|
|
const lockedBadges = allBadgeKeys.filter(k => !earnedBadges.includes(k));
|
|
|
|
if (lockedBadges.length > 0 && lockedBadges.length <= 6) {
|
|
const lockedDisplay = lockedBadges.map(key => {
|
|
const info = BADGE_INFO[key];
|
|
return `🔒 ${info.name}`;
|
|
}).join(', ');
|
|
embed.addFields({ name: 'Locked Badges', value: lockedDisplay });
|
|
}
|
|
|
|
await interaction.editReply({ embeds: [embed] });
|
|
|
|
} catch (error) {
|
|
console.error('Badges error:', error);
|
|
await interaction.editReply({ content: 'Failed to fetch badge data.' });
|
|
}
|
|
},
|
|
};
|