205 lines
9.0 KiB
TypeScript
205 lines
9.0 KiB
TypeScript
import BotCommand from "../../libs/BotCommand";
|
|
import BotClient from "../../libs/BotClient";
|
|
import { ChatInputCommandInteraction, MessageFlags, EmbedBuilder, PermissionFlagsBits } from "discord.js";
|
|
import Team from "../../models/Team";
|
|
import User from "../../models/User";
|
|
import Database from "../../libs/Database";
|
|
import PointsManager from "../../libs/PointsManager";
|
|
|
|
export default class TeamManageCommand extends BotCommand {
|
|
constructor() {
|
|
super("team", "Create, edit, or delete teams (Admin only)", "/team");
|
|
|
|
this.data.addSubcommand(subcommand =>
|
|
subcommand.setName("create")
|
|
.setDescription("Create a new team")
|
|
.addStringOption(option =>
|
|
option.setName("name")
|
|
.setDescription("Team name")
|
|
.setRequired(true))
|
|
.addUserOption(option =>
|
|
option.setName("leader")
|
|
.setDescription("Team leader")
|
|
.setRequired(true))
|
|
.addRoleOption(option =>
|
|
option.setName("role")
|
|
.setDescription("Team role to assign to members")
|
|
.setRequired(true))
|
|
.addStringOption(option =>
|
|
option.setName("description")
|
|
.setDescription("Team description")
|
|
.setRequired(false))
|
|
);
|
|
|
|
this.data.addSubcommand(subcommand =>
|
|
subcommand.setName("delete")
|
|
.setDescription("Delete a team")
|
|
.addStringOption(option =>
|
|
option.setName("name")
|
|
.setDescription("Team name")
|
|
.setRequired(true))
|
|
);
|
|
|
|
this.data.addSubcommand(subcommand =>
|
|
subcommand.setName("change-leader")
|
|
.setDescription("Change team leader")
|
|
.addStringOption(option =>
|
|
option.setName("name")
|
|
.setDescription("Team name")
|
|
.setRequired(true))
|
|
.addUserOption(option =>
|
|
option.setName("new-leader")
|
|
.setDescription("New team leader")
|
|
.setRequired(true))
|
|
);
|
|
|
|
this.data.addSubcommand(subcommand =>
|
|
subcommand.setName("list")
|
|
.setDescription("List all teams")
|
|
);
|
|
|
|
this.data.addSubcommand(subcommand =>
|
|
subcommand.setName("change-user-team")
|
|
.setDescription("Change a user's team (only during first week of month)")
|
|
.addUserOption(option =>
|
|
option.setName("user")
|
|
.setDescription("User to move")
|
|
.setRequired(true))
|
|
.addStringOption(option =>
|
|
option.setName("team")
|
|
.setDescription("Team name")
|
|
.setRequired(true))
|
|
);
|
|
|
|
this.data.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild);
|
|
}
|
|
|
|
override async execute(Discord: any, client: BotClient, interaction: ChatInputCommandInteraction): Promise<any> {
|
|
const db = Database.getInstance();
|
|
if (!db.isConnected()) {
|
|
return interaction.reply({ content: "❌ Database not connected. Points system unavailable.", flags: MessageFlags.Ephemeral });
|
|
}
|
|
|
|
const subcommand = interaction.options.getSubcommand();
|
|
|
|
try {
|
|
if (subcommand === "create") {
|
|
const name = interaction.options.getString("name", true);
|
|
const leader = interaction.options.getUser("leader", true);
|
|
const role = interaction.options.getRole("role", true);
|
|
const description = interaction.options.getString("description") || "";
|
|
|
|
const existing = await Team.findOne({ name });
|
|
if (existing) {
|
|
return interaction.reply({ content: `❌ Team **${name}** already exists.`, flags: MessageFlags.Ephemeral });
|
|
}
|
|
|
|
const team = new Team({
|
|
name,
|
|
leaderId: leader.id,
|
|
roleId: role.id,
|
|
description,
|
|
points: 0,
|
|
memberCount: 0
|
|
});
|
|
await team.save();
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setTitle("✅ Team Created")
|
|
.setColor(0x22c55e)
|
|
.addFields(
|
|
{ name: "Team Name", value: name, inline: true },
|
|
{ name: "Leader", value: `<@${leader.id}>`, inline: true },
|
|
{ name: "Role", value: `<@&${role.id}>`, inline: true },
|
|
{ name: "Description", value: description || "None", inline: false }
|
|
)
|
|
.setTimestamp();
|
|
|
|
return interaction.reply({ embeds: [embed] });
|
|
|
|
} else if (subcommand === "delete") {
|
|
const name = interaction.options.getString("name", true);
|
|
const team = await Team.findOne({ name });
|
|
|
|
if (!team) {
|
|
return interaction.reply({ content: `❌ Team **${name}** not found.`, flags: MessageFlags.Ephemeral });
|
|
}
|
|
|
|
// Remove role from all team members
|
|
const teamMembers = await User.find({ teamId: team._id });
|
|
const guild = interaction.guild;
|
|
if (guild) {
|
|
for (const user of teamMembers) {
|
|
try {
|
|
const member = await guild.members.fetch(user.userId);
|
|
if (member && member.roles.cache.has(team.roleId)) {
|
|
await member.roles.remove(team.roleId);
|
|
}
|
|
} catch (err) {
|
|
console.error(`Failed to remove role from ${user.userId}:`, err);
|
|
}
|
|
}
|
|
}
|
|
|
|
await User.updateMany({ teamId: team._id }, { $set: { teamId: null } });
|
|
await Team.deleteOne({ _id: team._id });
|
|
|
|
return interaction.reply({ content: `✅ Team **${name}** has been deleted and roles removed from members.`, flags: MessageFlags.Ephemeral });
|
|
|
|
} else if (subcommand === "change-leader") {
|
|
const name = interaction.options.getString("name", true);
|
|
const newLeader = interaction.options.getUser("new-leader", true);
|
|
const team = await Team.findOne({ name });
|
|
|
|
if (!team) {
|
|
return interaction.reply({ content: `❌ Team **${name}** not found.`, flags: MessageFlags.Ephemeral });
|
|
}
|
|
|
|
team.leaderId = newLeader.id;
|
|
await team.save();
|
|
|
|
return interaction.reply({ content: `✅ Team **${name}** leader changed to <@${newLeader.id}>.`, flags: MessageFlags.Ephemeral });
|
|
|
|
} else if (subcommand === "list") {
|
|
const teams = await Team.find().sort({ points: -1 }).exec();
|
|
|
|
if (teams.length === 0) {
|
|
return interaction.reply({ content: "No teams exist yet.", flags: MessageFlags.Ephemeral });
|
|
}
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setTitle("📋 All Teams")
|
|
.setColor(0x60a5fa)
|
|
.setDescription(teams.map((t: any, i: number) =>
|
|
`**${i + 1}.** ${t.name} - Leader: <@${t.leaderId}> - Role: <@&${t.roleId}>\n` +
|
|
` Members: ${t.memberCount} | Points: ${t.points} (Adjusted: ${t.adjustedPoints})`
|
|
).join("\n\n"))
|
|
.setTimestamp();
|
|
|
|
return interaction.reply({ embeds: [embed] });
|
|
|
|
} else if (subcommand === "change-user-team") {
|
|
const user = interaction.options.getUser("user", true);
|
|
const teamName = interaction.options.getString("team", true);
|
|
const team = await Team.findOne({ name: teamName });
|
|
|
|
if (!team) {
|
|
return interaction.reply({ content: `❌ Team **${teamName}** not found.`, flags: MessageFlags.Ephemeral });
|
|
}
|
|
|
|
const result = await PointsManager.joinTeam(user.id, user.username, team._id.toString(), true, interaction.guild || undefined);
|
|
|
|
if (result.success) {
|
|
return interaction.reply({ content: `✅ <@${user.id}> has been moved to team **${teamName}**.`, flags: MessageFlags.Ephemeral });
|
|
} else {
|
|
return interaction.reply({ content: `❌ ${result.message}`, flags: MessageFlags.Ephemeral });
|
|
}
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error("Error in team-manage command:", error);
|
|
return interaction.reply({ content: "❌ An error occurred.", flags: MessageFlags.Ephemeral });
|
|
}
|
|
}
|
|
}
|