Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/commands/admin/team/addmember.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js';
import { ConfigService } from '#services/configService.js';
import { TeamService } from '#services/teamService.js';
import logger from '#utils/logger.js';

export const data = new SlashCommandBuilder()
.setName('addmember')
.setDescription('Add a registered member to a team.')
.addStringOption((option) =>
option
.setName('team')
.setDescription('The team to add the member to.')
.setRequired(true)
.setAutocomplete(true)
)
.addUserOption((option) =>
option.setName('member').setDescription('The member to add to the team.').setRequired(true)
);

/**
* @param {ChatInputCommandInteraction} interaction
*/
export async function execute(interaction) {
if (!interaction.member.permissions.has('Administrator')) {
const customRole = await ConfigService.getAdminRole(interaction.guildId);
if (customRole) {
const member = await interaction.guild.members.fetch(interaction.user.id);
if (!member.roles.cache.has(customRole)) {
await interaction.reply('You do not have permission to set the approval channel.');
return;
}
} else {
await interaction.reply('You do not have permission to set the approval channel.');
return;
}
}
const teamId = interaction.options.getString('team');
const member = interaction.options.getUser('member');

// Check if the user is already in the team
const team = await TeamService.getTeamById(teamId);
const isMember = team.members.some((member) => member.user.discordId === member.Id);
if (isMember) {
await interaction.reply('This user is already a member of the team.');
return;
}
// Check if the user is already in another team
if (await TeamService.isUserInTeam(member.Id)) {
await interaction.reply('This user is already in another team.');
return;
}
try {
const team = await TeamService.addMemberToTeam(teamId, member.Id);
await interaction.reply(`Member <@${member.id}> added to team ${team.name} successfully!`);
logger.info(
`Member ${member.username} - ${member.id} added to team ${team.name} ${team.id} successfully!`
);
} catch (error) {
logger.error('Error adding member to team', error);
await interaction.reply('An error occurred while adding the member to the team.');
}
}

/**
* @param {ChatInputCommandInteraction} interaction
*/
export async function autocomplete(interaction) {
const focusedValue = interaction.options.getFocused();
const events = await TeamService.getTeams();
const filtered = events.filter((event) => event.name.startsWith(focusedValue));
const choices = filtered.map((event) => event).slice(0, 25);
await interaction.respond(choices.map((choice) => ({ name: choice.name, value: choice.id })));
}
67 changes: 67 additions & 0 deletions src/commands/admin/team/registerteam.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js';
import { EventService } from '#services/eventService.js';
import { TeamService } from '#services/teamService.js';
import logger from '#utils/logger.js';

export const data = new SlashCommandBuilder()
.setName('register-team')
.setDescription('Register team to the event')
.addStringOption((option) =>
option
.setName('event')
.setDescription('Select the event to register the team to')
.setRequired(true)
.setAutocomplete(true)
)
.addStringOption((option) =>
option
.setName('team')
.setDescription('Select the team to register')
.setRequired(true)
.setAutocomplete(true)
);

/**
* @param {ChatInputCommandInteraction} interaction
*/
export async function execute(interaction) {
const eventId = interaction.options.getString('event');
const teamId = interaction.options.getString('team');
// Register the team to the event
const event = await EventService.getEventById(eventId);
if (!event) {
await interaction.reply('Event not found');
return;
}
const team = await TeamService.getTeamById(teamId);
if (!team) {
await interaction.reply('Team not found');
return;
}
try {
await EventService.registerTeamToEvent(eventId, teamId);
await interaction.reply(`Team ${team.name} registered to event ${event.name}`);
logger.info(`Team ${teamId} registered to event ${eventId}`);
} catch (error) {
logger.error('Error registering team to event', error);
await interaction.reply('An error occurred while registering the team to the event.');
}
}

/**
* @param {ChatInputCommandInteraction} interaction
*/
export async function autocomplete(interaction) {
const focusedOption = interaction.options.getFocused(true);
if (focusedOption.name === 'event') {
const events = await EventService.getEvents();
const filtered = events.filter((event) => event.name.startsWith(focusedOption.value));
const choices = filtered.map((event) => event).slice(0, 25);
await interaction.respond(choices.map((choice) => ({ name: choice.name, value: choice.id })));
} else if (focusedOption.name === 'team') {
const teams = await TeamService.getTeams();
const filtered = teams.filter((team) => team.name.startsWith(focusedOption.value));
const choices = filtered.map((event) => event).slice(0, 25);
await interaction.respond(choices.map((choice) => ({ name: choice.name, value: choice.id })));
}
}
46 changes: 46 additions & 0 deletions src/commands/admin/team/removemember.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js';
import { ConfigService } from '#services/configService.js';
import { TeamService } from '#services/teamService.js';
import logger from '#utils/logger.js';

export const data = new SlashCommandBuilder()
.setName('removemember')
.setDescription('Remove a member from the team.')
.addUserOption((option) =>
option.setName('member').setDescription('The member to remove from the team.').setRequired(true)
);

