Skip to content

Commit 7bfdc43

Browse files
committed
feat: implement file based subcommands and update examples in playground
1 parent 4900f6a commit 7bfdc43

File tree

17 files changed

+421
-148
lines changed

17 files changed

+421
-148
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,11 @@ Here's what's planned for future releases:
252252
- [ ] Attachment type
253253
- [ ] Better JSDocs support JSDoc comments
254254
- [ ] Localization support
255-
- [ ] File-based subcommands
255+
- [x] File-based subcommands
256256
- [x] Auto-complete API
257257
- [ ] Guild-specific commands
258258
- [ ] Nuxt-devtools integration
259-
- [ ] Unit tests
259+
- [ ] Unit tests (WIP)
260260

261261
### Web Interface Enhancements
262262

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"scripts": {
3939
"prepack": "nuxt-module-build build",
4040
"dev": "pnpm run dev:prepare && nuxi dev playground",
41-
"dev:debug": "pnpm run dev:prepare && NODE_OPTIONS='--inspect' nuxi dev playground",
41+
"dev:debug": "pnpm run dev:prepare && node --inspect ./node_modules/nuxt/bin/nuxt.mjs dev playground --no-fork",
4242
"dev:build": "nuxi build playground",
4343
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
4444
"release": "pnpm run lint && pnpm run test && pnpm run prepack && changelogen --release && pnpm publish && git push --follow-tags",
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
* @name channel
3+
* @description A set of commands related to channels
4+
*/
5+
export default () => {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
* @name members
3+
* @description A set of commands related to getting information from channels members
4+
*/
5+
export default () => {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { ChannelType } from 'discord.js'
2+
3+
/**
4+
* @name count
5+
* @description Gets the number of members in the channel
6+
*/
7+
export default defineSlashCommand(async () => {
8+
const interaction = useInteraction()
9+
10+
if (interaction?.channel?.type === ChannelType.GuildText) {
11+
const members = interaction.channel.members
12+
return reply.ephemeral(`There are ${members.size} members in ${interaction.channel.name}.`)
13+
}
14+
else {
15+
return reply.ephemeral('Unsupported channel type')
16+
}
17+
})
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { ChannelType } from 'discord.js'
2+
3+
/**
4+
* @name names
5+
* @description Gets the names of all members in the channel
6+
*/
7+
export default defineSlashCommand(async () => {
8+
const interaction = useInteraction()
9+
10+
if (interaction?.channel?.type === ChannelType.GuildText) {
11+
const members = interaction.channel.members
12+
const memberNames = members.map(member => member.displayName).join(', ')
13+
return reply.ephemeral(`Members of ${interaction.channel.name}: ${memberNames}`)
14+
}
15+
else {
16+
return reply.ephemeral('Unsupported channel type')
17+
}
18+
})
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { ChannelType } from 'discord.js'
2+
3+
/**
4+
* @name send
5+
* @description Sends a message to the channel
6+
* @param text The text to send
7+
*/
8+
export default defineSlashCommand(async (text: string) => {
9+
const interaction = useInteraction()
10+
11+
if (interaction?.channel?.type === ChannelType.GuildText) {
12+
await interaction.channel.send(text)
13+
return reply.ephemeral(`Message '${text}' sent to ${interaction.channel.name}!`)
14+
}
15+
else {
16+
return reply.ephemeral('Unsupported channel type')
17+
}
18+
})

src/runtime/client/pages/slash-commands.css

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
.font-medium{--un-font-weight:var(--fontWeight-medium);font-weight:var(--fontWeight-medium);}
5656
.font-semibold{--un-font-weight:var(--fontWeight-semibold);font-weight:var(--fontWeight-semibold);}
5757
.mx-auto{margin-inline:auto;}
58+
.my-0\.75{margin-block:calc(var(--spacing) * 0.75);}
5859
.my-6{margin-block:calc(var(--spacing) * 6);}
5960
.mb-1{margin-bottom:calc(var(--spacing) * 1);}
6061
.mb-16{margin-bottom:calc(var(--spacing) * 16);}
@@ -80,22 +81,23 @@
8081
.flex{display:flex;}
8182
.flex-col{flex-direction:column;}
8283
.flex-wrap{flex-wrap:wrap;}
84+
.gap-1{gap:calc(var(--spacing) * 1);}
8385
.gap-2{gap:calc(var(--spacing) * 2);}
8486
.gap-3{gap:calc(var(--spacing) * 3);}
8587
.gap-4{gap:calc(var(--spacing) * 4);}
8688
.grid{display:grid;}
89+
.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6);}
8790
.h-12{height:calc(var(--spacing) * 12);}
8891
.h-4{height:calc(var(--spacing) * 4);}
89-
.h-5{height:calc(var(--spacing) * 5);}
9092
.w-12{width:calc(var(--spacing) * 12);}
9193
.w-4{width:calc(var(--spacing) * 4);}
92-
.w-5{width:calc(var(--spacing) * 5);}
9394
.w-full{width:100%;}
9495
.hover\:cursor-pointer:hover{cursor:pointer;}
9596
.disabled\:hover\:cursor-not-allowed:hover:disabled{cursor:not-allowed;}
9697
.ring-0{--un-ring-shadow:var(--un-ring-inset,) 0 0 0 calc(0px + var(--un-ring-offset-width)) var(--un-ring-color, currentColor);box-shadow:var(--un-inset-shadow), var(--un-inset-ring-shadow), var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow);}
9798
.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--un-ease, var(--default-transition-timingFunction));transition-duration:var(--un-duration, var(--default-transition-duration));}
9899
.duration-200{--un-duration:200ms;transition-duration:200ms;}
100+
.items-start{align-items:flex-start;}
99101
.items-center{align-items:center;}
100102
.justify-between{justify-content:space-between;}
101103
.overflow-hidden{overflow:hidden;}

