4
4
[ Discord commands] ( https://discord.com/developers/docs/interactions/application-commands )
5
5
that run on [ Cloudflare Workers] ( https://workers.cloudflare.com/ ) , using a
6
6
React-inspired syntax. It focuses on providing a great local development
7
- experience, powered by [ 🔥 Miniflare 2 ] ( https://v2. miniflare.dev/ ) .
7
+ experience, powered by [ 🔥 Miniflare] ( https://miniflare.dev/ ) .
8
8
9
9
<!-- prettier-ignore-start -->
10
10
``` tsx
@@ -15,7 +15,7 @@ function add(): CommandHandler {
15
15
const a = useNumber (" a" , " 1st number" , { required: true });
16
16
const b = useNumber (" b" , " 2nd number" , { required: true });
17
17
return (interaction , env , ctx ) => (
18
- <Message ephemeral >{ a } + { b } = { a + b } </Message >
18
+ <Message ephemeral >{ a } + { b } = { a + b } </Message >
19
19
);
20
20
};
21
21
@@ -44,14 +44,15 @@ export default { fetch: handler };
44
44
45
45
## Quick* ish* Start
46
46
47
- > ⚠️ To enable auto-deployments on reload, Slshx requires the
48
- > [ ` --global-async-io ` Miniflare flag] ( https://v2.miniflare.dev/core/standards#global-functionality-limits )
49
- > to be set.
50
-
51
47
1 . Clone the [ ` slshx-starter ` ] ( https://github.com/mrbbot/slshx-starter )
52
- repository. This includes a [ Miniflare] ( https://v2. miniflare.dev/ ) and
48
+ repository. This includes a [ Miniflare] ( https://miniflare.dev/ ) and
53
49
[ ` esbuild ` ] ( https://esbuild.github.io/ ) setup that removes unneeded local
54
50
development code when deploying to Workers.
51
+
52
+ > ⚠️ To enable auto-deployments on reload, Slshx requires the
53
+ > [ ` --global-async-io ` Miniflare flag] ( https://miniflare.dev/core/standards#global-functionality-limits )
54
+ > to be set. ` slshx-starter ` automatically enables this for you.
55
+
55
56
2 . Copy the ` env.example.jsonc ` file to ` env.jsonc ` . ⚠️ Do not commit this file.
56
57
3 . Create a new application in the
57
58
[ Discord Developer Portal] ( https://discord.com/developers/applications ) . Copy
@@ -220,7 +221,7 @@ Some types have additional optional fields that control acceptable values.
220
221
<!-- prettier-ignore-start -->
221
222
``` tsx
222
223
import { ChannelType } from " slshx" ;
223
- import type { APIUser , APIInteractionDataResolvedChannel , APIRole } from " discord-api-types/v9" ;
224
+ import type { APIUser , APIInteractionDataResolvedChannel , APIRole , APIAttachment } from " discord-api-types/v9" ;
224
225
225
226
function cmd(): CommandHandler {
226
227
useDescription (" Command demonstrating option types" );
@@ -256,6 +257,9 @@ function cmd(): CommandHandler {
256
257
const n1 = useNumber (" name" , " Description" );
257
258
// └ number | null
258
259
const n2 = useNumber (" name" , " Description" , { min: 5 , max: 100 });
260
+
261
+ const a = useAttachment (" name" , " Description" );
262
+ // └ APIAttachment | null
259
263
260
264
return () => {}; // ...
261
265
};
@@ -347,6 +351,11 @@ function cover(): CommandHandler<Env> {
347
351
}
348
352
```
349
353
354
+ > ⚠️ Discord does not include full user, channel, role, mentionable or
355
+ > attachment objects in autocomplete interactions. If a user specifies a value
356
+ > for one of these options, the hook will return a partial object of the form
357
+ > ` { id: "..." } ` instead.
358
+
350
359
### Subcommands
351
360
352
361
Discord supports grouping chat commands into
@@ -1144,6 +1153,115 @@ function selects(): CommandHandler {
1144
1153
1145
1154
![ Select Menu] ( ./.github/screenshots/select.png )
1146
1155
1156
+ ## Using Modals
1157
+
1158
+ [ Modals] ( https://discord.com/developers/docs/interactions/receiving-and-responding#responding-to-an-interaction )
1159
+ allow you to respond to commands or message component interactions with dialog
1160
+ boxes containing text inputs. Instead of returning a ` <Message> ` , return a
1161
+ ` <Modal> ` or a plain message object with the ` [$modal] ` property set to ` true ` .
1162
+
1163
+ To generate a custom modal ID including the required Slshx routing information,
1164
+ call the ` useModal ` hook. This takes a callback function taking an
1165
+ ` interaction ` , ` env ` , and ` ctx ` that will be called when the modal is submitted.
1166
+
1167
+ To add text inputs, call the ` useInput ` hook. This returns an ` [id, value] `
1168
+ tuple containing a custom ID to identify the input and the submitted value. Note
1169
+ that the ` value ` should only be used inside ` useModal ` callback functions.
1170
+
1171
+ <!-- prettier-ignore-start -->
1172
+ ``` tsx
1173
+ import { CommandHandler , useInput , useModal , createElement , Message , Modal , Input , $modal , ComponentType , TextInputStyle } from " slshx" ;
1174
+
1175
+ export function modals(): CommandHandler <Env > {
1176
+ // ...
1177
+ const [nameId, nameValue] = useInput ();
1178
+ const [messageId, messageValue] = useInput ();
1179
+ const modalId = useModal <Env >((interaction , env , ctx ) => {
1180
+ // └ APIModalSubmitInteraction
1181
+
1182
+ // With JSX
1183
+ return <Message >Hello { nameValue } ! { messageValue } </Message >;
1184
+
1185
+ // Without JSX
1186
+ return { content: ` Hello ${nameValue }! ${messageValue } ` };
1187
+ });
1188
+
1189
+ return () => {
1190
+ // With JSX
1191
+ return (
1192
+ <Modal id = { modalId } title = " Send Message" >
1193
+ <Input
1194
+ id = { nameId } // Only `id` and `label` are required
1195
+ label = " Name"
1196
+ required
1197
+ value = " Initial value"
1198
+ minLength = { 1 }
1199
+ />
1200
+ <Input
1201
+ id = { messageId }
1202
+ label = " Message"
1203
+ placeholder = " Something to send"
1204
+ maxLength = { 1000 }
1205
+ paragraph // Multiline input
1206
+ />
1207
+ </Modal >
1208
+ );
1209
+
1210
+ // Without JSX
1211
+ return {
1212
+ [$modal ]: true ,
1213
+ custom_id: modalId ,
1214
+ title: " Send Message" ,
1215
+ components: [
1216
+ {
1217
+ type: ComponentType .ACTION_ROW ,
1218
+ components: [
1219
+ {
1220
+ type: ComponentType .TEXT_INPUT ,
1221
+ style: TextInputStyle .SHORT ,
1222
+ custom_id: nameId ,
1223
+ label: " Name" ,
1224
+ required: true ,
1225
+ value: " Initial value" ,
1226
+ min_length: 1 ,
1227
+ },
1228
+ ],
1229
+ },
1230
+ {
1231
+ type: ComponentType .ACTION_ROW ,
1232
+ components: [
1233
+ {
1234
+ type: ComponentType .TEXT_INPUT ,
1235
+ style: TextInputStyle .PARAGRAPH ,
1236
+ custom_id: messageId ,
1237
+ label: " Message" ,
1238
+ placeholder: " Something to send" ,
1239
+ required: false , // Inputs are required by default
1240
+ max_length: 1000 ,
1241
+ },
1242
+ ],
1243
+ },
1244
+ ],
1245
+ };
1246
+ };
1247
+ }
1248
+ ```
1249
+ <!-- prettier-ignore-end -->
1250
+
1251
+ ![ Modal] ( ./.github/screenshots/modal.png )
1252
+
1253
+ ![ Modal Submission] ( ./.github/screenshots/modal-submit.png )
1254
+
1255
+ ## Errors
1256
+
1257
+ During development, if a command, message component, or modal submission handler
1258
+ throws an error, Slshx will respond with the message and stack trace. In
1259
+ production, the interaction will fail.
1260
+
1261
+ ![ Development Error] ( ./.github/screenshots/error-development.png )
1262
+
1263
+ ![ Production Error] ( ./.github/screenshots/error-production.png )
1264
+
1147
1265
## Deploying Commands Globally
1148
1266
1149
1267
Once you're happy with your commands, you can deploy them globally, making them
@@ -1273,9 +1391,11 @@ If an API does not have Slshx bindings, you can use the
1273
1391
` URLSearchParams ` (sent as ` application/x-www-form-urlencoded ` ), or an
1274
1392
arbitrary JSON-serializable object (sent as ` application/json ` ). If ` body ` is
1275
1393
falsy, it's omitted.
1276
- - ` auth ` can be an object of the form ` { bearer: string } ` (what ` getBearerAuth `
1277
- returns) to use ` Bearer ` token authentication, or
1278
- ` { username: string; password: string } ` to use HTTP ` Basic ` authentication
1394
+ - ` auth ` can be an object of the form:
1395
+ - ` { bearer: string } ` (what ` getBearerAuth ` returns) to use ` Bearer ` token
1396
+ authentication
1397
+ - ` { username: string; password: string } ` to use HTTP ` Basic ` authentication
1398
+ - ` { bot: string } ` to use ` Bot ` token authentication
1279
1399
1280
1400
This function is generic in ` Body ` and ` Result ` . You can find types for these in
1281
1401
the ` discord-api-types ` package. See [ ` src/api/ ` ] ( ./src/api ) for examples of
0 commit comments