diff --git a/server/package.json b/server/package.json index 1a79b938..cf75363b 100644 --- a/server/package.json +++ b/server/package.json @@ -28,7 +28,7 @@ "body-parser": "^1.19.0", "chalk": "^4.1.0", "cors": "^2.8.5", - "discord.js": "^14.11.0", + "discord.js": "^14.12.0-dev.1688904265-df40dcd.0", "dotenv": "^8.2.0", "express": "^4.17.1", "libsodium-wrappers": "^0.7.10", diff --git a/server/src/action-utils/action-permissions.js b/server/src/action-utils/action-permissions.js index ee872362..e765d191 100644 --- a/server/src/action-utils/action-permissions.js +++ b/server/src/action-utils/action-permissions.js @@ -75,7 +75,7 @@ async function isEventStaffOrHasRole(user, event, role, websiteRoles) { return false; } -async function canUpdateUserDetails(user) { +function canUpdateUserDetails(user) { // TODO: Better / specific permission? return (user.airtable?.website_settings ?? []).includes("Full broadcast permissions"); } diff --git a/server/src/actions/update-player-discord-id.js b/server/src/actions/update-player-discord-id.js index eb82cdfc..9af150da 100644 --- a/server/src/actions/update-player-discord-id.js +++ b/server/src/actions/update-player-discord-id.js @@ -1,4 +1,7 @@ -import { canUpdateUserDetails } from "../action-utils/action-permissions"; +const { canUpdateUserDetails } = require("../action-utils/action-permissions"); +const { + User +} = require("discord.js"); const Cache = require("../cache"); module.exports = { @@ -6,12 +9,11 @@ module.exports = { requiredParams: ["discordData"], auth: ["user"], /*** - * @param {object} discordData + * @param {User} discordData * @param {UserData} user * @returns {Promise} */ async handler({ discordData }, { user }) { - // TODO: Check auth level of current user if (!canUpdateUserDetails(user)) { throw { errorMessage: "You don't have permission update user details", @@ -19,11 +21,27 @@ module.exports = { }; } - // TODO: Get airtable user based on discordData - let players = (await Promise.all((await Cache.get("Players")).ids.map(id => (Cache.get(id.slice(3)))))); - let searchValues = [`${discordData.username}`, `${discordData.username}#${discordData.discriminator ?? "0000"}`]; + let players = await Promise.all((await Cache.get("Players")).ids.map(id => (Cache.get(id.slice(3))))); + + if (await Cache.auth.getPlayer(discordData.id)) { + throw { + errorMessage: "This user is already linked to a SLMN.GG profile", + errorCode: 400 + }; + } + + const isNewUsername = discordData.discriminator === "0"; + + let searchValues = [discordData.username, discordData.globalName, !isNewUsername && `${discordData.username}#${discordData.discriminator}`] + .filter(Boolean) + .map((value) => value.toLocaleLowerCase()); + let potentials = players.filter((player) => { - return (!player.discord_id) && searchValues.includes(player.discord_tag); + if (player.discord_id) return false; + + const discordSimple = player.discord_tag?.split("#")[0].toLocaleLowerCase(); + + return searchValues.includes(discordSimple) || searchValues.includes(player.discord_tag?.toLocaleLowerCase()) || searchValues.includes(player.name?.toLocaleLowerCase()); }); if (potentials.length === 0) { @@ -33,18 +51,17 @@ module.exports = { }; } else if (potentials.length > 1) { throw { - errorMessage: "Found more than 1 SLMN.GG player baesd on discord details", + errorMessage: "Found more than 1 SLMN.GG player based on discord details", errorCode: 500 }; } const targetUser = potentials[0]; - // TODO: Update record with discord ID - console.log("[profile]", user.airtable.name, user.airtable.id, "is setting discord id for", targetUser.name, targetUser.id, "to", discordData.id); let response = await this.helpers.updateRecord("Players", targetUser, { - "Discord Id": discordData.id + "Discord ID": discordData.id, + "Discord Tag": discordData.username }); if (response?.error) { diff --git a/server/src/discord/commands/admin/set-user-id.js b/server/src/discord/commands/admin/set-user-id.js index f6c9a665..44206914 100644 --- a/server/src/discord/commands/admin/set-user-id.js +++ b/server/src/discord/commands/admin/set-user-id.js @@ -1,7 +1,7 @@ const { ContextMenuCommandBuilder, userMention, - ContextMenuCommandType + ApplicationCommandType } = require("discord.js"); const Cache = require("../../../cache.js"); @@ -11,7 +11,7 @@ module.exports = { data: new ContextMenuCommandBuilder() .setName("Associate with SLMN.GG player") .setDMPermission(false) - .setType(ContextMenuCommandType.User), + .setType(ApplicationCommandType.User), async execute(interaction) { const ephemeral = true; @@ -20,24 +20,24 @@ module.exports = { const { token } = await Cache.auth.startRawDiscordAuth(interaction.user); if (!token) { - return interaction.editReply({ ephemeral, content: "Auth failed: no user player data found" }); + return interaction.followUp({ ephemeral, content: "Action failed: no user player data found" }); } const internalManager = getInternalManager(); if (!internalManager) { - return interaction.editReply("No action handlers can process your request."); + return interaction.followUp("No action handlers can process your request."); } await internalManager.runAction("update-player-discord-id", { discordData: interaction.targetUser }, token) .then(async slmnggUser => { - await interaction.editReply({ ephemeral, content: `Linked discord user ${userMention(interaction.targetUser)} to SLMN.GG user ${slmnggUser}` }); + await interaction.followUp({ ephemeral, content: `Linked discord user ${userMention(interaction.targetUser.id)} to SLMN.GG user ${slmnggUser}` }); }) .catch(({ errorCode, errorMessage }) => { console.error({ errorCode, errorMessage }); - interaction.editReply({ + interaction.followUp({ ephemeral, content: `Action failed: ${errorMessage}` }); }); diff --git a/server/src/discord/slash-commands.js b/server/src/discord/slash-commands.js index 6f9e26b2..c22e6d6c 100644 --- a/server/src/discord/slash-commands.js +++ b/server/src/discord/slash-commands.js @@ -26,8 +26,6 @@ for (const folder of commandFolders) { } client.on(Events.InteractionCreate, async (interaction) => { - if (!interaction.isChatInputCommand()) return; - const command = interaction.client.commands.get(interaction.commandName); if (!command) { diff --git a/server/yarn.lock b/server/yarn.lock index 96685308..567e9a18 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -210,7 +210,7 @@ fast-deep-equal "^3.1.3" lodash "^4.17.21" -"@sapphire/snowflake@^3.4.2": +"@sapphire/snowflake@^3.4.2", "@sapphire/snowflake@^3.5.1": version "3.5.1" resolved "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz" integrity sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA== @@ -977,10 +977,15 @@ discord-api-types@^0.37.37, discord-api-types@^0.37.41: resolved "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.45.tgz" integrity sha512-r9m/g+YQfo7XWMrl645jvMlYoWF8lvns/ch4NCxsz/FbingrECu97LFSD2zKOvgHaSc90BHP8wgshaMcA2/c6Q== -discord.js@^14.11.0: - version "14.11.0" - resolved "https://registry.npmjs.org/discord.js/-/discord.js-14.11.0.tgz" - integrity sha512-CkueWYFQ28U38YPR8HgsBR/QT35oPpMbEsTNM30Fs8loBIhnA4s70AwQEoy6JvLcpWWJO7GY0y2BUzZmuBMepQ== +discord-api-types@^0.37.45: + version "0.37.47" + resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.37.47.tgz#d622d5f5629a71ca2cd534442ae2800844e1888d" + integrity sha512-rNif8IAv6duS2z47BMXq/V9kkrLfkAoiwpFY3sLxxbyKprk065zqf3HLTg4bEoxRSmi+Lhc7yqGDrG8C3j8GFA== + +discord.js@14.12.0-dev.1688904265-df40dcd.0: + version "14.12.0-dev.1688904265-df40dcd.0" + resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.12.0-dev.1688904265-df40dcd.0.tgz#94c7100827ac1672af5d3a041b70331d90497c1e" + integrity sha512-4TomFy6bRIvU7uUAO/cFqhSY3LtiQkSJPYQHKkO+5eZQJZhXQl2fTNu807V5xJpzpElno7oEl+4SEoPItIAVvg== dependencies: "@discordjs/builders" "^1.6.3" "@discordjs/collection" "^1.5.1" @@ -988,13 +993,13 @@ discord.js@^14.11.0: "@discordjs/rest" "^1.7.1" "@discordjs/util" "^0.3.1" "@discordjs/ws" "^0.8.3" - "@sapphire/snowflake" "^3.4.2" + "@sapphire/snowflake" "^3.5.1" "@types/ws" "^8.5.4" - discord-api-types "^0.37.41" + discord-api-types "^0.37.45" fast-deep-equal "^3.1.3" lodash.snakecase "^4.1.1" - tslib "^2.5.0" - undici "^5.22.0" + tslib "^2.5.2" + undici "^5.22.1" ws "^8.13.0" doctrine@^3.0.0: @@ -3094,6 +3099,11 @@ tslib@^2.5.0: resolved "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz" integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== +tslib@^2.5.2: + version "2.6.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" + integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" @@ -3150,7 +3160,7 @@ undefsafe@^2.0.3: dependencies: debug "^2.2.0" -undici@^5.22.0: +undici@^5.22.0, undici@^5.22.1: version "5.22.1" resolved "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz" integrity sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==