diff --git a/packages/bot/src/helpers.ts b/packages/bot/src/helpers.ts index 26c407c6b..3d08a59cc 100644 --- a/packages/bot/src/helpers.ts +++ b/packages/bot/src/helpers.ts @@ -5,6 +5,7 @@ import type { AtLeastOne, BeginGuildPrune, BigString, + BulkUpdateLobbyMember, Camelize, CreateApplicationCommand, CreateApplicationEmoji, @@ -619,6 +620,9 @@ export function createBotHelpers { return bot.transformers.lobbyMember(bot, snakelize(await bot.rest.addMemberToLobby(lobbyId, userId, options))); }, + bulkUpdateLobbyMembers: async (lobbyId, options) => { + return (await bot.rest.bulkUpdateLobbyMembers(lobbyId, options)).map((res) => bot.transformers.lobbyMember(bot, snakelize(res))); + }, linkChannelToLobby: async (lobbyId, bearerToken, options) => { return bot.transformers.lobby(bot, snakelize(await bot.rest.linkChannelToLobby(lobbyId, bearerToken, options))); }, @@ -1169,6 +1173,7 @@ export type BotHelpers Promise>; modifyLobby: (lobbyId: BigString, options: ModifyLobby) => Promise>; addMemberToLobby: (lobbyId: BigString, userId: BigString, options: AddLobbyMember) => Promise>; + bulkUpdateLobbyMembers: (lobbyId: BigString, options: BulkUpdateLobbyMember[]) => Promise[]>; linkChannelToLobby: (lobbyId: BigString, bearerToken: string, options: LinkChannelToLobby) => Promise>; unlinkChannelToLobby: (lobbyId: BigString, bearerToken: string) => Promise>; updateLobbyMessageModerationMetadata: (lobbyId: BigString, messageId: BigString, options: Record) => Promise; diff --git a/packages/rest/src/manager.ts b/packages/rest/src/manager.ts index 9b7bce5a4..588f4a76d 100644 --- a/packages/rest/src/manager.ts +++ b/packages/rest/src/manager.ts @@ -1904,6 +1904,12 @@ export function createRestManager(options: CreateRestManagerOptions): RestManage }); }, + async bulkUpdateLobbyMembers(lobbyId, options) { + return await rest.post(rest.routes.lobby.membersBulk(lobbyId), { + body: options, + }); + }, + async removeMemberFromLobby(lobbyId, userId) { return await rest.delete(rest.routes.lobby.member(lobbyId, userId)); }, diff --git a/packages/rest/src/routes.ts b/packages/rest/src/routes.ts index 825b5059d..328108a25 100644 --- a/packages/rest/src/routes.ts +++ b/packages/rest/src/routes.ts @@ -695,6 +695,10 @@ export function createRoutes(disableURIEncode: boolean = false): RestRoutes { return `/lobbies/${encode(lobbyId)}/channel-linking`; }, + membersBulk: (lobbyId) => { + return `/lobbies/${encode(lobbyId)}/members/bulk`; + }, + moderationMetadata: (lobbyId, messageId) => { return `/lobbies/${encode(lobbyId)}/messages/${encode(messageId)}/moderation-metadata`; }, diff --git a/packages/rest/src/types.ts b/packages/rest/src/types.ts index 9edd719f6..10b84cc30 100644 --- a/packages/rest/src/types.ts +++ b/packages/rest/src/types.ts @@ -5,6 +5,7 @@ import type { AtLeastOne, BeginGuildPrune, BigString, + BulkUpdateLobbyMember, Camelize, ChannelTypes, CreateApplicationCommand, @@ -3257,6 +3258,22 @@ export interface RestManager { * @returns The lobby member object */ addMemberToLobby: (lobbyId: BigString, userId: BigString, options: AddLobbyMember) => Promise>; + /** + * Adds, updates, or removes up to 25 members from the specified lobby in a single request. + * + * @param lobbyId - The ID of the lobby to add, update, or remove members from + * @param options - The options to add, update, or remove members from the lobby + * @returns Returns an array of lobby member objects for the upserted members. Removed members are not included in the response. + * + * @remarks + * Members with `remove_member: false` (the default) are upserted — added if not present, or updated with the provided metadata and flags if already a member. Members with `remove_member: true` are removed. + * + * Users unknown to Discord will return a 404 UNKNOWN_USER error. + * Users that fail permission checks or who have already reached the maximum number of lobbies per application (and are not already a member of this lobby) are silently dropped from the upsert set. + * + * @see {@link https://docs.discord.com/developers/resources/lobby#bulk-update-lobby-members} + */ + bulkUpdateLobbyMembers: (lobbyId: BigString, options: BulkUpdateLobbyMember[]) => Promise[]>; /** * Removes the provided user from the specified lobby. It is safe to call this even if the user is no longer a member of the lobby, but will fail if the lobby does not exist. * diff --git a/packages/rest/src/typings/routes.ts b/packages/rest/src/typings/routes.ts index 5a38990e7..a76af3c95 100644 --- a/packages/rest/src/typings/routes.ts +++ b/packages/rest/src/typings/routes.ts @@ -316,6 +316,8 @@ export interface RestRoutes { leave: (lobbyId: BigString) => string; /** Route to link a lobby */ link: (lobbyId: BigString) => string; + /** Route to bulk update members of a lobby */ + membersBulk: (lobbyId: BigString) => string; /** Route to set the lobby moderation metadata */ moderationMetadata: (lobbyId: BigString, messageId: BigString) => string; }; diff --git a/packages/types/src/discordeno/lobby.ts b/packages/types/src/discordeno/lobby.ts index 293ca67f6..38dbd348d 100644 --- a/packages/types/src/discordeno/lobby.ts +++ b/packages/types/src/discordeno/lobby.ts @@ -45,6 +45,26 @@ export interface AddLobbyMember { flags?: number; } +/** https://docs.discord.com/developers/resources/lobby#bulk-update-lobby-members */ +export interface BulkUpdateLobbyMember { + /** Discord user id of the user to add, update, or remove */ + id: BigString; + /** Optional dictionary of string key/value pairs. The max total length is 1000. */ + metadata?: Record | null; + /** + * Lobby member flags combined as a bitfield + * + * @see {@link DiscordLobbyMemberFlags} + */ + flags?: number; + /** + * if `true`, the user is removed from the lobby instead of upserted. + * + * @default false + */ + removeMember?: boolean; +} + /** https://docs.discord.com/developers/resources/lobby#link-channel-to-lobby */ export interface LinkChannelToLobby { /** The id of the channel to link to the lobby. If not provided, will unlink any currently linked channels from the lobby. */