public interface tweaks and such
This commit is contained in:
@@ -25,43 +25,6 @@ import type { ReacordInstance } from "./instance"
|
||||
import type { ReacordConfig } from "./reacord"
|
||||
import { Reacord } from "./reacord"
|
||||
|
||||
/**
|
||||
* Options for the channel message.
|
||||
*
|
||||
* @see https://reacord.mapleleaf.dev/guides/sending-messages
|
||||
*/
|
||||
export interface LegacyCreateChannelMessageOptions
|
||||
extends CreateChannelMessageOptions {
|
||||
/**
|
||||
* Send message as a reply. Requires the use of message event instead of
|
||||
* channel id provided as argument.
|
||||
*
|
||||
* @deprecated Use reacord.createMessageReply()
|
||||
*/
|
||||
reply?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the channel message.
|
||||
*
|
||||
* @see https://reacord.mapleleaf.dev/guides/sending-messages
|
||||
*/
|
||||
export interface CreateChannelMessageOptions {}
|
||||
|
||||
/**
|
||||
* Options for the message reply method.
|
||||
*
|
||||
* @see https://reacord.mapleleaf.dev/guides/sending-messages
|
||||
*/
|
||||
export interface CreateMessageReplyOptions {}
|
||||
|
||||
/**
|
||||
* Custom options for the interaction reply method.
|
||||
*
|
||||
* @see https://reacord.mapleleaf.dev/guides/sending-messages
|
||||
*/
|
||||
export type CreateInteractionReplyOptions = ReplyInfo
|
||||
|
||||
/**
|
||||
* The Reacord adapter for Discord.js.
|
||||
*
|
||||
@@ -86,45 +49,31 @@ export class ReacordDiscordJs extends Reacord {
|
||||
/**
|
||||
* Sends a message to a channel.
|
||||
*
|
||||
* @param target - Discord channel object.
|
||||
* @param [options] - Options for the channel message
|
||||
* @param target Discord channel object.
|
||||
* @param [options] Options for the channel message
|
||||
* @see https://reacord.mapleleaf.dev/guides/sending-messages
|
||||
* @see {@link Discord.MessageCreateOptions}
|
||||
*/
|
||||
public createChannelMessage(
|
||||
target: Discord.Channel,
|
||||
options: CreateChannelMessageOptions = {},
|
||||
target: Discord.ChannelResolvable,
|
||||
options: Discord.MessageCreateOptions = {},
|
||||
): ReacordInstance {
|
||||
return this.createInstance(
|
||||
this.createChannelMessageRenderer(target, options),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Replies to a message by sending a message.
|
||||
*
|
||||
* @param message - Discord message event object.
|
||||
* @param [options] - Options for the message reply method.
|
||||
* @see https://reacord.mapleleaf.dev/guides/sending-messages
|
||||
*/
|
||||
public createMessageReply(
|
||||
message: Discord.Message,
|
||||
options: CreateMessageReplyOptions = {},
|
||||
): ReacordInstance {
|
||||
return this.createInstance(
|
||||
this.createMessageReplyRenderer(message, options),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Replies to a command interaction by sending a message.
|
||||
*
|
||||
* @param interaction - Discord command interaction object.
|
||||
* @param [options] - Custom options for the interaction reply method.
|
||||
* @param interaction Discord command interaction object.
|
||||
* @param [options] Custom options for the interaction reply method.
|
||||
* @see https://reacord.mapleleaf.dev/guides/sending-messages
|
||||
* @see {@link Discord.InteractionReplyOptions}
|
||||
*/
|
||||
public createInteractionReply(
|
||||
interaction: Discord.CommandInteraction,
|
||||
options: CreateInteractionReplyOptions = {},
|
||||
options: Discord.InteractionReplyOptions = {},
|
||||
): ReacordInstance {
|
||||
return this.createInstance(
|
||||
this.createInteractionReplyRenderer(interaction, options),
|
||||
@@ -132,19 +81,17 @@ export class ReacordDiscordJs extends Reacord {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to a channel. Alternatively replies to message event.
|
||||
* Sends a message to a channel.
|
||||
*
|
||||
* @deprecated Use reacord.createChannelMessage() or
|
||||
* reacord.createMessageReply() instead.
|
||||
* @deprecated Use reacord.createChannelMessage() instead.
|
||||
* @see https://reacord.mapleleaf.dev/guides/sending-messages
|
||||
*/
|
||||
public send(
|
||||
event: string | Discord.Message,
|
||||
channel: Discord.ChannelResolvable,
|
||||
initialContent?: React.ReactNode,
|
||||
options: LegacyCreateChannelMessageOptions = {},
|
||||
): ReacordInstance {
|
||||
return this.createInstance(
|
||||
this.createMessageReplyRenderer(event, options),
|
||||
this.createChannelMessageRenderer(channel, {}),
|
||||
initialContent,
|
||||
)
|
||||
}
|
||||
@@ -158,10 +105,9 @@ export class ReacordDiscordJs extends Reacord {
|
||||
public reply(
|
||||
interaction: Discord.CommandInteraction,
|
||||
initialContent?: React.ReactNode,
|
||||
options: CreateInteractionReplyOptions = {},
|
||||
): ReacordInstance {
|
||||
return this.createInstance(
|
||||
this.createInteractionReplyRenderer(interaction, options),
|
||||
this.createInteractionReplyRenderer(interaction, {}),
|
||||
initialContent,
|
||||
)
|
||||
}
|
||||
@@ -169,18 +115,16 @@ export class ReacordDiscordJs extends Reacord {
|
||||
/**
|
||||
* Sends an ephemeral message as a reply to a command interaction.
|
||||
*
|
||||
* @deprecated Use reacord.createInteractionReply(interaction, content, {
|
||||
* ephemeral: true })
|
||||
* @deprecated Use reacord.createInteractionReply(interaction, { ephemeral:
|
||||
* true })
|
||||
* @see https://reacord.mapleleaf.dev/guides/sending-messages
|
||||
*/
|
||||
public ephemeralReply(
|
||||
interaction: Discord.CommandInteraction,
|
||||
initialContent?: React.ReactNode,
|
||||
options?: Omit<CreateInteractionReplyOptions, "ephemeral">,
|
||||
): ReacordInstance {
|
||||
return this.createInstance(
|
||||
this.createInteractionReplyRenderer(interaction, {
|
||||
...options,
|
||||
ephemeral: true,
|
||||
}),
|
||||
initialContent,
|
||||
@@ -188,49 +132,32 @@ export class ReacordDiscordJs extends Reacord {
|
||||
}
|
||||
|
||||
private createChannelMessageRenderer(
|
||||
channel: Discord.Channel,
|
||||
_opts?: CreateMessageReplyOptions,
|
||||
channelResolvable: Discord.ChannelResolvable,
|
||||
messageCreateOptions?: Discord.MessageCreateOptions,
|
||||
) {
|
||||
return new ChannelMessageRenderer({
|
||||
send: async (options) => {
|
||||
if (!channel.isTextBased()) {
|
||||
raise(`Channel ${channel.id} is not a text channel`)
|
||||
send: async (messageOptions) => {
|
||||
let channel = this.client.channels.resolve(channelResolvable)
|
||||
if (!channel && typeof channelResolvable === "string") {
|
||||
channel = await this.client.channels.fetch(channelResolvable)
|
||||
}
|
||||
|
||||
const message = await channel.send(getDiscordMessageOptions(options))
|
||||
return createReacordMessage(message)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
private createMessageReplyRenderer(
|
||||
event: string | Discord.Message,
|
||||
opts: CreateChannelMessageOptions | LegacyCreateChannelMessageOptions,
|
||||
) {
|
||||
return new ChannelMessageRenderer({
|
||||
send: async (options) => {
|
||||
// Backwards compatible channelId api
|
||||
// `event` is treated as MessageEvent depending on its type
|
||||
const channel =
|
||||
typeof event === "string"
|
||||
? this.client.channels.cache.get(event) ??
|
||||
(await this.client.channels.fetch(event)) ??
|
||||
raise(`Channel ${event} not found`)
|
||||
: event.channel
|
||||
if (!channel) {
|
||||
const id =
|
||||
typeof channelResolvable === "string"
|
||||
? channelResolvable
|
||||
: channelResolvable.id
|
||||
raise(`Channel ${id} not found`)
|
||||
}
|
||||
|
||||
if (!channel.isTextBased()) {
|
||||
raise(`Channel ${channel.id} is not a text channel`)
|
||||
raise(`Channel ${channel.id} must be a text channel`)
|
||||
}
|
||||
|
||||
if ("reply" in opts && opts.reply) {
|
||||
if (typeof event === "string") {
|
||||
raise("Cannot send reply with channel ID provided")
|
||||
}
|
||||
|
||||
const message = await event.reply(getDiscordMessageOptions(options))
|
||||
return createReacordMessage(message)
|
||||
}
|
||||
const message = await channel.send(getDiscordMessageOptions(options))
|
||||
const message = await channel.send({
|
||||
...getDiscordMessageOptions(messageOptions),
|
||||
...messageCreateOptions,
|
||||
})
|
||||
return createReacordMessage(message)
|
||||
},
|
||||
})
|
||||
@@ -240,23 +167,22 @@ export class ReacordDiscordJs extends Reacord {
|
||||
interaction:
|
||||
| Discord.CommandInteraction
|
||||
| Discord.MessageComponentInteraction,
|
||||
opts: CreateInteractionReplyOptions,
|
||||
interactionReplyOptions: Discord.InteractionReplyOptions,
|
||||
) {
|
||||
return new InteractionReplyRenderer({
|
||||
type: "command",
|
||||
id: interaction.id,
|
||||
reply: async (options) => {
|
||||
interactionId: interaction.id,
|
||||
reply: async (messageOptions) => {
|
||||
const message = await interaction.reply({
|
||||
...getDiscordMessageOptions(options),
|
||||
...opts,
|
||||
...getDiscordMessageOptions(messageOptions),
|
||||
...interactionReplyOptions,
|
||||
fetchReply: true,
|
||||
})
|
||||
return createReacordMessage(message)
|
||||
},
|
||||
followUp: async (options) => {
|
||||
followUp: async (messageOptions) => {
|
||||
const message = await interaction.followUp({
|
||||
...getDiscordMessageOptions(options),
|
||||
...opts,
|
||||
...getDiscordMessageOptions(messageOptions),
|
||||
...interactionReplyOptions,
|
||||
fetchReply: true,
|
||||
})
|
||||
return createReacordMessage(message)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Interaction } from "../interaction"
|
||||
import type { Message, MessageOptions } from "../message"
|
||||
import { Renderer } from "./renderer"
|
||||
|
||||
@@ -6,17 +5,23 @@ import { Renderer } from "./renderer"
|
||||
// so we know whether to call reply() or followUp()
|
||||
const repliedInteractionIds = new Set<string>()
|
||||
|
||||
export type InteractionReplyRendererImplementation = {
|
||||
interactionId: string
|
||||
reply: (options: MessageOptions) => Promise<Message>
|
||||
followUp: (options: MessageOptions) => Promise<Message>
|
||||
}
|
||||
|
||||
export class InteractionReplyRenderer extends Renderer {
|
||||
constructor(private interaction: Interaction) {
|
||||
constructor(private implementation: InteractionReplyRendererImplementation) {
|
||||
super()
|
||||
}
|
||||
|
||||
protected createMessage(options: MessageOptions): Promise<Message> {
|
||||
if (repliedInteractionIds.has(this.interaction.id)) {
|
||||
return this.interaction.followUp(options)
|
||||
if (repliedInteractionIds.has(this.implementation.interactionId)) {
|
||||
return this.implementation.followUp(options)
|
||||
}
|
||||
|
||||
repliedInteractionIds.add(this.interaction.id)
|
||||
return this.interaction.reply(options)
|
||||
repliedInteractionIds.add(this.implementation.interactionId)
|
||||
return this.implementation.reply(options)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ slug: getting-started
|
||||
|
||||
# Getting Started
|
||||
|
||||
These guides assume some familiarity with JavaScript, [React](https://reactjs.org), [Discord.js](https://discord.js.org) and the [Discord API](https://discord.dev). Keep these pages as reference if you need it.
|
||||
These guides assume some familiarity with [JavaScript](https://developer.mozilla.org/en-US/docs/Web/javascript), [React](https://reactjs.org), [Discord.js](https://discord.js.org) and the [Discord API](https://discord.dev). Keep these pages as reference if you need it.
|
||||
|
||||
## Setup from template
|
||||
|
||||
@@ -47,6 +47,13 @@ await client.login(process.env.BOT_TOKEN)
|
||||
To use JSX in your code, run it with [tsx](https://npm.im/tsx):
|
||||
|
||||
```bash
|
||||
npm install tsx
|
||||
tsx main.tsx
|
||||
npm install -D tsx
|
||||
npx tsx main.tsx
|
||||
```
|
||||
|
||||
For production, I recommend compiling it with [tsup](https://npm.im/tsup):
|
||||
|
||||
```bash
|
||||
npm install -D tsup
|
||||
npx tsup src/main.tsx --target node20
|
||||
```
|
||||
|
||||
@@ -36,7 +36,6 @@ function Uptime() {
|
||||
|
||||
client.on("ready", () => {
|
||||
const instance = reacord.createChannelMessage(channel)
|
||||
|
||||
instance.render(<Uptime />)
|
||||
})
|
||||
```
|
||||
@@ -48,26 +47,25 @@ const Hello = ({ subject }) => <>Hello, {subject}!</>
|
||||
|
||||
client.on("ready", () => {
|
||||
const instance = reacord.createChannelMessage(channel)
|
||||
|
||||
instance.render(<Hello subject="World" />)
|
||||
instance.render(<Hello subject="Moon" />)
|
||||
})
|
||||
```
|
||||
|
||||
## Replying to Messages
|
||||
|
||||
Instead of sending messages to a channel, you may want to reply to a specific message instead. To do this, create an instance using `.createMessageReply()` instead:
|
||||
You can specify various options for the message:
|
||||
|
||||
```jsx
|
||||
const Hello = ({ username }) => <>Hello, {username}!</>
|
||||
|
||||
client.on("messageCreate", (message) => {
|
||||
reacord
|
||||
.createMessageReply(message)
|
||||
.render(<Hello username={message.author.displayName} />)
|
||||
const instance = reacord.createChannelMessage(channel, {
|
||||
tts: true,
|
||||
reply: {
|
||||
messageReference: someMessage.id,
|
||||
},
|
||||
flags: [MessageFlags.SuppressNotifications],
|
||||
})
|
||||
```
|
||||
|
||||
See the [Discord.js docs](https://discord.js.org/#/docs/discord.js/main/typedef/MessageCreateOptions) for all of the available options.
|
||||
|
||||
## Cleaning Up Instances
|
||||
|
||||
If you no longer want to use the instance, you can clean it up in a few ways:
|
||||
@@ -91,7 +89,7 @@ const reacord = new ReacordDiscordJs(client, {
|
||||
This section also applies to other kinds of application commands, such as context menu commands.
|
||||
</aside>
|
||||
|
||||
To reply to a command interaction, use the `.createInteractionReply()` function. This function returns an instance that works the same way as the one from `.createChannelMessage()` and `.createMessageReply()`. Here's an example:
|
||||
To reply to a command interaction, use the `.createInteractionReply()` function. This function returns an instance that works the same way as the one from `.createChannelMessage()`. Here's an example:
|
||||
|
||||
```jsx
|
||||
import { Client } from "discord.js"
|
||||
@@ -163,11 +161,7 @@ handleCommands(client, [
|
||||
])
|
||||
```
|
||||
|
||||
## Interaction Options
|
||||
|
||||
Just like `.createChannelMessage()` and `.createMessageReply()`, interaction replies provide a way to specify certain `interaction.reply()` options.
|
||||
|
||||
### Ephemeral Command Replies
|
||||
## Ephemeral Command Replies
|
||||
|
||||
Ephemeral replies are replies that only appear for one user. To create them, use the `.createInteractionReply()` function and provide `ephemeral` option.
|
||||
|
||||
@@ -185,7 +179,7 @@ handleCommands(client, [
|
||||
])
|
||||
```
|
||||
|
||||
### Text-to-Speech Command Replies
|
||||
## Text-to-Speech Command Replies
|
||||
|
||||
Additionally interaction replies may have `tts` option to turn on text-to-speech ability for the reply. To create such reply, use `.createInteractionReply()` function and provide `tts` option.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user