feat: Add Modals and Text Inputs (#7023)

Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Ryan Munro <monbrey@gmail.com>
Co-authored-by: Vitor <milagre.vitor@gmail.com>
This commit is contained in:
Suneet Tipirneni
2022-03-04 02:53:41 -05:00
committed by GitHub
parent 53defb82e3
commit ed92015634
31 changed files with 1075 additions and 115 deletions

View File

@@ -0,0 +1,16 @@
import { z } from 'zod';
import { ActionRow, type ModalActionRowComponent } from '../..';
import { customIdValidator } from '../../components/Assertions';
export const titleValidator = z.string().min(1).max(45);
export const componentsValidator = z.array(z.instanceof(ActionRow)).min(1);
export function validateRequiredParameters(
customId?: string,
title?: string,
components?: ActionRow<ModalActionRowComponent>[],
) {
customIdValidator.parse(customId);
titleValidator.parse(title);
componentsValidator.parse(components);
}

View File

@@ -0,0 +1,19 @@
import type { APIModalInteractionResponseCallbackData } from 'discord-api-types/v9';
import { customIdValidator } from '../../components/Assertions';
import { titleValidator, validateRequiredParameters } from './Assertions';
import { UnsafeModal } from './UnsafeModal';
export class Modal extends UnsafeModal {
public override setCustomId(customId: string): this {
return super.setCustomId(customIdValidator.parse(customId));
}
public override setTitle(title: string) {
return super.setTitle(titleValidator.parse(title));
}
public override toJSON(): APIModalInteractionResponseCallbackData {
validateRequiredParameters(this.data.custom_id, this.data.title, this.components);
return super.toJSON();
}
}

View File

@@ -0,0 +1,80 @@
import type {
APIActionRowComponent,
APIModalActionRowComponent,
APIModalInteractionResponseCallbackData,
} from 'discord-api-types/v9';
import { ActionRow, createComponent, JSONEncodable, ModalActionRowComponent } from '../../index';
export class UnsafeModal implements JSONEncodable<APIModalInteractionResponseCallbackData> {
protected readonly data: Partial<Omit<APIModalInteractionResponseCallbackData, 'components'>>;
public readonly components: ActionRow<ModalActionRowComponent>[] = [];
public constructor({ components, ...data }: Partial<APIModalInteractionResponseCallbackData> = {}) {
this.data = { ...data };
this.components = (components?.map((c) => createComponent(c)) ?? []) as ActionRow<ModalActionRowComponent>[];
}
/**
* The custom id of this modal
*/
public get customId() {
return this.data.custom_id;
}
/**
* The title of this modal
*/
public get title() {
return this.data.title;
}
/**
* Sets the title of the modal
* @param title The title of the modal
*/
public setTitle(title: string) {
this.data.title = title;
return this;
}
/**
* Sets the custom id of the modal
* @param customId The custom id of this modal
*/
public setCustomId(customId: string) {
this.data.custom_id = customId;
return this;
}
/**
* Adds components to this modal
* @param components The components to add to this modal
*/
public addComponents(
...components: (ActionRow<ModalActionRowComponent> | APIActionRowComponent<APIModalActionRowComponent>)[]
) {
this.components.push(
...components.map((component) =>
component instanceof ActionRow ? component : new ActionRow<ModalActionRowComponent>(component),
),
);
return this;
}
/**
* Sets the components in this modal
* @param components The components to set this modal to
*/
public setComponents(...components: ActionRow<ModalActionRowComponent>[]) {
this.components.splice(0, this.components.length, ...components);
return this;
}
public toJSON(): APIModalInteractionResponseCallbackData {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return {
...this.data,
components: this.components.map((component) => component.toJSON()),
} as APIModalInteractionResponseCallbackData;
}
}