feat(interactions): support with_response query parameter in core (#10512)

* feat(interactions): support with_response query parameter

* fix: address feedback from comments

* chore: remove extraneous documentation

* fix: return type is now undefined

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Ryan Munro
2024-11-18 09:48:30 +11:00
committed by GitHub
parent 28d5c84ddc
commit 40fbd827fa

View File

@@ -1,6 +1,6 @@
/* eslint-disable jsdoc/check-param-names */
import type { RawFile, RequestData, REST } from '@discordjs/rest';
import { makeURLSearchParams, type RawFile, type RequestData, type REST } from '@discordjs/rest';
import {
InteractionResponseType,
Routes,
@@ -10,6 +10,8 @@ import {
type APIModalInteractionResponseCallbackData,
type APIPremiumRequiredInteractionResponse,
type RESTGetAPIWebhookWithTokenMessageResult,
type RESTPostAPIInteractionCallbackQuery,
type RESTPostAPIInteractionCallbackWithResponseResult,
type Snowflake,
} from 'discord-api-types/v10';
import type { WebhooksAPI } from './webhook.js';
@@ -20,6 +22,23 @@ export class InteractionsAPI {
private readonly webhooks: WebhooksAPI,
) {}
/**
* Replies to an interaction and returns an interaction callback object
*
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param body - The callback data for replying
* @param options - The options for replying
*/
public async reply(
interactionId: Snowflake,
interactionToken: string,
body: APIInteractionResponseCallbackData &
RESTPostAPIInteractionCallbackQuery & { files?: RawFile[]; with_response: true },
options?: Pick<RequestData, 'signal'>,
): Promise<RESTPostAPIInteractionCallbackWithResponseResult>;
/**
* Replies to an interaction
*
@@ -32,10 +51,23 @@ export class InteractionsAPI {
public async reply(
interactionId: Snowflake,
interactionToken: string,
{ files, ...data }: APIInteractionResponseCallbackData & { files?: RawFile[] },
body: APIInteractionResponseCallbackData &
RESTPostAPIInteractionCallbackQuery & { files?: RawFile[]; with_response?: false },
options?: Pick<RequestData, 'signal'>,
): Promise<undefined>;
public async reply(
interactionId: Snowflake,
interactionToken: string,
{
files,
with_response,
...data
}: APIInteractionResponseCallbackData & RESTPostAPIInteractionCallbackQuery & { files?: RawFile[] },
{ signal }: Pick<RequestData, 'signal'> = {},
) {
await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
const response = await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
query: makeURLSearchParams({ with_response }),
files,
auth: false,
body: {
@@ -44,24 +76,55 @@ export class InteractionsAPI {
},
signal,
});
return with_response ? response : undefined;
}
/**
* Defers the reply to an interaction and returns an interaction callback object
*
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param body - The callback data for deferring the reply
* @param options - The options for deferring
*/
public async defer(
interactionId: Snowflake,
interactionToken: string,
body: APIInteractionResponseDeferredChannelMessageWithSource['data'] &
RESTPostAPIInteractionCallbackQuery & { with_response: true },
options?: Pick<RequestData, 'signal'>,
): Promise<RESTPostAPIInteractionCallbackWithResponseResult>;
/**
* Defers the reply to an interaction
*
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param data - The data for deferring the reply
* @param body - The callback data for deferring the reply
* @param options - The options for deferring
*/
public async defer(
interactionId: Snowflake,
interactionToken: string,
data?: APIInteractionResponseDeferredChannelMessageWithSource['data'],
body?: APIInteractionResponseDeferredChannelMessageWithSource['data'] &
RESTPostAPIInteractionCallbackQuery & { with_response?: false },
options?: Pick<RequestData, 'signal'>,
): Promise<undefined>;
public async defer(
interactionId: Snowflake,
interactionToken: string,
{
with_response,
...data
}: APIInteractionResponseDeferredChannelMessageWithSource['data'] & RESTPostAPIInteractionCallbackQuery = {},
{ signal }: Pick<RequestData, 'signal'> = {},
) {
await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
const response = await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
query: makeURLSearchParams({ with_response }),
auth: false,
body: {
type: InteractionResponseType.DeferredChannelMessageWithSource,
@@ -69,28 +132,58 @@ export class InteractionsAPI {
},
signal,
});
return with_response ? response : undefined;
}
/**
* Defers an update from a message component interaction and returns an interaction callback object
*
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param body - The callback data for deferring the update
* @param options - The options for deferring
*/
public async deferMessageUpdate(
interactionId: Snowflake,
interactionToken: string,
body: RESTPostAPIInteractionCallbackQuery & { with_response: true },
options?: Pick<RequestData, 'signal'>,
): Promise<undefined>;
/**
* Defers an update from a message component interaction
*
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param body - The callback data for deferring the update
* @param options - The options for deferring
*/
public async deferMessageUpdate(
interactionId: Snowflake,
interactionToken: string,
body?: RESTPostAPIInteractionCallbackQuery & { with_response?: false },
options?: Pick<RequestData, 'signal'>,
): Promise<RESTPostAPIInteractionCallbackWithResponseResult>;
public async deferMessageUpdate(
interactionId: Snowflake,
interactionToken: string,
{ with_response }: RESTPostAPIInteractionCallbackQuery = {},
{ signal }: Pick<RequestData, 'signal'> = {},
) {
await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
const response = await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
query: makeURLSearchParams({ with_response }),
auth: false,
body: {
type: InteractionResponseType.DeferredMessageUpdate,
},
signal,
});
return with_response ? response : undefined;
}
/**
@@ -175,6 +268,23 @@ export class InteractionsAPI {
await this.webhooks.deleteMessage(applicationId, interactionToken, messageId ?? '@original', {}, { signal });
}
/**
* Updates the message the component interaction was triggered on and returns an interaction callback object
*
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param callbackData - The callback data for updating the interaction
* @param options - The options for updating the interaction
*/
public async updateMessage(
interactionId: Snowflake,
interactionToken: string,
callbackData: APIInteractionResponseCallbackData &
RESTPostAPIInteractionCallbackQuery & { files?: RawFile[]; with_response: true },
options: Pick<RequestData, 'signal'>,
): Promise<RESTPostAPIInteractionCallbackWithResponseResult>;
/**
* Updates the message the component interaction was triggered on
*
@@ -187,10 +297,22 @@ export class InteractionsAPI {
public async updateMessage(
interactionId: Snowflake,
interactionToken: string,
{ files, ...data }: APIInteractionResponseCallbackData & { files?: RawFile[] },
callbackData: APIInteractionResponseCallbackData &
RESTPostAPIInteractionCallbackQuery & { files?: RawFile[]; with_response?: false },
options: Pick<RequestData, 'signal'>,
): Promise<undefined>;
public async updateMessage(
interactionId: Snowflake,
interactionToken: string,
{
files,
with_response,
...data
}: APIInteractionResponseCallbackData & RESTPostAPIInteractionCallbackQuery & { files?: RawFile[] },
{ signal }: Pick<RequestData, 'signal'> = {},
) {
await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
const response = await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
files,
auth: false,
body: {
@@ -199,8 +321,27 @@ export class InteractionsAPI {
},
signal,
});
return with_response ? response : undefined;
}
/**
* Sends an autocomplete response to an interaction and returns an interaction callback object
*
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param callbackData - The callback data for the autocomplete response
* @param options - The options for sending the autocomplete response
*/
public async createAutocompleteResponse(
interactionId: Snowflake,
interactionToken: string,
callbackData: APICommandAutocompleteInteractionResponseCallbackData &
RESTPostAPIInteractionCallbackQuery & { with_response: true },
options?: Pick<RequestData, 'signal'>,
): Promise<APICommandAutocompleteInteractionResponseCallbackData>;
/**
* Sends an autocomplete response to an interaction
*
@@ -213,19 +354,49 @@ export class InteractionsAPI {
public async createAutocompleteResponse(
interactionId: Snowflake,
interactionToken: string,
callbackData: APICommandAutocompleteInteractionResponseCallbackData,
callbackData: APICommandAutocompleteInteractionResponseCallbackData &
RESTPostAPIInteractionCallbackQuery & { with_response?: false },
options: Pick<RequestData, 'signal'>,
): Promise<undefined>;
public async createAutocompleteResponse(
interactionId: Snowflake,
interactionToken: string,
{
with_response,
...data
}: APICommandAutocompleteInteractionResponseCallbackData & RESTPostAPIInteractionCallbackQuery,
{ signal }: Pick<RequestData, 'signal'> = {},
) {
await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
const response = await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
auth: false,
body: {
type: InteractionResponseType.ApplicationCommandAutocompleteResult,
data: callbackData,
data,
},
signal,
});
return with_response ? response : undefined;
}
/**
* Sends a modal response to an interaction and returns an interaction callback object
*
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param callbackData - The modal callback data to send
* @param options - The options for sending the modal
*/
public async createModal(
interactionId: Snowflake,
interactionToken: string,
callbackData: APIModalInteractionResponseCallbackData &
RESTPostAPIInteractionCallbackQuery & { with_response: true },
options?: Pick<RequestData, 'signal'>,
): Promise<RESTPostAPIInteractionCallbackWithResponseResult>;
/**
* Sends a modal response to an interaction
*
@@ -238,17 +409,27 @@ export class InteractionsAPI {
public async createModal(
interactionId: Snowflake,
interactionToken: string,
callbackData: APIModalInteractionResponseCallbackData,
callbackData: APIModalInteractionResponseCallbackData &
RESTPostAPIInteractionCallbackQuery & { with_response?: false },
options?: Pick<RequestData, 'signal'>,
): Promise<undefined>;
public async createModal(
interactionId: Snowflake,
interactionToken: string,
{ with_response, ...data }: APIModalInteractionResponseCallbackData & RESTPostAPIInteractionCallbackQuery,
{ signal }: Pick<RequestData, 'signal'> = {},
) {
await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
const response = await this.rest.post(Routes.interactionCallback(interactionId, interactionToken), {
auth: false,
body: {
type: InteractionResponseType.Modal,
data: callbackData,
data,
},
signal,
});
return with_response ? response : undefined;
}
/**