diff --git a/src/commands/name-sync.ts b/src/commands/name-sync.ts index d40b0d3..af71710 100644 --- a/src/commands/name-sync.ts +++ b/src/commands/name-sync.ts @@ -1,6 +1,6 @@ import { ApplicationIntegrationType, ChatInputCommandInteraction, Client, InteractionContextType, MessageFlags, PermissionFlagsBits, SlashCommandBuilder } from 'discord.js'; import { Database } from '../shared/Database'; -import { getE621User } from '../utils'; +import { getE621User, syncName } from '../utils'; import { config } from '../config'; import { E621User } from '../types'; @@ -19,24 +19,9 @@ export default { ), handler: async function (client: Client, interaction: ChatInputCommandInteraction) { await interaction.deferReply({ flags: [MessageFlags.Ephemeral] }); - const id = interaction.options.getInteger('id'); - const availableIds = await Database.getE621Ids(interaction.user.id); - - let e621User: E621User | null; - - if (!id || !availableIds.includes(id)) { - e621User = await getE621User(availableIds[0]); - } else { - e621User = await getE621User(id); - } - - if (!e621User) { - return interaction.editReply("Couldn't figure out what your name was. Please contact an administrator."); - } - - const guild = await client.guilds.fetch(config.DISCORD_GUILD_ID!); + const guild = await interaction.client.guilds.fetch(config.DISCORD_GUILD_ID!); if (!guild) { return interaction.editReply('An error has occurred. Please try again later.'); @@ -48,11 +33,6 @@ export default { return interaction.editReply('An error has occurred. Please try again later.'); } - if (member.roles.highest.comparePositionTo(guild.members.me.roles.highest) > 0) { - return interaction.editReply('I am unable to set your nickname as your role is higher than mine.'); - } - - await member.setNickname(e621User.name); - interaction.editReply(`Nickname set to: ${e621User.name}`); + await syncName(interaction, member, id); } }; \ No newline at end of file diff --git a/src/context-menus/sync-name.ts b/src/context-menus/sync-name.ts new file mode 100644 index 0000000..34cb68f --- /dev/null +++ b/src/context-menus/sync-name.ts @@ -0,0 +1,55 @@ +import { ApplicationIntegrationType, Client, InteractionContextType, PermissionFlagsBits, ContextMenuCommandBuilder, ApplicationCommandType, UserContextMenuCommandInteraction, GuildBasedChannel, MessageFlags, ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle } from 'discord.js'; +import { channelIsInStaffCategory, deferInteraction, getRecordMessageFromDiscordId, handleWhoIsInteraction, syncName } from '../utils'; +import { Database } from '../shared/Database'; +import { config } from '../config'; + +export default { + name: 'Sync Name', + data: new ContextMenuCommandBuilder() + .setName('Sync Name') + .setIntegrationTypes(ApplicationIntegrationType.GuildInstall) + .setContexts(InteractionContextType.Guild) + .setDefaultMemberPermissions(PermissionFlagsBits.ManageNicknames) + .setType(ApplicationCommandType.User), + handler: async function (client: Client, interaction: UserContextMenuCommandInteraction) { + const availableIds = await Database.getE621Ids(interaction.user.id); + + const idToUse = interaction.targetUser.id; + + const member = await interaction.guild?.members.fetch(idToUse); + + if (!member) { + return interaction.reply('An error has occurred. Please try again later.'); + } + + if (availableIds.length > 1) { + const modal = new ModalBuilder() + .setCustomId(`sync-name-modal_${idToUse}`) + .setTitle(`Syncing ${member ? member.displayName : idToUse}'s name`); + + const input = new TextInputBuilder() + .setCustomId('id') + .setLabel('User has multiple linked accounts. Provide ID') + .setStyle(TextInputStyle.Short) + .setRequired(false); + + modal.addComponents(new ActionRowBuilder().addComponents(input)); + + return await interaction.showModal(modal); + } + + await deferInteraction(interaction); + + const guild = await interaction.client.guilds.fetch(config.DISCORD_GUILD_ID!); + + if (!guild) { + return interaction.editReply('An error has occurred. Please try again later.'); + } + + if (!guild.members.me) { + return interaction.editReply('An error has occurred. Please try again later.'); + } + + await syncName(interaction, member, null); + } +}; \ No newline at end of file diff --git a/src/modals/sync-name-modal.ts b/src/modals/sync-name-modal.ts new file mode 100644 index 0000000..93e4760 --- /dev/null +++ b/src/modals/sync-name-modal.ts @@ -0,0 +1,36 @@ +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, Client, GuildTextBasedChannel, MessageFlags, ModalSubmitInteraction, TextChannel, ThreadAutoArchiveDuration } from 'discord.js'; +import { ticketCooldownMap } from '../shared/ticket-cooldown'; +import { Database } from '../shared/Database'; +import { deferInteraction, logCustomEvent, syncName } from '../utils'; +import { config } from '../config'; + +export default { + name: 'sync-name-modal', + handler: async function (client: Client, interaction: ModalSubmitInteraction, id: string) { + await deferInteraction(interaction); + + const e621Id = Number(interaction.fields.getTextInputValue('id') ?? 0); + + console.log(e621Id); + + if (isNaN(e621Id)) return await interaction.editReply('Provided id is not a number'); + + const member = await interaction.guild?.members.fetch(id); + + if (!member) { + return interaction.editReply('An error has occurred. Please try again later.'); + } + + const guild = await interaction.client.guilds.fetch(config.DISCORD_GUILD_ID!); + + if (!guild) { + return interaction.editReply('An error has occurred. Please try again later.'); + } + + if (!guild.members.me) { + return interaction.editReply('An error has occurred. Please try again later.'); + } + + await syncName(interaction, member, e621Id); + } +}; \ No newline at end of file diff --git a/src/utils/index.ts b/src/utils/index.ts index f28126a..a884159 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -11,6 +11,7 @@ export * from './file-utils'; export * from './interaction-utils'; export * from './message-utils'; export * from './ms-to-human'; +export * from './name-sync'; export * from './note-utils'; export * from './record-utils'; export * from './refresh-commands'; diff --git a/src/utils/interaction-utils.ts b/src/utils/interaction-utils.ts index 2c3a47e..594c57a 100644 --- a/src/utils/interaction-utils.ts +++ b/src/utils/interaction-utils.ts @@ -1,7 +1,7 @@ -import { ChatInputCommandInteraction, ContextMenuCommandInteraction, GuildBasedChannel, MessageFlags } from 'discord.js'; +import { ChatInputCommandInteraction, ContextMenuCommandInteraction, GuildBasedChannel, MessageFlags, ModalSubmitInteraction } from 'discord.js'; import { channelIsInStaffCategory } from './channel-utils'; -export async function deferInteraction(interaction: ChatInputCommandInteraction | ContextMenuCommandInteraction) { +export async function deferInteraction(interaction: ChatInputCommandInteraction | ContextMenuCommandInteraction | ModalSubmitInteraction) { const isStaffChannel = await channelIsInStaffCategory(interaction.channel as GuildBasedChannel); if (isStaffChannel) await interaction.deferReply(); diff --git a/src/utils/name-sync.ts b/src/utils/name-sync.ts new file mode 100644 index 0000000..9763a9a --- /dev/null +++ b/src/utils/name-sync.ts @@ -0,0 +1,28 @@ +import { E621User } from '../types'; +import { getE621User } from './e621-utils'; +import { Database } from '../shared/Database'; +import { config } from '../config'; +import { ChatInputCommandInteraction, GuildMember, ModalSubmitInteraction, UserContextMenuCommandInteraction } from 'discord.js'; + +export async function syncName(interaction: ChatInputCommandInteraction | UserContextMenuCommandInteraction | ModalSubmitInteraction, member: GuildMember, id: number | null) { + if (member.roles.highest.comparePositionTo(member.guild.members.me!.roles.highest) > 0) { + return interaction.editReply('I am unable to set your nickname as your role is higher than mine.'); + } + + const availableIds = await Database.getE621Ids(interaction.user.id); + + let e621User: E621User | null; + + if (!id || !availableIds.includes(id)) { + e621User = await getE621User(availableIds[0]); + } else { + e621User = await getE621User(id); + } + + if (!e621User) { + return interaction.editReply("Couldn't figure out what your name was. Please contact an administrator."); + } + + await member.setNickname(e621User.name); + interaction.editReply(`Nickname set to: ${e621User.name}`); +} \ No newline at end of file