poixpixel-discord-bot/src/commands/util/user-info.ts
2025-04-13 16:48:18 -04:00

147 lines
5 KiB
TypeScript

import {
SlashCommandBuilder,
EmbedBuilder,
GuildMember,
PermissionsBitField,
} from 'discord.js';
import { getMember } from '@/db/db.js';
import { OptionsCommand } from '@/types/CommandTypes.js';
const command: OptionsCommand = {
data: new SlashCommandBuilder()
.setName('userinfo')
.setDescription('Provides information about the specified user.')
.addUserOption((option) =>
option
.setName('user')
.setDescription('The user whose information you want to retrieve.')
.setRequired(true),
),
execute: async (interaction) => {
const userOption = interaction.options.get(
'user',
) as unknown as GuildMember;
const user = userOption.user;
if (!userOption || !user) {
await interaction.reply('User not found');
return;
}
if (
!interaction.memberPermissions!.has(
PermissionsBitField.Flags.ModerateMembers,
)
) {
await interaction.reply(
'You do not have permission to view member information.',
);
return;
}
const memberData = await getMember(user.id);
const numberOfWarnings = memberData?.moderations.filter(
(moderation) => moderation.action === 'warning',
).length;
const recentWarnings = memberData?.moderations
.filter((moderation) => moderation.action === 'warning')
.sort((a, b) => b.createdAt!.getTime() - a.createdAt!.getTime())
.slice(0, 5);
const numberOfMutes = memberData?.moderations.filter(
(moderation) => moderation.action === 'mute',
).length;
const currentMute = memberData?.moderations
.filter((moderation) => moderation.action === 'mute')
.sort((a, b) => b.createdAt!.getTime() - a.createdAt!.getTime())[0];
const numberOfBans = memberData?.moderations.filter(
(moderation) => moderation.action === 'ban',
).length;
const currentBan = memberData?.moderations
.filter((moderation) => moderation.action === 'ban')
.sort((a, b) => b.createdAt!.getTime() - a.createdAt!.getTime())[0];
const embed = new EmbedBuilder()
.setTitle(`User Information - ${user?.username}`)
.setColor(user.accentColor || '#5865F2')
.setThumbnail(user.displayAvatarURL({ size: 256 }))
.setTimestamp()
.addFields(
{
name: '👤 Basic Information',
value: [
`**Username:** ${user.username}`,
`**Discord ID:** ${user.id}`,
`**Account Created:** ${user.createdAt.toLocaleString()}`,
`**Joined Server:** ${
interaction.guild?.members.cache
.get(user.id)
?.joinedAt?.toLocaleString() || 'Not available'
}`,
`**Currently in Server:** ${memberData?.currentlyInServer ? '✅ Yes' : '❌ No'}`,
].join('\n'),
inline: false,
},
{
name: '🛡️ Moderation History',
value: [
`**Total Warnings:** ${numberOfWarnings || '0'} ${numberOfWarnings ? '⚠️' : ''}`,
`**Total Mutes:** ${numberOfMutes || '0'} ${numberOfMutes ? '🔇' : ''}`,
`**Total Bans:** ${numberOfBans || '0'} ${numberOfBans ? '🔨' : ''}`,
`**Currently Muted:** ${memberData?.currentlyMuted ? '🔇 Yes' : '✅ No'}`,
`**Currently Banned:** ${memberData?.currentlyBanned ? '🚫 Yes' : '✅ No'}`,
].join('\n'),
inline: false,
},
);
if (recentWarnings && recentWarnings.length > 0) {
embed.addFields({
name: '⚠️ Recent Warnings',
value: recentWarnings
.map(
(warning, index) =>
`${index + 1}. \`${warning.createdAt?.toLocaleDateString() || 'Unknown'}\` - ` +
`By <@${warning.moderatorDiscordId}>\n` +
`└ Reason: ${warning.reason || 'No reason provided'}`,
)
.join('\n\n'),
inline: false,
});
}
if (memberData?.currentlyMuted && currentMute) {
embed.addFields({
name: '🔇 Current Mute Details',
value: [
`**Reason:** ${currentMute.reason || 'No reason provided'}`,
`**Duration:** ${currentMute.duration || 'Indefinite'}`,
`**Muted At:** ${currentMute.createdAt?.toLocaleString() || 'Unknown'}`,
`**Muted By:** <@${currentMute.moderatorDiscordId}>`,
].join('\n'),
inline: false,
});
}
if (memberData?.currentlyBanned && currentBan) {
embed.addFields({
name: '📌 Current Ban Details',
value: [
`**Reason:** ${currentBan.reason || 'No reason provided'}`,
`**Duration:** ${currentBan.duration || 'Permanent'}`,
`**Banned At:** ${currentBan.createdAt?.toLocaleString() || 'Unknown'}`,
].join('\n'),
inline: false,
});
}
embed.setFooter({
text: `Requested by ${interaction.user.username}`,
iconURL: interaction.user.displayAvatarURL(),
});
await interaction.reply({ embeds: [embed] });
},
};
export default command;