src/runtime/client/pages/slash-commands.vue

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script lang="ts" setup>
22
import type { WatchEvent } from 'nuxt/schema'
33
import type { SlashCommand, SlashCommandOption } from '../../../types'
4+
import slashCommands from '#build/discord/slashCommands'
45
import { computed, ref, useFetch, useRuntimeConfig, watchEffect } from '#imports'
56
import { useWebSocket } from '@vueuse/core'
67
import TheHeader from '../components/TheHeader.vue'
@@ -81,7 +82,7 @@ function getRemoteId(command: any): string | undefined {
8182
return undefined
8283
}
8384
84-
const commands = ref([] as typeof import('discord/slashCommands').default)
85+
const commands = ref(slashCommands)
8586
8687
const {
8788
data: diff,
@@ -90,9 +91,6 @@ const {
9091
'/api/discord/slash-command/remote-diff',
9192
{
9293
method: 'post',
93-
body: {
94-
commands,
95-
},
9694
immediate: import.meta.dev,
9795
},
9896
)
@@ -301,9 +299,9 @@ const statusClasses = {
301299
>
302300
<template #header>
303301
<div class="flex items-center justify-between">
304-
<div class="flex gap-3 items-center">
305-
<UIcon name="i-heroicons-command-line" class="text-primary-500 h-5 w-5" />
306-
<div>
302+
<div class="flex gap-3 items-start">
303+
<UIcon name="i-heroicons-command-line" class="text-primary-500 my-0.75 size-6" />
304+
<div class="flex flex-col gap-1 items-start">
307305
<h3
308306
class="text-lg text-gray-700 font-semibold dark:text-gray-200"
309307
:class="command.status === 'conflict' && 'text-[var(--ui-error)]!'"
@@ -314,7 +312,14 @@ const statusClasses = {
314312
{{ command.description }}
315313
</p>
316314
<UBadge
317-
v-if="command.options.length > 0"
315+
v-if="'subcommands' in command && (command.subcommands?.length ?? 0) > 0"
316+
:label="`${command.subcommands!.length} subcommand${command.subcommands!.length === 1 ? '' : 's'}`"
317+
variant="soft"
318+
color="info"
319+
size="sm"
320+
/>
321+
<UBadge
322+
v-else-if="command.options.length > 0"
318323
:label="`${command.options.length} option${command.options.length === 1 ? '' : 's'}`"
319324
variant="soft"
320325
color="neutral"
Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,12 @@
1-
import type { APIApplicationCommand } from 'discord.js'
2-
import type { SlashCommand, SlashCommandRuntime } from '../../../../../types'
1+
import type { SlashCommand } from '../../../../../types'
32
import { defineEventHandler, readBody } from 'h3'
43
import { useDiscordClient } from '../../../utils/useDiscordClient'
54

6-
export default defineEventHandler<{
7-
body?: {
8-
commands?: SlashCommand[]
9-
}
10-
}, Promise<{
11-
added: SlashCommandRuntime[]
12-
removed: APIApplicationCommand[]
13-
changed: {
14-
local: SlashCommandRuntime
15-
remote: APIApplicationCommand
16-
}[]
17-
synced: {
18-
local: SlashCommandRuntime
19-
remote: APIApplicationCommand
20-
}[]
21-
conflict: SlashCommandRuntime[]
22-
}>>(async (event) => {
5+
export default defineEventHandler(async (event) => {
236
const client = useDiscordClient()
24-
const body = await readBody(event)
7+
const body: {
8+
commands?: SlashCommand[]
9+
} = await readBody(event)
2510
const diff = await client.diffRemoteSlashCommands(body?.commands)
2611
return diff
2712
})

0 commit comments

Comments
 (0)