AeThex-Bot-Master/aethex-bot/commands/leaderboard.js
sirpiglr b178664f99 Make Supabase features optional and integrate new security systems
Updates bot.js to make Supabase integration optional, adds Sentinel security listeners, and modifies several commands to handle missing Supabase configurations gracefully. Also updates package.json and replit.md for new dependencies and features.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 0d645005-4840-49ef-9446-2c62d2bb7eed
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/Wmps8l5
Replit-Helium-Checkpoint-Created: true
2025-12-07 23:41:11 +00:00

158 lines
5 KiB
JavaScript

const { SlashCommandBuilder, EmbedBuilder } = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("leaderboard")
.setDescription("View the top AeThex contributors")
.addStringOption((option) =>
option
.setName("category")
.setDescription("Leaderboard category")
.setRequired(false)
.addChoices(
{ name: "🔥 Most Active (Posts)", value: "posts" },
{ name: "❤️ Most Liked", value: "likes" },
{ name: "🎨 Top Creators", value: "creators" }
)
),
async execute(interaction, supabase) {
if (!supabase) {
return interaction.reply({ content: "This feature requires Supabase to be configured.", ephemeral: true });
}
await interaction.deferReply();
try {
const category = interaction.options.getString("category") || "posts";
let leaderboardData = [];
let title = "";
let emoji = "";
if (category === "posts") {
title = "Most Active Posters";
emoji = "🔥";
const { data: posts } = await supabase
.from("community_posts")
.select("user_id")
.not("user_id", "is", null);
const postCounts = {};
posts?.forEach((post) => {
postCounts[post.user_id] = (postCounts[post.user_id] || 0) + 1;
});
const sortedUsers = Object.entries(postCounts)
.sort(([, a], [, b]) => b - a)
.slice(0, 10);
for (const [userId, count] of sortedUsers) {
const { data: profile } = await supabase
.from("user_profiles")
.select("username, full_name, avatar_url")
.eq("id", userId)
.single();
if (profile) {
leaderboardData.push({
name: profile.full_name || profile.username || "Anonymous",
value: `${count} posts`,
username: profile.username,
});
}
}
} else if (category === "likes") {
title = "Most Liked Users";
emoji = "❤️";
const { data: posts } = await supabase
.from("community_posts")
.select("user_id, likes_count")
.not("user_id", "is", null)
.order("likes_count", { ascending: false });
const likeCounts = {};
posts?.forEach((post) => {
likeCounts[post.user_id] =
(likeCounts[post.user_id] || 0) + (post.likes_count || 0);
});
const sortedUsers = Object.entries(likeCounts)
.sort(([, a], [, b]) => b - a)
.slice(0, 10);
for (const [userId, count] of sortedUsers) {
const { data: profile } = await supabase
.from("user_profiles")
.select("username, full_name, avatar_url")
.eq("id", userId)
.single();
if (profile) {
leaderboardData.push({
name: profile.full_name || profile.username || "Anonymous",
value: `${count} likes received`,
username: profile.username,
});
}
}
} else if (category === "creators") {
title = "Top Creators";
emoji = "🎨";
const { data: creators } = await supabase
.from("aethex_creators")
.select("user_id, total_projects, verified, featured")
.order("total_projects", { ascending: false })
.limit(10);
for (const creator of creators || []) {
const { data: profile } = await supabase
.from("user_profiles")
.select("username, full_name, avatar_url")
.eq("id", creator.user_id)
.single();
if (profile) {
const badges = [];
if (creator.verified) badges.push("✅");
if (creator.featured) badges.push("⭐");
leaderboardData.push({
name: profile.full_name || profile.username || "Anonymous",
value: `${creator.total_projects || 0} projects ${badges.join(" ")}`,
username: profile.username,
});
}
}
}
const embed = new EmbedBuilder()
.setColor(0x7289da)
.setTitle(`${emoji} ${title}`)
.setDescription(
leaderboardData.length > 0
? leaderboardData
.map(
(user, index) =>
`**${index + 1}.** ${user.name} - ${user.value}`
)
.join("\n")
: "No data available yet. Be the first to contribute!"
)
.setFooter({ text: "AeThex Leaderboard | Updated in real-time" })
.setTimestamp();
await interaction.editReply({ embeds: [embed] });
} catch (error) {
console.error("Leaderboard command error:", error);
const embed = new EmbedBuilder()
.setColor(0xff0000)
.setTitle("❌ Error")
.setDescription("Failed to fetch leaderboard. Please try again.");
await interaction.editReply({ embeds: [embed] });
}
},
};