Skip to content

Commit ec7ded8

Browse files
committed
feat: add mentionable and attachment to command option type
1 parent 245723b commit ec7ded8

File tree

3 files changed

+90
-94
lines changed

3 files changed

+90
-94
lines changed

src/register.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ClientEvents, Events } from 'discord.js'
22
import consola from 'consola'
33
import { colors } from 'consola/utils'
4-
import { toOption, resolveOption } from './utils'
4+
import { resolveOption } from './utils'
55
import { ctx } from './harmonix'
66
import type { Harmonix, ParsedInputs, ParsedOptions } from './types'
77

@@ -36,11 +36,7 @@ export const registerCommands = (harmonix: Harmonix) => {
3636
Promise<ParsedOptions>
3737
>(async (acc, opt) => {
3838
const resolvedAcc = await acc
39-
const resolvedOption = await resolveOption(
40-
interaction,
41-
toOption(opt.type),
42-
String(opt.value)
43-
)
39+
const resolvedOption = resolveOption(interaction, opt.type, opt.name)
4440

4541
return {
4642
...resolvedAcc,

src/types/commands.ts

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,24 @@ import type {
44
PermissionsString,
55
User,
66
GuildBasedChannel,
7-
Role
7+
Role,
8+
APIRole,
9+
APIInteractionDataResolvedChannel,
10+
GuildMember,
11+
APIInteractionDataResolvedGuildMember,
12+
Attachment
813
} from 'discord.js'
914

10-
export type OptionType =
15+
type OptionType =
1116
| 'String'
1217
| 'Integer'
1318
| 'Boolean'
1419
| 'User'
1520
| 'Channel'
1621
| 'Role'
1722
| 'Number'
23+
| 'Mentionable'
24+
| 'Attachment'
1825

1926
type _OptionDef<T extends OptionType> = {
2027
type: T
@@ -30,6 +37,8 @@ type UserOptionDef = _OptionDef<'User'>
3037
type ChannelOptionDef = _OptionDef<'Channel'>
3138
type RoleOptionDef = _OptionDef<'Role'>
3239
type NumberOptionDef = _OptionDef<'Number'>
40+
type MentionableOptionDef = _OptionDef<'Mentionable'>
41+
type AttachmentOptionDef = _OptionDef<'Attachment'>
3342

3443
type OptionDef =
3544
| StringOptionDef
@@ -39,8 +48,24 @@ type OptionDef =
3948
| ChannelOptionDef
4049
| RoleOptionDef
4150
| NumberOptionDef
51+
| MentionableOptionDef
52+
| AttachmentOptionDef
4253
export type OptionsDef = Record<string, OptionDef>
4354

55+
export type ParsedOptionType =
56+
| string
57+
| number
58+
| boolean
59+
| User
60+
| GuildBasedChannel
61+
| APIInteractionDataResolvedChannel
62+
| Role
63+
| APIRole
64+
| GuildMember
65+
| APIInteractionDataResolvedGuildMember
66+
| Attachment
67+
| null
68+
4469
export type ParsedOptions<T extends OptionsDef = OptionsDef> = Record<
4570
{
4671
[K in keyof T]: T[K] extends {
@@ -49,7 +74,7 @@ export type ParsedOptions<T extends OptionsDef = OptionsDef> = Record<
4974
? K
5075
: never
5176
}[keyof T],
52-
string | undefined
77+
string | null
5378
> &
5479
Record<
5580
{
@@ -59,7 +84,7 @@ export type ParsedOptions<T extends OptionsDef = OptionsDef> = Record<
5984
? K
6085
: never
6186
}[keyof T],
62-
number | undefined
87+
number | null
6388
> &
6489
Record<
6590
{
@@ -69,7 +94,7 @@ export type ParsedOptions<T extends OptionsDef = OptionsDef> = Record<
6994
? K
7095
: never
7196
}[keyof T],
72-
boolean | undefined
97+
boolean | null
7398
> &
7499
Record<
75100
{
@@ -79,7 +104,7 @@ export type ParsedOptions<T extends OptionsDef = OptionsDef> = Record<
79104
? K
80105
: never
81106
}[keyof T],
82-
User | undefined
107+
User | null
83108
> &
84109
Record<
85110
{
@@ -89,7 +114,7 @@ export type ParsedOptions<T extends OptionsDef = OptionsDef> = Record<
89114
? K
90115
: never
91116
}[keyof T],
92-
GuildBasedChannel | undefined
117+
GuildBasedChannel | APIInteractionDataResolvedChannel | null
93118
> &
94119
Record<
95120
{
@@ -99,7 +124,7 @@ export type ParsedOptions<T extends OptionsDef = OptionsDef> = Record<
99124
? K
100125
: never
101126
}[keyof T],
102-
Role | undefined
127+
Role | APIRole | null
103128
> &
104129
Record<
105130
{
@@ -109,7 +134,27 @@ export type ParsedOptions<T extends OptionsDef = OptionsDef> = Record<
109134
? K
110135
: never
111136
}[keyof T],
112-
number | undefined
137+
number | null
138+
> &
139+
Record<
140+
{
141+
[K in keyof T]: T[K] extends {
142+
type: 'Mentionable'
143+
}
144+
? K
145+
: never
146+
}[keyof T],
147+
GuildMember | APIInteractionDataResolvedGuildMember | null
148+
> &
149+
Record<
150+
{
151+
[K in keyof T]: T[K] extends {
152+
type: 'Attachment'
153+
}
154+
? K
155+
: never
156+
}[keyof T],
157+
Attachment | null
113158
>
114159

115160
interface CommandContext<T extends OptionsDef = OptionsDef> {

src/utils.ts

Lines changed: 34 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,13 @@ import {
44
ChatInputCommandInteraction,
55
ContextMenuCommandBuilder,
66
PermissionFlagsBits,
7-
SlashCommandBuilder,
8-
channelMention,
9-
roleMention,
10-
userMention,
11-
type User
7+
SlashCommandBuilder
128
} from 'discord.js'
139
import type {
1410
HarmonixCommand,
1511
HarmonixContextMenu,
16-
OptionType,
17-
OptionsDef
12+
OptionsDef,
13+
ParsedOptionType
1814
} from './types'
1915

2016
export const slashToJSON = (cmd: HarmonixCommand<OptionsDef>) => {
@@ -143,6 +139,22 @@ export const slashToJSON = (cmd: HarmonixCommand<OptionsDef>) => {
143139
return opt
144140
})
145141
break
142+
case 'Mentionable':
143+
builder.addMentionableOption((opt) =>
144+
opt
145+
.setName(name)
146+
.setDescription(arg.description ?? 'No description provided')
147+
.setRequired(arg.required ?? true)
148+
)
149+
break
150+
case 'Attachment':
151+
builder.addAttachmentOption((opt) =>
152+
opt
153+
.setName(name)
154+
.setDescription(arg.description ?? 'No description provided')
155+
.setRequired(arg.required ?? true)
156+
)
157+
break
146158
}
147159
}
148160
}
@@ -176,87 +188,30 @@ export const isHarmonixCommand = (
176188
return (command as HarmonixCommand<OptionsDef>).config.category !== undefined
177189
}
178190

179-
export const resolveOption = async (
180-
interaction: ChatInputCommandInteraction,
181-
type: OptionType | null,
182-
value: string
183-
) => {
184-
switch (type) {
185-
case 'String':
186-
return value
187-
case 'Integer':
188-
return parseInt(value)
189-
case 'Boolean':
190-
return value === 'true'
191-
case 'User':
192-
const user = await resolveUser(interaction, value)
193-
194-
return user
195-
case 'Channel':
196-
const channel = await resolveChannel(interaction, value)
197-
198-
return channel
199-
case 'Role':
200-
const role = await resolveRole(interaction, value)
201-
202-
return role
203-
case 'Number':
204-
return parseFloat(value)
205-
}
206-
}
207-
208-
const resolveUser = async (
209-
interaction: ChatInputCommandInteraction,
210-
value: string
211-
): Promise<User | undefined> => {
212-
return interaction.guild?.members.cache.find(
213-
(member) =>
214-
member.user.username === value ||
215-
member.nickname === value ||
216-
member.id === value ||
217-
userMention(member.id) === value ||
218-
`<@!${member.id}>` === value
219-
)?.user
220-
}
221-
222-
const resolveChannel = async (
191+
export const resolveOption = (
223192
interaction: ChatInputCommandInteraction,
224-
value: string
225-
) => {
226-
return interaction.guild?.channels.cache.find(
227-
(channel) =>
228-
channel.name === value ||
229-
channel.id === value ||
230-
channelMention(channel.id) === value
231-
)
232-
}
233-
234-
const resolveRole = async (
235-
interaction: ChatInputCommandInteraction,
236-
value: string
237-
) => {
238-
return interaction.guild?.roles.cache.find(
239-
(role) =>
240-
role.name === value || role.id === value || roleMention(role.id) === value
241-
)
242-
}
243-
244-
export const toOption = (type: ApplicationCommandOptionType | null) => {
193+
type: ApplicationCommandOptionType,
194+
name: string
195+
): ParsedOptionType => {
245196
switch (type) {
246197
case ApplicationCommandOptionType.String:
247-
return 'String'
198+
return interaction.options.getString(name)
248199
case ApplicationCommandOptionType.Integer:
249-
return 'Integer'
200+
return interaction.options.getInteger(name)
250201
case ApplicationCommandOptionType.Boolean:
251-
return 'Boolean'
202+
return interaction.options.getBoolean(name)
252203
case ApplicationCommandOptionType.User:
253-
return 'User'
204+
return interaction.options.getUser(name)
254205
case ApplicationCommandOptionType.Channel:
255-
return 'Channel'
206+
return interaction.options.getChannel(name)
256207
case ApplicationCommandOptionType.Role:
257-
return 'Role'
208+
return interaction.options.getRole(name)
258209
case ApplicationCommandOptionType.Number:
259-
return 'Number'
210+
return interaction.options.getNumber(name)
211+
case ApplicationCommandOptionType.Mentionable:
212+
return interaction.options.getMentionable(name)
213+
case ApplicationCommandOptionType.Attachment:
214+
return interaction.options.getAttachment(name)
260215
default:
261216
return null
262217
}

0 commit comments

Comments
 (0)