0
# RestAction System
1
2
Powerful asynchronous request system with automatic rate-limit handling, chaining capabilities, error handling, and execution control for Discord API interactions.
3
4
## Capabilities
5
6
### Core RestAction
7
8
The foundation of JDA's asynchronous request system providing multiple execution patterns.
9
10
```java { .api }
11
/**
12
* Represents an asynchronous Discord API request that can be executed in various ways.
13
* @param <T> The type that will be returned when this RestAction is executed
14
*/
15
interface RestAction<T> {
16
/** Execute asynchronously without callbacks */
17
void queue();
18
19
/** Execute asynchronously with success callback */
20
void queue(Consumer<? super T> success);
21
22
/** Execute asynchronously with success and failure callbacks */
23
void queue(Consumer<? super T> success, Consumer<? super Throwable> failure);
24
25
/** Execute and return CompletableFuture */
26
CompletableFuture<T> submit();
27
28
/** Execute synchronously (blocking) */
29
T complete() throws RuntimeException;
30
31
/** Execute synchronously with timeout */
32
T complete(long timeout, TimeUnit unit) throws RuntimeException, TimeoutException;
33
34
/** Execute after delay */
35
RestAction<T> queueAfter(long delay, TimeUnit unit);
36
RestAction<T> queueAfter(long delay, TimeUnit unit, ScheduledExecutorService executor);
37
38
/** Execute after delay with callbacks */
39
void queueAfter(long delay, TimeUnit unit, Consumer<? super T> success);
40
void queueAfter(long delay, TimeUnit unit, Consumer<? super T> success, Consumer<? super Throwable> failure);
41
42
/** Execute after delay and return future */
43
CompletableFuture<T> submitAfter(long delay, TimeUnit unit);
44
CompletableFuture<T> submitAfter(long delay, TimeUnit unit, ScheduledExecutorService executor);
45
46
/** Execute after delay, blocking */
47
T completeAfter(long delay, TimeUnit unit);
48
49
/** Transform result with function */
50
<U> RestAction<U> map(Function<? super T, ? extends U> mapper);
51
52
/** Chain with another RestAction */
53
<U> RestAction<U> flatMap(Function<? super T, ? extends RestAction<U>> flatMapper);
54
55
/** Handle errors and provide fallback */
56
RestAction<T> onErrorMap(Function<? super Throwable, ? extends T> mapper);
57
RestAction<T> onErrorMap(Predicate<? super Throwable> condition, Function<? super Throwable, ? extends T> mapper);
58
59
/** Chain error handling with RestAction */
60
RestAction<T> onErrorFlatMap(Function<? super Throwable, ? extends RestAction<T>> flatMapper);
61
RestAction<T> onErrorFlatMap(Predicate<? super Throwable> condition, Function<? super Throwable, ? extends RestAction<T>> flatMapper);
62
63
/** Set request timeout */
64
RestAction<T> timeout(long timeout, TimeUnit unit);
65
66
/** Set deadline for request */
67
RestAction<T> deadline(long timestamp);
68
69
/** Add check before execution */
70
RestAction<T> setCheck(BooleanSupplier checks);
71
72
/** Get the check supplier */
73
BooleanSupplier getCheck();
74
75
/** Check if this RestAction is completed */
76
boolean isPassContext();
77
78
/** Set context passing */
79
RestAction<T> setPassContext(boolean passContext);
80
81
/** Get JDA instance */
82
JDA getJDA();
83
}
84
```
85
86
**Usage Examples:**
87
88
```java
89
import net.dv8tion.jda.api.requests.RestAction;
90
import java.util.concurrent.CompletableFuture;
91
import java.util.concurrent.TimeUnit;
92
93
// Basic asynchronous execution
94
channel.sendMessage("Hello!").queue();
95
96
// With success callback
97
channel.sendMessage("Hello!").queue(
98
message -> System.out.println("Message sent: " + message.getId())
99
);
100
101
// With success and error callbacks
102
channel.sendMessage("Hello!").queue(
103
message -> System.out.println("Success: " + message.getId()),
104
error -> System.err.println("Failed to send: " + error.getMessage())
105
);
106
107
// Using CompletableFuture
108
CompletableFuture<Message> future = channel.sendMessage("Hello!").submit();
109
future.thenAccept(message -> System.out.println("Message sent: " + message.getId()))
110
.exceptionally(error -> {
111
System.err.println("Error: " + error.getMessage());
112
return null;
113
});
114
115
// Synchronous execution (blocking)
116
try {
117
Message message = channel.sendMessage("Hello!").complete();
118
System.out.println("Message sent synchronously: " + message.getId());
119
} catch (Exception e) {
120
System.err.println("Failed to send message: " + e.getMessage());
121
}
122
123
// Delayed execution
124
channel.sendMessage("This will be sent in 5 seconds")
125
.queueAfter(5, TimeUnit.SECONDS);
126
127
// With timeout
128
channel.sendMessage("Hello!")
129
.timeout(10, TimeUnit.SECONDS)
130
.queue(
131
success -> System.out.println("Sent within timeout"),
132
error -> System.err.println("Failed or timed out: " + error.getMessage())
133
);
134
```
135
136
### RestAction Chaining
137
138
Powerful chaining capabilities for sequential and dependent operations.
139
140
```java { .api }
141
/**
142
* Chain RestActions together for complex operations.
143
*/
144
// Example chaining methods (part of RestAction interface)
145
146
/** Transform the result */
147
<U> RestAction<U> map(Function<? super T, ? extends U> mapper);
148
149
/** Chain with another RestAction */
150
<U> RestAction<U> flatMap(Function<? super T, ? extends RestAction<U>> flatMapper);
151
152
/** Handle errors with transformation */
153
RestAction<T> onErrorMap(Function<? super Throwable, ? extends T> mapper);
154
155
/** Handle errors with RestAction chaining */
156
RestAction<T> onErrorFlatMap(Function<? super Throwable, ? extends RestAction<T>> flatMapper);
157
```
158
159
**Usage Examples:**
160
161
```java
162
// Transform message content
163
channel.retrieveMessageById("123456789")
164
.map(Message::getContentRaw)
165
.queue(content -> System.out.println("Message content: " + content));
166
167
// Chain operations: send message, then pin it
168
channel.sendMessage("Important announcement!")
169
.flatMap(Message::pin)
170
.queue(
171
success -> System.out.println("Message sent and pinned"),
172
error -> System.err.println("Failed: " + error.getMessage())
173
);
174
175
// Complex chaining: create role, assign to user, send confirmation
176
guild.createRole()
177
.setName("New Member")
178
.setColor(Color.GREEN)
179
.flatMap(role -> guild.addRoleToMember(member, role)
180
.map(success -> role))
181
.flatMap(role -> channel.sendMessage("Welcome! You've been given the " + role.getAsMention() + " role."))
182
.queue(
183
message -> System.out.println("Welcome process completed"),
184
error -> System.err.println("Welcome process failed: " + error.getMessage())
185
);
186
187
// Error handling with fallback
188
guild.retrieveMemberById(userId)
189
.onErrorFlatMap(error -> {
190
if (error instanceof ErrorResponseException) {
191
ErrorResponseException ere = (ErrorResponseException) error;
192
if (ere.getErrorCode() == 10007) { // Unknown Member
193
return jda.retrieveUserById(userId)
194
.map(user -> null); // Return null for non-members
195
}
196
}
197
return RestAction.forResult(null);
198
})
199
.queue(member -> {
200
if (member != null) {
201
System.out.println("Member found: " + member.getEffectiveName());
202
} else {
203
System.out.println("User exists but is not a member");
204
}
205
});
206
207
// Transform with error handling
208
channel.retrieveMessageById(messageId)
209
.map(message -> message.getContentRaw().length())
210
.onErrorMap(error -> -1) // Return -1 if message not found
211
.queue(length -> {
212
if (length == -1) {
213
System.out.println("Message not found");
214
} else {
215
System.out.println("Message length: " + length);
216
}
217
});
218
```
219
220
### Auditable RestActions
221
222
RestActions that create entries in the guild's audit log with reason tracking.
223
224
```java { .api }
225
/**
226
* Extension of RestAction for actions that appear in audit log.
227
* @param <T> The return type of this RestAction
228
*/
229
interface AuditableRestAction<T> extends RestAction<T> {
230
/** Set audit log reason */
231
AuditableRestAction<T> reason(String reason);
232
233
/** Get current audit log reason */
234
String getReason();
235
}
236
```
237
238
**Usage Examples:**
239
240
```java
241
// Ban with audit log reason
242
guild.ban(user, 7, TimeUnit.DAYS)
243
.reason("Spamming in chat")
244
.queue(
245
success -> System.out.println("User banned with reason logged"),
246
error -> System.err.println("Ban failed: " + error.getMessage())
247
);
248
249
// Kick with reason
250
guild.kick(member)
251
.reason("Violation of community guidelines")
252
.queue();
253
254
// Role modification with reason
255
guild.createRole()
256
.setName("Moderator")
257
.setPermissions(Permission.KICK_MEMBERS, Permission.MESSAGE_MANAGE)
258
.reason("Creating moderator role for new staff")
259
.queue();
260
261
// Channel creation with reason
262
guild.createTextChannel("announcements")
263
.setTopic("Important server announcements")
264
.reason("Creating dedicated announcement channel")
265
.queue();
266
267
// Member timeout with reason
268
member.timeoutFor(1, TimeUnit.HOURS)
269
.reason("Inappropriate behavior in voice chat")
270
.queue(
271
success -> channel.sendMessage("Member has been timed out for 1 hour").queue(),
272
error -> channel.sendMessage("Failed to timeout member: " + error.getMessage()).queue()
273
);
274
```
275
276
### Specialized RestActions
277
278
Specific RestAction implementations for different Discord API operations.
279
280
```java { .api }
281
/**
282
* RestAction for creating messages with additional message-specific options.
283
*/
284
interface MessageCreateAction extends RestAction<Message> {
285
MessageCreateAction setContent(String content);
286
MessageCreateAction setEmbeds(MessageEmbed... embeds);
287
MessageCreateAction setFiles(FileUpload... files);
288
MessageCreateAction setComponents(ActionRow... components);
289
MessageCreateAction setTTS(boolean tts);
290
MessageCreateAction setSuppressEmbeds(boolean suppress);
291
MessageCreateAction mentionUsers(String... userIds);
292
MessageCreateAction mentionRoles(String... roleIds);
293
}
294
295
/**
296
* RestAction for editing messages.
297
*/
298
interface MessageEditAction extends RestAction<Message> {
299
MessageEditAction setContent(String content);
300
MessageEditAction setEmbeds(MessageEmbed... embeds);
301
MessageEditAction setComponents(ActionRow... components);
302
MessageEditAction setAttachments(AttachedFile... attachments);
303
MessageEditAction setSuppressEmbeds(boolean suppress);
304
}
305
306
/**
307
* RestAction for creating channels.
308
*/
309
interface ChannelAction<T extends GuildChannel> extends AuditableRestAction<T> {
310
ChannelAction<T> setName(String name);
311
ChannelAction<T> setTopic(String topic);
312
ChannelAction<T> setNSFW(boolean nsfw);
313
ChannelAction<T> setPosition(Integer position);
314
ChannelAction<T> setParent(Category parent);
315
ChannelAction<T> setSlowmode(int slowmode);
316
ChannelAction<T> setBitrate(Integer bitrate);
317
ChannelAction<T> setUserlimit(Integer userlimit);
318
ChannelAction<T> addPermissionOverride(IPermissionHolder permHolder, long allow, long deny);
319
ChannelAction<T> addMemberPermissionOverride(long memberId, long allow, long deny);
320
ChannelAction<T> addRolePermissionOverride(long roleId, long allow, long deny);
321
}
322
323
/**
324
* RestAction for creating roles.
325
*/
326
interface RoleAction extends AuditableRestAction<Role> {
327
RoleAction setName(String name);
328
RoleAction setHoisted(Boolean hoisted);
329
RoleAction setMentionable(Boolean mentionable);
330
RoleAction setColor(Color color);
331
RoleAction setColor(int rgb);
332
RoleAction setPermissions(Permission... permissions);
333
RoleAction setPermissions(Collection<Permission> permissions);
334
RoleAction setPermissions(long permissions);
335
RoleAction setIcon(Icon icon);
336
RoleAction setEmoji(Emoji emoji);
337
}
338
339
/**
340
* RestAction for creating invites.
341
*/
342
interface InviteAction extends RestAction<Invite> {
343
InviteAction setMaxAge(Integer maxAge);
344
InviteAction setMaxUses(Integer maxUses);
345
InviteAction setTemporary(Boolean temporary);
346
InviteAction setUnique(Boolean unique);
347
InviteAction setTargetUser(User targetUser);
348
InviteAction setTargetApplication(long applicationId);
349
InviteAction setTargetType(Invite.TargetType targetType);
350
}
351
```
352
353
**Usage Examples:**
354
355
```java
356
// Complex channel creation
357
guild.createTextChannel("general-chat")
358
.setTopic("General discussion channel")
359
.setNSFW(false)
360
.setSlowmode(5) // 5 second slowmode
361
.addMemberPermissionOverride(member.getIdLong(),
362
Permission.VIEW_CHANNEL.getRawValue(), 0)
363
.addRolePermissionOverride(mutedRole.getIdLong(),
364
0, Permission.SEND_MESSAGES.getRawValue())
365
.reason("Creating general chat channel")
366
.queue(channel -> {
367
System.out.println("Created channel: " + channel.getName());
368
369
// Send welcome message to new channel
370
channel.sendMessage("Welcome to the general chat!")
371
.queue();
372
});
373
374
// Complex role creation with permissions
375
guild.createRole()
376
.setName("Helper")
377
.setColor(Color.CYAN)
378
.setHoisted(true)
379
.setMentionable(true)
380
.setPermissions(
381
Permission.MESSAGE_MANAGE,
382
Permission.KICK_MEMBERS,
383
Permission.MANAGE_ROLES
384
)
385
.reason("Creating helper role for trusted members")
386
.flatMap(role -> {
387
// Assign role to specific member
388
return guild.addRoleToMember(member, role)
389
.reason("Promoting member to helper")
390
.map(success -> role);
391
})
392
.queue(role -> {
393
channel.sendMessage("Created " + role.getAsMention() + " role and assigned to " + member.getAsMention())
394
.queue();
395
});
396
397
// Invite creation with specific settings
398
channel.createInvite()
399
.setMaxAge(3600) // 1 hour
400
.setMaxUses(10)
401
.setTemporary(false)
402
.setUnique(true)
403
.queue(invite -> {
404
System.out.println("Created invite: " + invite.getUrl());
405
406
// Send invite in DM
407
member.getUser().openPrivateChannel()
408
.flatMap(dm -> dm.sendMessage("Here's your server invite: " + invite.getUrl()))
409
.queue();
410
});
411
```
412
413
### RestAction Utilities
414
415
Utility methods and classes for advanced RestAction manipulation.
416
417
```java { .api }
418
/**
419
* Utility methods for RestAction operations.
420
*/
421
class RestAction {
422
/** Create RestAction that immediately completes with value */
423
static <E> RestAction<E> forResult(E result);
424
425
/** Combine multiple RestActions */
426
static RestAction<List<Object>> allOf(RestAction<?>... actions);
427
static RestAction<List<Object>> allOf(Collection<? extends RestAction<?>> actions);
428
429
/** Execute first successful RestAction */
430
static <T> RestAction<T> firstOf(RestAction<T>... actions);
431
static <T> RestAction<T> firstOf(Collection<? extends RestAction<T>> actions);
432
433
/** Set default failure handler */
434
static void setDefaultFailure(Consumer<? super Throwable> callback);
435
436
/** Set default success handler */
437
static void setDefaultSuccess(Consumer<Object> callback);
438
439
/** Get default timeout */
440
static long getDefaultTimeout(TimeUnit unit);
441
442
/** Set default timeout */
443
static void setDefaultTimeout(long timeout, TimeUnit unit);
444
}
445
```
446
447
**Usage Examples:**
448
449
```java
450
// Combine multiple operations
451
List<RestAction<Message>> messageActions = Arrays.asList(
452
channel1.sendMessage("Hello from channel 1"),
453
channel2.sendMessage("Hello from channel 2"),
454
channel3.sendMessage("Hello from channel 3")
455
);
456
457
RestAction.allOf(messageActions)
458
.queue(results -> System.out.println("All messages sent successfully"));
459
460
// First successful operation
461
List<RestAction<User>> userRetrieves = Arrays.asList(
462
jda.retrieveUserById("123456789"),
463
jda.retrieveUserById("987654321"),
464
jda.retrieveUserById("555666777")
465
);
466
467
RestAction.firstOf(userRetrieves)
468
.queue(user -> System.out.println("Found user: " + user.getName()));
469
470
// Immediate result
471
RestAction<String> immediateResult = RestAction.forResult("Cached value");
472
immediateResult.queue(value -> System.out.println("Got: " + value));
473
474
// Set global defaults
475
RestAction.setDefaultTimeout(30, TimeUnit.SECONDS);
476
RestAction.setDefaultFailure(error ->
477
System.err.println("Default error handler: " + error.getMessage()));
478
479
// Complex batch operation
480
List<Member> membersToTimeout = getViolatingMembers();
481
List<RestAction<Void>> timeoutActions = membersToTimeout.stream()
482
.map(member -> member.timeoutFor(10, TimeUnit.MINUTES)
483
.reason("Automated moderation action"))
484
.collect(Collectors.toList());
485
486
RestAction.allOf(timeoutActions)
487
.queue(
488
success -> channel.sendMessage("Timed out " + membersToTimeout.size() + " members").queue(),
489
error -> channel.sendMessage("Failed to timeout some members: " + error.getMessage()).queue()
490
);
491
```
492
493
## Types
494
495
```java { .api }
496
// Error response exception for API errors
497
class ErrorResponseException extends RuntimeException {
498
/** Get Discord error code */
499
int getErrorCode();
500
501
/** Get error response */
502
ErrorResponse getErrorResponse();
503
504
/** Get meaning of error */
505
String getMeaning();
506
507
/** Check if error is server error */
508
boolean isServerError();
509
}
510
511
// Common error responses
512
enum ErrorResponse {
513
GENERAL_ERROR(0, "General error"),
514
UNKNOWN_ACCOUNT(10001, "Unknown account"),
515
UNKNOWN_APPLICATION(10002, "Unknown application"),
516
UNKNOWN_CHANNEL(10003, "Unknown channel"),
517
UNKNOWN_GUILD(10004, "Unknown guild"),
518
UNKNOWN_INTEGRATION(10005, "Unknown integration"),
519
UNKNOWN_INVITE(10006, "Unknown invite"),
520
UNKNOWN_MEMBER(10007, "Unknown member"),
521
UNKNOWN_MESSAGE(10008, "Unknown message"),
522
UNKNOWN_OVERWRITE(10009, "Unknown permission overwrite"),
523
UNKNOWN_PROVIDER(10010, "Unknown provider"),
524
UNKNOWN_ROLE(10011, "Unknown role"),
525
UNKNOWN_TOKEN(10012, "Unknown token"),
526
UNKNOWN_USER(10013, "Unknown user"),
527
UNKNOWN_EMOJI(10014, "Unknown emoji"),
528
UNKNOWN_WEBHOOK(10015, "Unknown webhook"),
529
UNKNOWN_BAN(10026, "Unknown ban"),
530
UNKNOWN_INTERACTION(10062, "Unknown interaction"),
531
BOT_PROHIBITED_ENDPOINT(20001, "Bots cannot use this endpoint"),
532
BOT_ONLY_ENDPOINT(20002, "Only bots can use this endpoint"),
533
ANNOUNCEMENT_EDIT_LIMIT_EXCEEDED(20022, "Announcement rate limit exceeded"),
534
CHANNEL_HIT_WRITE_RATELIMIT(20028, "Channel rate limit exceeded"),
535
MAXIMUM_GUILDS(30001, "Maximum number of guilds reached"),
536
MAXIMUM_FRIENDS(30002, "Maximum number of friends reached"),
537
MAXIMUM_PINS(30003, "Maximum number of pins reached for the channel"),
538
MAXIMUM_ROLES(30005, "Maximum number of guild roles reached"),
539
MAXIMUM_WEBHOOKS(30007, "Maximum number of webhooks reached"),
540
MAXIMUM_EMOJIS(30008, "Maximum number of emojis reached"),
541
MAXIMUM_REACTIONS(30010, "Maximum number of reactions reached"),
542
MAXIMUM_CHANNELS(30013, "Maximum number of guild channels reached"),
543
MAXIMUM_ATTACHMENTS(30015, "Maximum number of attachments in a message reached"),
544
MAXIMUM_INVITES(30016, "Maximum number of invites reached"),
545
GUILD_ALREADY_HAS_TEMPLATE(30031, "Guild already has a template"),
546
UNAUTHORIZED(40001, "Unauthorized"),
547
ACCOUNT_VERIFICATION_REQUIRED(40002, "Account verification required"),
548
REQUEST_ENTITY_TOO_LARGE(40005, "Request entity too large"),
549
FEATURE_TEMPORARILY_DISABLED(40006, "Feature temporarily disabled server-side"),
550
USER_BANNED(40007, "User banned from this guild"),
551
MISSING_ACCESS(50001, "Missing access"),
552
INVALID_ACCOUNT_TYPE(50002, "Invalid account type"),
553
CANNOT_EXECUTE_ON_DM(50003, "Cannot execute action on a DM channel"),
554
GUILD_WIDGET_DISABLED(50004, "Guild widget disabled"),
555
CANNOT_EDIT_MESSAGE_BY_OTHER(50005, "Cannot edit a message authored by another user"),
556
CANNOT_SEND_EMPTY_MESSAGE(50006, "Cannot send an empty message"),
557
CANNOT_MESSAGE_USER(50007, "Cannot send messages to this user"),
558
CANNOT_SEND_IN_VOICE_CHANNEL(50008, "Cannot send messages in a voice channel"),
559
CHANNEL_VERIFICATION_TOO_HIGH(50009, "Channel verification level is too high for you to gain access"),
560
OAUTH2_APPLICATION_BOT_ABSENT(50010, "OAuth2 application does not have a bot"),
561
OAUTH2_APPLICATION_LIMIT_REACHED(50011, "OAuth2 application limit reached"),
562
INVALID_OAUTH_STATE(50012, "Invalid OAuth2 state"),
563
MISSING_PERMISSIONS(50013, "Missing permissions"),
564
INVALID_AUTHENTICATION_TOKEN(50014, "Invalid authentication token"),
565
NOTE_TOO_LONG(50015, "Note was too long"),
566
INVALID_BULK_DELETE_QUANTITY(50016, "Invalid bulk delete quantity"),
567
CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL(50019, "Cannot pin a message in a different channel"),
568
INVALID_OR_TAKEN_INVITE_CODE(50020, "Invalid or taken invite code"),
569
CANNOT_EXECUTE_ON_SYSTEM_MESSAGE(50021, "Cannot execute action on a system message"),
570
CANNOT_EXECUTE_ON_CHANNEL_TYPE(50024, "Cannot execute action on this channel type"),
571
INVALID_OAUTH_TOKEN(50025, "Invalid OAuth2 access token"),
572
MISSING_OAUTH_SCOPE(50026, "Missing required OAuth2 scope"),
573
INVALID_WEBHOOK_TOKEN(50027, "Invalid webhook token"),
574
INVALID_ROLE(50028, "Invalid role"),
575
INVALID_RECIPIENTS(50033, "Invalid Recipient(s)"),
576
BULK_DELETE_MESSAGE_TOO_OLD(50034, "Bulk delete messages too old"),
577
INVALID_FORM_BODY(50035, "Invalid form body"),
578
INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT(50036, "Invite accepted to guild not containing bot"),
579
INVALID_API_VERSION(50041, "Invalid API version"),
580
FILE_UPLOADED_EXCEEDS_MAXIMUM_SIZE(50045, "File uploaded exceeds maximum size"),
581
INVALID_FILE_UPLOADED(50046, "Invalid file uploaded"),
582
REACTION_BLOCKED(90001, "Reaction was blocked"),
583
API_RESOURCE_OVERLOADED(130000, "API resource is currently overloaded");
584
585
/** Get numeric error code */
586
int getCode();
587
588
/** Get error meaning */
589
String getMeaning();
590
}
591
592
// Rate limit exception
593
class RateLimitedException extends RuntimeException {
594
/** Get retry after time in milliseconds */
595
long getRetryAfter();
596
597
/** Get rate limit bucket */
598
String getScope();
599
600
/** Check if rate limit is global */
601
boolean isGlobal();
602
}
603
```