Add manager Join/Leave/Alternate commands
additionally update deleteConfirmed such that the group up manager name syntax matches name syntax elsewhere in the bot
This commit is contained in:
parent
9051792ff3
commit
00a98db405
|
@ -8,6 +8,9 @@ const actions = [
|
|||
'cmd-report',
|
||||
'cmd-setup',
|
||||
'cmd-gameSel',
|
||||
'cmd-join',
|
||||
'cmd-leave',
|
||||
'cmd-alternate',
|
||||
'btn-gameSel',
|
||||
'btn-customAct',
|
||||
'btn-createEvt',
|
||||
|
|
|
@ -10,7 +10,7 @@ export const confirmedCustomId = 'confirmedCustomId';
|
|||
export const confirmStr = 'yes';
|
||||
|
||||
const execute = async (bot: Bot, interaction: Interaction) => {
|
||||
if (interaction?.data?.customId && interaction?.data?.components?.length && interaction.channelId && interaction.guildId && interaction.member) {
|
||||
if (interaction?.data?.customId && interaction?.data?.components?.length && interaction.channelId && interaction.guildId && interaction.member && interaction.member.user) {
|
||||
// Light Telemetry
|
||||
dbClient.execute(queries.callIncCnt('btn-confirmDelEvent')).catch((e) => utils.commonLoggers.dbError('deleteConfirmed.ts@incCnt', 'call sproc INC_CNT on', e));
|
||||
|
||||
|
@ -33,6 +33,7 @@ const execute = async (bot: Bot, interaction: Interaction) => {
|
|||
if (tempDataMap.get(confirmedCustomId)?.toLowerCase() === confirmStr) {
|
||||
const eventMessage = await bot.helpers.getMessage(evtChannelId, evtMessageId).catch((e: Error) => utils.commonLoggers.messageGetError('deleteConfirmed.ts', 'get eventMessage', e));
|
||||
const userId = interaction.member.id;
|
||||
const userName = interaction.member.user.username;
|
||||
// Delete event
|
||||
bot.helpers.deleteMessage(evtChannelId, evtMessageId, 'User deleted event').then(() => {
|
||||
dbClient.execute(queries.deleteEvent, [evtChannelId, evtMessageId]).catch((e) => utils.commonLoggers.dbError('deleteConfirmed.ts@deleteEvent', 'delete event from', e));
|
||||
|
@ -56,7 +57,7 @@ const execute = async (bot: Bot, interaction: Interaction) => {
|
|||
embeds: [{
|
||||
color: infoColor2,
|
||||
title: `Event deleted by a ${config.name} Manager`,
|
||||
description: `The following event was deleted by <@${userId}>.`,
|
||||
description: `The following event was deleted by ${userName} - <@${userId}>.`,
|
||||
timestamp: new Date().getTime(),
|
||||
}, eventEmbed],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('deleteConfirmed.ts', 'send log message', e));
|
||||
|
|
|
@ -18,7 +18,7 @@ const execute = async (bot: Bot, interaction: Interaction) => {
|
|||
const memberRequesting = getLfgMembers(interaction.message.embeds[0].fields[0].value || '')[0];
|
||||
const approved = interaction.data.customId.includes(approveStr);
|
||||
const responseStr = interaction.data.customId.split(idSeparator)[1] || '';
|
||||
const capResponseStr = `${responseStr.charAt(0).toUpperCase()}${responseStr.slice(1)}`;
|
||||
const capResponseStr = utils.capitalizeFirstChar(responseStr);
|
||||
const eventIds = utils.messageUrlToIds(interaction.message.embeds[0].description.split(')')[0] || '');
|
||||
const eventUrl = utils.idsToMessageUrl(eventIds);
|
||||
const joinRequestMapId = generateMapId(eventIds.messageId, eventIds.channelId, memberRequesting.id);
|
||||
|
|
|
@ -81,7 +81,7 @@ const editEvent = async (
|
|||
memberList: Array<LFGMember>,
|
||||
maxMemberCount: number,
|
||||
alternateList: Array<LFGMember>,
|
||||
loudAcknowledge = false,
|
||||
loudAcknowledge: boolean,
|
||||
) => {
|
||||
if (evtMessageEmbed.fields) {
|
||||
// Update the fields
|
||||
|
@ -122,7 +122,7 @@ ${safelyDismissMsg}`,
|
|||
};
|
||||
|
||||
// Generic no response response
|
||||
const noEdit = async (bot: Bot, interaction: Interaction, loudAcknowledge = false) => {
|
||||
const noEdit = async (bot: Bot, interaction: Interaction, loudAcknowledge: boolean) => {
|
||||
if (loudAcknowledge) {
|
||||
bot.helpers.sendInteractionResponse(interaction.id, interaction.token, {
|
||||
type: InteractionResponseTypes.ChannelMessageWithSource,
|
||||
|
@ -149,7 +149,16 @@ export const getGuildName = async (bot: Bot, guildId: bigint): Promise<string> =
|
|||
(await bot.helpers.getGuild(guildId).catch((e: Error) => utils.commonLoggers.messageGetError('utils.ts', 'get guild', e)) || { name: 'failed to get guild name' }).name;
|
||||
|
||||
// Remove member from the event
|
||||
export const removeMemberFromEvent = async (bot: Bot, interaction: Interaction, evtMessageEmbed: Embed, evtMessageId: bigint, evtChannelId: bigint, userId: bigint, evtGuildId: bigint) => {
|
||||
export const removeMemberFromEvent = async (
|
||||
bot: Bot,
|
||||
interaction: Interaction,
|
||||
evtMessageEmbed: Embed,
|
||||
evtMessageId: bigint,
|
||||
evtChannelId: bigint,
|
||||
userId: bigint,
|
||||
evtGuildId: bigint,
|
||||
loudAcknowledge = false,
|
||||
): Promise<boolean> => {
|
||||
if (evtMessageEmbed.fields) {
|
||||
// Get old counts
|
||||
const [oldMemberCount, maxMemberCount] = getEventMemberCount(evtMessageEmbed.fields[LfgEmbedIndexes.JoinedMembers].name);
|
||||
|
@ -202,13 +211,16 @@ export const removeMemberFromEvent = async (bot: Bot, interaction: Interaction,
|
|||
}
|
||||
|
||||
// Update the event
|
||||
await editEvent(bot, interaction, evtMessageEmbed, evtMessageId, evtChannelId, memberList, maxMemberCount, alternateList);
|
||||
await editEvent(bot, interaction, evtMessageEmbed, evtMessageId, evtChannelId, memberList, maxMemberCount, alternateList, loudAcknowledge);
|
||||
return true;
|
||||
} else {
|
||||
// Send noEdit response because user did not actually leave
|
||||
await noEdit(bot, interaction);
|
||||
await noEdit(bot, interaction, loudAcknowledge);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
await somethingWentWrong(bot, interaction, 'noFieldsInRemoveMember');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -222,7 +234,7 @@ export const alternateMemberToEvent = async (
|
|||
member: LFGMember,
|
||||
userJoinOnFull = false,
|
||||
loudAcknowledge = false,
|
||||
) => {
|
||||
): Promise<boolean> => {
|
||||
if (evtMessageEmbed.fields) {
|
||||
member.joined = userJoinOnFull;
|
||||
// Get current alternates
|
||||
|
@ -241,18 +253,30 @@ export const alternateMemberToEvent = async (
|
|||
// Update the event
|
||||
evtMessageEmbed.fields[LfgEmbedIndexes.AlternateMembers].value = generateAlternateList(alternateList);
|
||||
await editEvent(bot, interaction, evtMessageEmbed, evtMessageId, evtChannelId, memberList, maxMemberCount, alternateList, loudAcknowledge);
|
||||
return true;
|
||||
} else {
|
||||
// Send noEdit response because user was already an alternate and joined status did not change
|
||||
await noEdit(bot, interaction, loudAcknowledge);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// No fields, can't alternate
|
||||
await somethingWentWrong(bot, interaction, 'noFieldsInAlternateMember');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Join member to the event
|
||||
export const joinMemberToEvent = async (bot: Bot, interaction: Interaction, evtMessageEmbed: Embed, evtMessageId: bigint, evtChannelId: bigint, member: LFGMember, evtGuildId: bigint) => {
|
||||
export const joinMemberToEvent = async (
|
||||
bot: Bot,
|
||||
interaction: Interaction,
|
||||
evtMessageEmbed: Embed,
|
||||
evtMessageId: bigint,
|
||||
evtChannelId: bigint,
|
||||
member: LFGMember,
|
||||
evtGuildId: bigint,
|
||||
loudAcknowledge = false,
|
||||
): Promise<boolean> => {
|
||||
if (evtMessageEmbed.fields) {
|
||||
// Get current member list and count
|
||||
const [oldMemberCount, maxMemberCount] = getEventMemberCount(evtMessageEmbed.fields[LfgEmbedIndexes.JoinedMembers].name);
|
||||
|
@ -260,10 +284,11 @@ export const joinMemberToEvent = async (bot: Bot, interaction: Interaction, evtM
|
|||
// Verify user is not already on the joined list
|
||||
if (memberList.find((joinedMember) => joinedMember.id === member.id)) {
|
||||
// Send noEdit response because user was already joined
|
||||
await noEdit(bot, interaction);
|
||||
await noEdit(bot, interaction, loudAcknowledge);
|
||||
return false;
|
||||
} else if (oldMemberCount === maxMemberCount) {
|
||||
// Event full, add member to alternate list
|
||||
await alternateMemberToEvent(bot, interaction, evtMessageEmbed, evtMessageId, evtChannelId, member, true);
|
||||
return await alternateMemberToEvent(bot, interaction, evtMessageEmbed, evtMessageId, evtChannelId, member, true, loudAcknowledge);
|
||||
} else {
|
||||
// Join member to event
|
||||
memberList.push(member);
|
||||
|
@ -272,7 +297,7 @@ export const joinMemberToEvent = async (bot: Bot, interaction: Interaction, evtM
|
|||
const alternateList = removeLfgMember(getLfgMembers(evtMessageEmbed.fields[LfgEmbedIndexes.AlternateMembers].value), member.id);
|
||||
|
||||
// Update the event
|
||||
await editEvent(bot, interaction, evtMessageEmbed, evtMessageId, evtChannelId, memberList, maxMemberCount, alternateList);
|
||||
await editEvent(bot, interaction, evtMessageEmbed, evtMessageId, evtChannelId, memberList, maxMemberCount, alternateList, loudAcknowledge);
|
||||
|
||||
// Check if we need to notify the owner that their event has filled
|
||||
if (memberList.length === maxMemberCount) {
|
||||
|
@ -292,10 +317,12 @@ export const joinMemberToEvent = async (bot: Bot, interaction: Interaction, evtM
|
|||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('utils.ts', 'event filled dm', e));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// No fields, can't join
|
||||
await somethingWentWrong(bot, interaction, 'noFieldsInJoinMember');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -6,9 +6,10 @@ import info from './info.ts';
|
|||
import report from './report.ts';
|
||||
import setup from './setup.ts';
|
||||
import deleteCmd from './delete.ts';
|
||||
import managerJLA from './managerJLA.ts';
|
||||
import { gameSelectionCommand } from '../buttons/event-creation/step1-gameSelection.ts';
|
||||
|
||||
export const commands: Array<Command> = [deleteCmd, info, report, setup, gameSelectionCommand];
|
||||
export const commands: Array<Command> = [deleteCmd, info, report, setup, gameSelectionCommand, managerJLA];
|
||||
|
||||
export const createSlashCommands = async (bot: Bot) => {
|
||||
const globalCommands: MakeRequired<CreateApplicationCommand, 'name'>[] = [];
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
import { ApplicationCommandOptionTypes, ApplicationCommandTypes, Bot, Interaction } from '../../deps.ts';
|
||||
import { alternateMemberToEvent, getGuildName, joinMemberToEvent, removeMemberFromEvent } from '../buttons/live-event/utils.ts';
|
||||
import { generateMemberList } from '../buttons/eventUtils.ts';
|
||||
import { dbClient, generateGuildSettingKey, lfgChannelSettings, queries } from '../db.ts';
|
||||
import { infoColor2, sendDirectMessage, somethingWentWrong, stopThat } from '../commandUtils.ts';
|
||||
import { CommandDetails, LFGMember } from '../types/commandTypes.ts';
|
||||
import config from '../../config.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const eventName = 'event';
|
||||
export const joinName = 'join';
|
||||
export const leaveName = 'leave';
|
||||
export const alternateName = 'alternate';
|
||||
export const eventLinkName = 'event-link';
|
||||
export const userName = 'user';
|
||||
|
||||
// Create command with three nearly identical subcommands
|
||||
const generateOptions = (commandName: string) => ({
|
||||
name: commandName,
|
||||
description: `${config.name} Manager Command: ${utils.capitalizeFirstChar(commandName)}s a user to an event in this channel.`,
|
||||
type: ApplicationCommandOptionTypes.SubCommand,
|
||||
options: [
|
||||
{
|
||||
name: eventLinkName,
|
||||
type: ApplicationCommandOptionTypes.String,
|
||||
description: 'Please copy the message link for the desired event.',
|
||||
required: true,
|
||||
minLength: 31,
|
||||
maxLength: 100,
|
||||
},
|
||||
{
|
||||
name: userName,
|
||||
type: ApplicationCommandOptionTypes.User,
|
||||
description: `The user you wish to ${commandName}.`,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
const details: CommandDetails = {
|
||||
name: eventName,
|
||||
description: `${config.name} Manager Command`,
|
||||
type: ApplicationCommandTypes.ChatInput,
|
||||
options: [generateOptions(joinName), generateOptions(leaveName), generateOptions(alternateName)],
|
||||
};
|
||||
|
||||
const execute = async (bot: Bot, interaction: Interaction) => {
|
||||
if (interaction.data?.options?.[0].options && interaction.channelId && interaction.guildId && interaction.member && interaction.member.user) {
|
||||
// Get action and log to db
|
||||
const actionName = interaction.data.options[0].name;
|
||||
dbClient.execute(queries.callIncCnt(`cmd-${actionName}`)).catch((e) => utils.commonLoggers.dbError('managerJLA.ts', 'call sproc INC_CNT on', e));
|
||||
const lfgChannelSetting = lfgChannelSettings.get(generateGuildSettingKey(interaction.guildId, interaction.channelId)) || {
|
||||
managed: false,
|
||||
managerRoleId: 0n,
|
||||
logChannelId: 0n,
|
||||
};
|
||||
|
||||
// Check if guild is managed and if user is a manager
|
||||
if (lfgChannelSetting.managed && interaction.member.roles.includes(lfgChannelSetting.managerRoleId)) {
|
||||
// User is a manager, parse out our data
|
||||
const tempDataMap: Map<string, string> = new Map();
|
||||
for (const option of interaction.data.options[0].options) {
|
||||
tempDataMap.set(option.name || 'missingCustomId', option.value as string || '');
|
||||
}
|
||||
const eventLink = tempDataMap.get(eventLinkName) || '';
|
||||
const userToAdd = BigInt(tempDataMap.get(userName) || '0');
|
||||
const eventIds = utils.messageUrlToIds(eventLink);
|
||||
|
||||
// Verify fields exist
|
||||
if (!eventLink || !userToAdd || !eventIds.guildId || !eventIds.channelId || !eventIds.messageId) {
|
||||
somethingWentWrong(bot, interaction, 'missingLinkOrUserInManagerJLA');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get event from link
|
||||
const eventMessage = await bot.helpers.getMessage(eventIds.channelId, eventIds.messageId).catch((e: Error) => utils.commonLoggers.messageGetError('managerJLA.ts', 'get eventMessage', e));
|
||||
const userDetails = await bot.helpers.getUser(userToAdd).catch((e: Error) => utils.commonLoggers.messageGetError('managerJLA.ts', 'get userDetails', e));
|
||||
if (eventMessage && userDetails) {
|
||||
// Perform the action
|
||||
const userInfo: LFGMember = {
|
||||
id: userToAdd,
|
||||
name: userDetails.username,
|
||||
};
|
||||
let changeMade = false;
|
||||
switch (actionName) {
|
||||
case joinName:
|
||||
changeMade = await joinMemberToEvent(bot, interaction, eventMessage.embeds[0], eventIds.messageId, eventIds.channelId, userInfo, eventIds.guildId, true);
|
||||
break;
|
||||
case leaveName:
|
||||
changeMade = await removeMemberFromEvent(bot, interaction, eventMessage.embeds[0], eventIds.messageId, eventIds.channelId, userToAdd, eventIds.guildId, true);
|
||||
break;
|
||||
case alternateName:
|
||||
changeMade = await alternateMemberToEvent(bot, interaction, eventMessage.embeds[0], eventIds.messageId, eventIds.channelId, userInfo, false, true);
|
||||
break;
|
||||
default:
|
||||
somethingWentWrong(bot, interaction, 'actionNameWrongManagerJLA');
|
||||
break;
|
||||
}
|
||||
|
||||
if (changeMade) {
|
||||
// userToAdd was had JLA done to them, DM them with details\
|
||||
const guildName = await getGuildName(bot, interaction.guildId);
|
||||
const commonFields = [{
|
||||
name: 'Event Link:',
|
||||
value: `[Click Here](${eventLink}) to view the event.`,
|
||||
inline: true,
|
||||
}, {
|
||||
name: 'Action Performed:',
|
||||
value: utils.capitalizeFirstChar(actionName),
|
||||
inline: true,
|
||||
}];
|
||||
sendDirectMessage(bot, userToAdd, {
|
||||
embeds: [{
|
||||
color: infoColor2,
|
||||
title: `Notice: A ${config.name} Manager has performed an action for you in ${guildName}`,
|
||||
fields: [
|
||||
{
|
||||
name: `${config.name} Manager:`,
|
||||
value: generateMemberList([{
|
||||
id: interaction.member.id,
|
||||
name: interaction.member.user.username,
|
||||
}]),
|
||||
inline: true,
|
||||
},
|
||||
...commonFields,
|
||||
{
|
||||
name: 'Are you unhappy with this action?',
|
||||
value: `Please reach out to the ${config.name} Manager that performed this action, or the moderators/administrators of ${guildName}.`,
|
||||
},
|
||||
],
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('managerJLA.ts', 'send DM fail', e));
|
||||
|
||||
// Log this action
|
||||
bot.helpers.sendMessage(lfgChannelSetting.logChannelId, {
|
||||
embeds: [{
|
||||
color: infoColor2,
|
||||
title: `A ${config.name} Manager has performed an action on behalf of a user.`,
|
||||
description: `The following user had an action by ${interaction.member.user.username} - <@${interaction.member.id}>.`,
|
||||
fields: [...commonFields, {
|
||||
name: 'User:',
|
||||
value: generateMemberList([userInfo]),
|
||||
inline: true,
|
||||
}],
|
||||
timestamp: new Date().getTime(),
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('deleteConfirmed.ts', 'send log message', e));
|
||||
}
|
||||
} else {
|
||||
somethingWentWrong(bot, interaction, 'eventOrUserMissingFromManagerJLA');
|
||||
}
|
||||
} else {
|
||||
// User not a manager
|
||||
stopThat(bot, interaction, `${actionName} users to`);
|
||||
}
|
||||
} else {
|
||||
// All data missing
|
||||
somethingWentWrong(bot, interaction, 'missingDataInManagerJLA');
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
details,
|
||||
execute,
|
||||
};
|
|
@ -19,6 +19,7 @@ import { CommandDetails } from '../types/commandTypes.ts';
|
|||
import utils from '../utils.ts';
|
||||
import { customId as gameSelId } from '../buttons/event-creation/step1-gameSelection.ts';
|
||||
import { alternateEventBtnStr, joinEventBtnStr, leaveEventBtnStr, requestToJoinEventBtnStr } from '../buttons/eventUtils.ts';
|
||||
import { alternateName, eventLinkName, eventName, joinName, leaveName, userName } from './managerJLA.ts';
|
||||
|
||||
const withoutMgrRole = 'without-manager-role';
|
||||
const withMgrRole = 'with-manager-role';
|
||||
|
@ -150,7 +151,7 @@ const execute = async (bot: Bot, interaction: Interaction) => {
|
|||
name: `${config.name} Manager Details:`,
|
||||
value: `${config.name} Managers with the <@&${managerRoleId}> role may edit or delete events in this guild, along with using the following commands to update the activity members:
|
||||
|
||||
\`/join\` \`/leave\` \`/alternate\`
|
||||
\`/${eventName} [${joinName} | ${leaveName} | ${alternateName}] [${eventLinkName}] [${userName}]\`
|
||||
|
||||
The Discord Slash Command system will ensure you provide all the required details.`,
|
||||
});
|
||||
|
|
|
@ -18,6 +18,8 @@ const messageUrlToIds = (url: string): UrlIds => {
|
|||
};
|
||||
};
|
||||
|
||||
const capitalizeFirstChar = (input: string) => `${input.charAt(0).toUpperCase()}${input.slice(1)}`;
|
||||
|
||||
const genericLogger = (level: LT, message: string) => log(level, message);
|
||||
const interactionSendError = (location: string, interaction: Interaction | string, err: Error) =>
|
||||
genericLogger(LT.ERROR, `${location} | Failed to respond to interaction: ${jsonStringifyBig(interaction)} | Error: ${err.name} - ${err.message}`);
|
||||
|
@ -38,6 +40,7 @@ const channelUpdateError = (location: string, message: string, err: Error) => ge
|
|||
const dbError = (location: string, type: string, err: Error) => genericLogger(LT.ERROR, `${location} | Failed to ${type} database | Error: ${err.name} - ${err.message}`);
|
||||
|
||||
export default {
|
||||
capitalizeFirstChar,
|
||||
commonLoggers: {
|
||||
channelUpdateError,
|
||||
dbError,
|
||||
|
|
Loading…
Reference in New Issue