discord-multipurpose-bot/commands/moderation/actionItems.js

154 lines
4.7 KiB
JavaScript

const { SlashCommandBuilder } = require("discord.js");
const ServerSettings = require("../../models/ServerSettings");
module.exports = {
data: new SlashCommandBuilder()
.setName("actionitems")
.setDescription(
"Create multiple action items and assign them to different users"
)
.addStringOption((option) =>
option
.setName("assignments")
.setDescription(
"List of tasks in the format @user: task1, @user2: task2"
)
.setRequired(true)
),
async execute(interaction) {
const serverSettings = await ServerSettings.findOne({
guildId: interaction.guild.id,
});
if (!serverSettings) {
return interaction.reply({
content:
"Server settings are not configured. Please run the setup command.",
ephemeral: true,
});
}
const actionItemsChannelId = serverSettings.actionItemsChannelId;
if (interaction.channelId !== actionItemsChannelId) {
return interaction.reply({
content: `This command can only be used in the <#${actionItemsChannelId}> channel.`,
ephemeral: true,
});
}
const assignmentsInput = interaction.options.getString("assignments");
const assignments = assignmentsInput
.split(",")
.map((assignment) => assignment.trim());
const userTaskMap = new Map();
const completedTasksMap = new Map();
// Parse each assignment to map users and tasks
for (const assignment of assignments) {
const [userMention, task] = assignment
.split(":")
.map((part) => part.trim());
const userId = userMention.match(/<@!?(\d+)>/)?.[1];
if (!userId || !task) {
return interaction.reply({
content: `Invalid format. Please use "@user: task" format. Example: @User1: Task 1, @User2: Task 2`,
ephemeral: true,
});
}
const user = await interaction.guild.members.fetch(userId);
if (!user) {
return interaction.reply({
content: `User ${userMention} not found.`,
ephemeral: true,
});
}
if (!userTaskMap.has(user)) {
userTaskMap.set(user, []);
completedTasksMap.set(user, new Set());
}
userTaskMap.get(user).push(task);
}
// initial message content
let messageContent = `📝 **Action Items:**\n\n`;
userTaskMap.forEach((tasks, user) => {
messageContent += `👤 **Assigned to:** ${user}\n`;
tasks.forEach((task, index) => {
messageContent += `**${index + 1}.** ${task}\n`;
});
messageContent += "\n";
});
const targetChannelId = serverSettings.actionItemsTargetChannelId;
const targetChannel = await interaction.guild.channels.fetch(
targetChannelId
);
if (!targetChannel) {
return interaction.reply({
content: `Unable to find the target channel.`,
ephemeral: true,
});
}
const actionMessage = await targetChannel.send({
content: messageContent + `✅ React with a checkmark to complete tasks!`,
});
await actionMessage.react("✅");
const filter = (reaction, user) => {
return reaction.emoji.name === "✅" && userTaskMap.has(user);
};
const collector = actionMessage.createReactionCollector({
filter,
dispose: true,
});
collector.on("collect", async (reaction, user) => {
const tasks = userTaskMap.get(user);
const completedTasks = completedTasksMap.get(user);
if (completedTasks.size < tasks.length) {
const nextTaskIndex = completedTasks.size;
completedTasks.add(nextTaskIndex);
let updatedMessageContent = `📝 **Action Items:**\n\n`;
userTaskMap.forEach((userTasks, assignedUser) => {
updatedMessageContent += `👤 **Assigned to:** ${assignedUser}\n`;
userTasks.forEach((task, idx) => {
updatedMessageContent += `**${idx + 1}.** ${task}\n`;
});
updatedMessageContent += "\n";
});
await actionMessage.edit({
content:
updatedMessageContent +
`✅ React with a checkmark to complete tasks!`,
});
await interaction.followUp({
content: `${user} has completed task **${tasks[nextTaskIndex]}**!`,
ephemeral: true,
});
}
});
collector.on("end", () => {
console.log("Collector ended");
});
// Confirm action items have been posted to the target channel
await interaction.reply({
content: `Action items have been successfully posted in <#${targetChannelId}>.`,
ephemeral: true,
});
},
};