Replaced `.single()` with `.maybeSingle()` in multiple command files to handle cases where no record is found, and added a new /pricing route and navigation links to the UI. Replit-Commit-Author: Agent Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261 Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: e91d020a-35a6-4add-9945-887dd3ecae9f Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/tdDjujk Replit-Helium-Checkpoint-Created: true
87 lines
2.8 KiB
JavaScript
87 lines
2.8 KiB
JavaScript
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
|
|
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('studio')
|
|
.setDescription('View your AeThex Studio profile and projects')
|
|
.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)
|
|
.maybeSingle();
|
|
|
|
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, bio')
|
|
.eq('id', link.user_id)
|
|
.maybeSingle();
|
|
|
|
const { data: projects, count: projectCount } = await supabase
|
|
.from('studio_projects')
|
|
.select('id, title, description, created_at, likes', { count: 'exact' })
|
|
.eq('user_id', link.user_id)
|
|
.order('created_at', { ascending: false })
|
|
.limit(5);
|
|
|
|
const avatarUrl = profile?.avatar_url && profile.avatar_url.startsWith('http')
|
|
? profile.avatar_url
|
|
: target.displayAvatarURL();
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setColor(0x7c3aed)
|
|
.setTitle(`${profile?.username || target.tag}'s Studio`)
|
|
.setThumbnail(avatarUrl)
|
|
.setDescription(profile?.bio || 'No bio set')
|
|
.addFields(
|
|
{ name: 'Total Projects', value: `${projectCount || 0}`, inline: true }
|
|
)
|
|
.setTimestamp();
|
|
|
|
if (projects && projects.length > 0) {
|
|
const projectList = projects.map((p, i) => {
|
|
const likes = p.likes || 0;
|
|
return `**${i + 1}. ${p.title}**\n❤️ ${likes} likes`;
|
|
}).join('\n\n');
|
|
embed.addFields({ name: 'Recent Projects', value: projectList });
|
|
} else {
|
|
embed.addFields({ name: 'Projects', value: 'No projects yet' });
|
|
}
|
|
|
|
embed.addFields({
|
|
name: 'Visit Studio',
|
|
value: '[aethex.studio](https://aethex.studio)'
|
|
});
|
|
|
|
await interaction.editReply({ embeds: [embed] });
|
|
|
|
} catch (error) {
|
|
console.error('Studio error:', error);
|
|
await interaction.editReply({ content: 'Failed to fetch studio data.' });
|
|
}
|
|
},
|
|
};
|