/**
* @param {ChatInputCommandInteraction} interaction
*/
export async function execute(interaction) {
if (!interaction.member.permissions.has('Administrator')) {
const customRole = await ConfigService.getAdminRole(interaction.guildId);
if (customRole) {
const member = await interaction.guild.members.fetch(interaction.user.id);
if (!member.roles.cache.has(customRole)) {
await interaction.reply('You do not have permission to set the approval channel.');
return;
}
} else {
await interaction.reply('You do not have permission to set the approval channel.');
return;
}
}
const member = interaction.options.getUser('member');

try {
// Check if the user is in a team
if (!(await TeamService.isUserInTeam(member.id))) {
await interaction.reply('This user is not in any team.');
return;
}
// Remove member from all teams
await TeamService.removeMemberFromAllTeams(member.id);
await interaction.reply(`Member <@${member.id}> removed from the team successfully!`);
logger.info(`Member ${member.username} - ${member.id} removed from the team successfully!`);
} catch (error) {
logger.error('Error removing member from team', error);
await interaction.reply('An error occurred while removing the member from the team.');
}
}
53 changes: 53 additions & 0 deletions src/commands/event/eventinfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js';
import { EventService } from '#services/eventService.js';
import logger from '#utils/logger.js';

export const data = new SlashCommandBuilder()
.setName('event-info')
.setDescription('Get Event information')
.addStringOption((option) =>
option
.setName('event')
.setDescription('Select the event to get information about')
.setRequired(true)
.setAutocomplete(true)
);

/**
* @param {ChatInputCommandInteraction} interaction
*/
export async function execute(interaction) {
const eventId = interaction.options.getString('event');
const event = await EventService.getEventById(eventId);
if (!event) {
await interaction.reply('Event not found');
return;
}
const embed = {
title: event.name,
description: event.description,
fields: [
{ name: 'Start Date', value: event.startDate.toString(), inline: true },
{ name: 'End Date', value: event.endDate.toString(), inline: true },
{ name: 'Status', value: event.status, inline: true },
{
name: 'Teams',
value: event.teams.map((team) => team.name).join('\n') || 'None',
inline: false,
},
],
};
await interaction.reply({ embeds: [embed] });
logger.info(`Event info requested: ${event.name}`);
}

/**
* @param {ChatInputCommandInteraction} interaction
*/
export async function autocomplete(interaction) {
const focusedValue = interaction.options.getFocused();
const events = await EventService.getEvents();
const filtered = events.filter((event) => event.name.startsWith(focusedValue));
const choices = filtered.map((event) => event).slice(0, 25);
await interaction.respond(choices.map((choice) => ({ name: choice.name, value: choice.id })));
}
52 changes: 52 additions & 0 deletions src/commands/event/teaminfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js';
import { TeamService } from '#services/teamService.js';
import logger from '#utils/logger.js';

export const data = new SlashCommandBuilder()
.setName('team-info')
.setDescription('Get Team information')
.addStringOption((option) =>
option
.setName('team')
.setDescription('Select the team to get information about')
.setRequired(true)
.setAutocomplete(true)
);

/**
* @param {ChatInputCommandInteraction} interaction
*/
export async function execute(interaction) {
const teamId = interaction.options.getString('team');
const team = await TeamService.getTeamById(teamId);
if (!team) {
await interaction.reply('Team not found');
return;
}
const embed = {
title: team.name,
description: team.description,
fields: [
{ name: 'Leader', value: `<@${team.leader.discordId}>`, inline: true },
{
name: 'Members',
value: team.members.map((member) => `<@${member.user.discordId}>`).join('\n') || 'None',
inline: false,
},
],
color: 0x00ae86,
};
await interaction.reply({ embeds: [embed] });
logger.info(`Team info requested: ${team.name}`);
}

/**
* @param {ChatInputCommandInteraction} interaction
*/
export async function autocomplete(interaction) {
const focusedValue = interaction.options.getFocused();
const events = await TeamService.getTeams();
const filtered = events.filter((event) => event.name.startsWith(focusedValue));
const choices = filtered.map((event) => event).slice(0, 25);
await interaction.respond(choices.map((choice) => ({ name: choice.name, value: choice.id })));
}
49 changes: 49 additions & 0 deletions src/services/eventService.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,31 @@ export class EventService {
}
}

/**
* Get an event by ID
* @param {String} eventId - The ID of the event
* @return {Promise<import('@prisma/client').Event>} The event object
*/
static async getEventById(eventId) {
try {
const event = await prisma.event.findUnique({
where: {
id: eventId,
},
include: {
teams: true,
},
});
if (!event) {
throw new Error(`Event with ID ${eventId} not found`);
}
return event;
} catch (error) {
logger.error(`Error getting event with ID ${eventId}:`, error);
throw error;
}
}

/**
* Update an event by ID
* @param {String} eventId - The ID of the event
Expand Down Expand Up @@ -95,4 +120,28 @@ export class EventService {
throw error;
}
}

/**
* Regsiter team to event
*/
static async registerTeamToEvent(eventId, teamId) {
try {
await prisma.event.update({
where: {
id: eventId,
},
data: {
teams: {
connect: {
id: teamId,
},
},
},
});
} catch (error) {
console.log(error);
logger.error(`Error registering team ${teamId} to event ${eventId}:`, error);
throw error;
}
}
}
Loading