Files
SupportBot/Commands/profile.js
T
2024-11-09 00:37:51 +00:00

260 lines
8.9 KiB
JavaScript

const { EmbedBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ApplicationCommandType, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationCommandOptionType } = require("discord.js");
const fs = require("fs");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Command = require("../Structures/Command.js");
const clockedInUsers = new Set();
function updateClockedInStatus(profileEmbed, clockedIn) {
profileEmbed.data.fields = profileEmbed.data.fields.map(field => {
if (field.name === 'Clocked In Status') {
field.value = clockedIn ? '✅ Clocked In' : '❌ Clocked Out';
}
return field;
});
return profileEmbed;
}
function formatSchedule(schedule) {
if (!schedule || Object.keys(schedule).length === 0) return 'No schedule set';
const days = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
return days
.filter(day => schedule[day])
.map(day => `${day.charAt(0).toUpperCase() + day.slice(1)}: ${schedule[day].start} - ${schedule[day].end}`)
.join('\n');
}
function calculateWeeklyHours(schedule) {
if (!schedule) return 0;
let totalMinutes = 0;
Object.values(schedule).forEach(day => {
if (day && day.start && day.end) {
const [startHour, startMin] = day.start.split(':').map(Number);
const [endHour, endMin] = day.end.split(':').map(Number);
const startMinutes = startHour * 60 + startMin;
const endMinutes = endHour * 60 + endMin;
totalMinutes += endMinutes - startMinutes;
}
});
return Math.round(totalMinutes / 60 * 10) / 10; // Round to 1 decimal place
}
module.exports = new Command({
name: cmdconfig.Profile.Command,
description: cmdconfig.Profile.Description,
type: ApplicationCommandType.ChatInput,
permissions: cmdconfig.Profile.Permission,
options: [
{
name: 'user',
description: 'The user to view the profile of',
type: ApplicationCommandOptionType.User,
required: false
}
],
async run(interaction) {
await interaction.deferReply({ ephemeral: true });
const userOption = interaction.options.getUser('user');
const viewingUser = userOption || interaction.user;
const viewingUserId = viewingUser.id;
const interactionUserId = interaction.user.id;
const user = interaction.guild.members.cache.get(viewingUserId);
const { getRole } = interaction.client;
const Staff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!Staff || !Admin) {
return interaction.editReply({
content: "Some roles seem to be missing!\nPlease check for errors when starting the bot.",
ephemeral: true,
});
}
const isStaff = user.roles.cache.has(Staff.id) || user.roles.cache.has(Admin.id);
const isOwnProfile = interactionUserId === viewingUserId;
const profilePath = `./Data/Profiles/${viewingUserId}.json`;
let profileData;
if (fs.existsSync(profilePath)) {
profileData = JSON.parse(fs.readFileSync(profilePath, "utf8"));
} else {
profileData = {
bio: "",
timezone: "",
clockedIn: false,
schedule: {}
};
fs.writeFileSync(profilePath, JSON.stringify(profileData, null, 2));
}
const { bio, timezone, clockedIn, schedule } = profileData;
const weeklyHours = calculateWeeklyHours(schedule);
let profileEmbed = new EmbedBuilder()
.setTitle(`${viewingUser.username}'s Profile`)
.setColor(supportbot.Embed.Colours.General)
.setThumbnail(viewingUser.displayAvatarURL())
.addFields(
{ name: 'Bio', value: bio || 'No bio set.', inline: false },
{ name: 'Timezone', value: timezone || 'No timezone set.', inline: true }
);
if (isStaff) {
profileEmbed.addFields(
{ name: 'Clocked In Status', value: clockedIn ? '✅ Clocked In' : '❌ Clocked Out', inline: true },
{ name: 'Weekly Hours', value: `${weeklyHours} hours`, inline: true }, // Now inline with Schedule
{ name: 'Schedule', value: formatSchedule(schedule), inline: true }
);
}
const buttonRow = new ActionRowBuilder();
if (isOwnProfile) {
buttonRow.addComponents(
new ButtonBuilder()
.setCustomId('editProfile')
.setLabel('Edit Profile')
.setStyle(ButtonStyle.Secondary)
);
if (isStaff) {
buttonRow.addComponents(
new ButtonBuilder()
.setCustomId('clockInOut')
.setLabel(clockedIn ? 'Clock Out' : 'Clock In')
.setStyle(ButtonStyle.Secondary),
new ButtonBuilder()
.setCustomId('editSchedule')
.setLabel('Edit Schedule')
.setStyle(ButtonStyle.Secondary)
);
}
}
if (isStaff && supportbot.Ticket.ClaimTickets.Enabled) {
buttonRow.addComponents(
new ButtonBuilder()
.setCustomId('viewTicketStats')
.setLabel('View Ticket Stats')
.setStyle(ButtonStyle.Secondary)
);
}
await interaction.editReply({ embeds: [profileEmbed], components: buttonRow.components.length > 0 ? [buttonRow] : [] });
const filter = i => (
['editProfile', 'clockInOut', 'viewTicketStats', 'editSchedule'].includes(i.customId)
&& i.user.id === interactionUserId
);
const collector = interaction.channel.createMessageComponentCollector({ filter, time: 60000 });
collector.on('collect', async i => {
if (i.customId === 'editProfile') {
const modal = new ModalBuilder()
.setCustomId('editProfileModal')
.setTitle('Edit Profile')
.addComponents(
new ActionRowBuilder().addComponents(
new TextInputBuilder()
.setCustomId('bio')
.setLabel('Bio')
.setStyle(TextInputStyle.Paragraph)
.setValue(profileData.bio || '')
.setRequired(false)
),
new ActionRowBuilder().addComponents(
new TextInputBuilder()
.setCustomId('timezone')
.setLabel('Timezone')
.setStyle(TextInputStyle.Short)
.setValue(profileData.timezone || '')
.setRequired(false)
)
);
await i.showModal(modal);
}
if (i.customId === 'clockInOut') {
profileData.clockedIn = !profileData.clockedIn;
fs.writeFileSync(profilePath, JSON.stringify(profileData, null, 2));
if (profileData.clockedIn) {
clockedInUsers.add(viewingUserId);
} else {
clockedInUsers.delete(viewingUserId);
}
profileEmbed = updateClockedInStatus(profileEmbed, profileData.clockedIn);
const updatedRow = new ActionRowBuilder().addComponents(
...buttonRow.components.map(button => {
if (button.data.custom_id === 'clockInOut') {
return new ButtonBuilder()
.setCustomId('clockInOut')
.setLabel(profileData.clockedIn ? 'Clock Out' : 'Clock In')
.setStyle(ButtonStyle.Secondary);
}
return ButtonBuilder.from(button.data);
})
);
await i.update({ embeds: [profileEmbed], components: [updatedRow] });
}
if (i.customId === 'viewTicketStats') {
// Handle ticket stats viewing here
const ticketStatsEmbed = new EmbedBuilder()
.setTitle('Ticket Stats')
.setDescription('Here are your ticket stats...')
.setColor(supportbot.Embed.Colours.General);
await i.update({ embeds: [ticketStatsEmbed], components: [] });
}
if (i.customId === 'editSchedule') {
const modal = new ModalBuilder()
.setCustomId('editScheduleModal')
.setTitle('Edit Schedule');
['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'].forEach(day => {
modal.addComponents(
new ActionRowBuilder().addComponents(
new TextInputBuilder()
.setCustomId(`${day.toLowerCase()}Start`)
.setLabel(`${day} Start Time (HH:mm)`)
.setStyle(TextInputStyle.Short)
.setRequired(false)
.setValue(schedule[day.toLowerCase()]?.start || '')
),
new ActionRowBuilder().addComponents(
new TextInputBuilder()
.setCustomId(`${day.toLowerCase()}End`)
.setLabel(`${day} End Time (HH:mm)`)
.setStyle(TextInputStyle.Short)
.setRequired(false)
.setValue(schedule[day.toLowerCase()]?.end || '')
)
);
});
await i.showModal(modal);
}
});
}
});