move stuff around until it feels right
This commit is contained in:
9
library/adapter/adapter.ts
Normal file
9
library/adapter/adapter.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { CommandInteraction, ComponentInteraction } from "../interaction"
|
||||
|
||||
export type Adapter<InteractionInit> = {
|
||||
addComponentInteractionListener(
|
||||
listener: (interaction: ComponentInteraction) => void,
|
||||
): void
|
||||
|
||||
createCommandInteraction(interactionInfo: InteractionInit): CommandInteraction
|
||||
}
|
||||
103
library/adapter/discord-js-adapter.ts
Normal file
103
library/adapter/discord-js-adapter.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import type * as Discord from "discord.js"
|
||||
import { raise } from "../../helpers/raise"
|
||||
import { toUpper } from "../../helpers/to-upper"
|
||||
import type { CommandInteraction, ComponentInteraction } from "../interaction"
|
||||
import type { Message, MessageOptions } from "../message"
|
||||
import type { Adapter } from "./adapter"
|
||||
|
||||
export class DiscordJsAdapter implements Adapter<Discord.CommandInteraction> {
|
||||
constructor(private client: Discord.Client) {}
|
||||
|
||||
addComponentInteractionListener(
|
||||
listener: (interaction: ComponentInteraction) => void,
|
||||
) {
|
||||
this.client.on("interactionCreate", (interaction) => {
|
||||
if (interaction.isButton()) {
|
||||
listener(createReacordComponentInteraction(interaction))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
createCommandInteraction(
|
||||
interaction: Discord.CommandInteraction,
|
||||
): CommandInteraction {
|
||||
return {
|
||||
type: "command",
|
||||
id: interaction.id,
|
||||
channelId: interaction.channelId,
|
||||
reply: async (options) => {
|
||||
const message = await interaction.reply({
|
||||
...getDiscordMessageOptions(options),
|
||||
fetchReply: true,
|
||||
})
|
||||
return createReacordMessage(message as Discord.Message)
|
||||
},
|
||||
followUp: async (options) => {
|
||||
const message = await interaction.followUp({
|
||||
...getDiscordMessageOptions(options),
|
||||
fetchReply: true,
|
||||
})
|
||||
return createReacordMessage(message as Discord.Message)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createReacordComponentInteraction(
|
||||
interaction: Discord.MessageComponentInteraction,
|
||||
): ComponentInteraction {
|
||||
return {
|
||||
type: "button",
|
||||
id: interaction.id,
|
||||
channelId: interaction.channelId,
|
||||
customId: interaction.customId,
|
||||
update: async (options) => {
|
||||
await interaction.update(getDiscordMessageOptions(options))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function createReacordMessage(message: Discord.Message): Message {
|
||||
return {
|
||||
edit: async (options) => {
|
||||
await message.edit(getDiscordMessageOptions(options))
|
||||
},
|
||||
disableComponents: async () => {
|
||||
for (const actionRow of message.components) {
|
||||
for (const component of actionRow.components) {
|
||||
component.setDisabled(true)
|
||||
}
|
||||
}
|
||||
|
||||
await message.edit({
|
||||
components: message.components,
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function getDiscordMessageOptions(
|
||||
options: MessageOptions,
|
||||
): Discord.MessageOptions {
|
||||
return {
|
||||
content: options.content,
|
||||
embeds: options.embeds,
|
||||
components: options.actionRows.map((row) => ({
|
||||
type: "ACTION_ROW",
|
||||
components: row.map((component) => {
|
||||
if (component.type === "button") {
|
||||
return {
|
||||
type: "BUTTON",
|
||||
customId: component.customId,
|
||||
label: component.label ?? "",
|
||||
style: toUpper(component.style ?? "secondary"),
|
||||
disabled: component.disabled,
|
||||
emoji: component.emoji,
|
||||
}
|
||||
}
|
||||
raise(`Unsupported component type: ${component.type}`)
|
||||
}),
|
||||
})),
|
||||
}
|
||||
}
|
||||
107
library/adapter/test-adapter.ts
Normal file
107
library/adapter/test-adapter.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { nanoid } from "nanoid"
|
||||
import { raise } from "../../helpers/raise"
|
||||
import type {
|
||||
ButtonInteraction,
|
||||
CommandInteraction,
|
||||
ComponentInteraction,
|
||||
} from "../interaction"
|
||||
import type { Message, MessageButtonOptions, MessageOptions } from "../message"
|
||||
import type { Adapter } from "./adapter"
|
||||
|
||||
export class TestAdapter implements Adapter<{}> {
|
||||
readonly messages: TestMessage[] = []
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
private componentInteractionListener: (
|
||||
interaction: ComponentInteraction,
|
||||
) => void = () => {}
|
||||
|
||||
addComponentInteractionListener(
|
||||
listener: (interaction: ComponentInteraction) => void,
|
||||
): void {
|
||||
this.componentInteractionListener = listener
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
createCommandInteraction(
|
||||
interaction: CommandInteraction,
|
||||
): CommandInteraction {
|
||||
return interaction
|
||||
}
|
||||
|
||||
findButtonByLabel(label: string) {
|
||||
for (const message of this.messages) {
|
||||
for (const component of message.options.actionRows.flat()) {
|
||||
if (component.type === "button" && component.label === label) {
|
||||
return this.createButtonActions(component, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
raise(`Couldn't find button with label "${label}"`)
|
||||
}
|
||||
|
||||
private createButtonActions(
|
||||
button: MessageButtonOptions,
|
||||
message: TestMessage,
|
||||
) {
|
||||
return {
|
||||
click: () => {
|
||||
this.componentInteractionListener(
|
||||
new TestButtonInteraction(button.customId, message),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class TestMessage implements Message {
|
||||
constructor(public options: MessageOptions) {}
|
||||
|
||||
async edit(options: MessageOptions): Promise<void> {
|
||||
this.options = options
|
||||
}
|
||||
|
||||
async disableComponents(): Promise<void> {
|
||||
for (const row of this.options.actionRows) {
|
||||
for (const action of row) {
|
||||
if (action.type === "button") {
|
||||
action.disabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class TestCommandInteraction implements CommandInteraction {
|
||||
readonly type = "command"
|
||||
readonly id = "test-command-interaction"
|
||||
readonly channelId = "test-channel-id"
|
||||
|
||||
constructor(private adapter: TestAdapter) {}
|
||||
|
||||
private createMesssage(messageOptions: MessageOptions): Message {
|
||||
const message = new TestMessage(messageOptions)
|
||||
this.adapter.messages.push(message)
|
||||
return message
|
||||
}
|
||||
|
||||
reply(messageOptions: MessageOptions): Promise<Message> {
|
||||
return Promise.resolve(this.createMesssage(messageOptions))
|
||||
}
|
||||
|
||||
followUp(messageOptions: MessageOptions): Promise<Message> {
|
||||
return Promise.resolve(this.createMesssage(messageOptions))
|
||||
}
|
||||
}
|
||||
|
||||
export class TestButtonInteraction implements ButtonInteraction {
|
||||
readonly type = "button"
|
||||
readonly id = nanoid()
|
||||
readonly channelId = "test-channel-id"
|
||||
|
||||
constructor(readonly customId: string, readonly message: TestMessage) {}
|
||||
|
||||
async update(options: MessageOptions): Promise<void> {
|
||||
this.message.options = options
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user