Support bulk queuing with queueAll in /music/{guildId}/queue
Extended the queue endpoint to allow bulk queuing of all search candidates by specifying `queueAll=true`. Updated relevant request and response DTOs, OpenAPI documentation, and endpoint logic to handle bulk queuing while maintaining input validation for individual candidates.
This commit is contained in:
1 parent
27aa0a1d55
commit
9cd1317659
3 files changed
+40
-11
No files matched your search
@@ -275,7 +275,7 @@ public final class MusicRoutes {
|
||||
@OpenApi(
|
||||
path = "/music/{guildId}/queue",
|
||||
methods = HttpMethod.POST,
|
||||
summary = "Queue a previously returned search candidate by passing the searchId/index returned by /music/{guildId}/search; the bot must already be connected to a voice channel in this guild",
|
||||
summary = "Queue a previously returned search candidate by passing the searchId/index returned by /music/{guildId}/search, or queue every candidate at once by passing searchId with queueAll=true; the bot must already be connected to a voice channel in this guild",
|
||||
tags = {"Music"},
|
||||
pathParams = @OpenApiParam(name = "guildId", description = "The Discord guild id"),
|
||||
requestBody = @OpenApiRequestBody(content = @OpenApiContent(from = QueueRequest.class)),
|
||||
@@ -344,9 +344,10 @@ public final class MusicRoutes {
|
||||
*/
|
||||
private static void playSelect(Guild guild, MusicManager manager, QueueRequest body, String userId, Context ctx) {
|
||||
String searchId = body.searchId();
|
||||
boolean queueAll = Boolean.TRUE.equals(body.queueAll());
|
||||
Integer index = body.index();
|
||||
if (index == null) {
|
||||
throw new BadRequestResponse("index is required when searchId is provided");
|
||||
if (!queueAll && index == null) {
|
||||
throw new BadRequestResponse("index is required when searchId is provided unless queueAll is true");
|
||||
}
|
||||
|
||||
List<Track> candidates = PendingSearchResults.consume(searchId, guild.getId());
|
||||
@@ -354,7 +355,7 @@ public final class MusicRoutes {
|
||||
throw new NotFoundResponse("Unknown or expired searchId");
|
||||
}
|
||||
|
||||
if (index < 0 || index >= candidates.size()) {
|
||||
if (!queueAll && (index < 0 || index >= candidates.size())) {
|
||||
throw new BadRequestResponse("index is out of range");
|
||||
}
|
||||
|
||||
@@ -362,6 +363,16 @@ public final class MusicRoutes {
|
||||
throw new BadRequestResponse("The bot isn't connected to a voice channel in this guild");
|
||||
}
|
||||
|
||||
if (queueAll) {
|
||||
ctx.future(() -> resolveMember(guild, userId)
|
||||
.thenApply(member -> {
|
||||
candidates.forEach(candidate -> manager.getQueueManager().queue(candidate, member));
|
||||
ctx.json(queuedAllBody(candidates, manager.getQueueSize()));
|
||||
return null;
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
Track track = candidates.get(index);
|
||||
|
||||
ctx.future(() -> resolveMember(guild, userId)
|
||||
@@ -444,6 +455,18 @@ public final class MusicRoutes {
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a JSON-friendly body for a batch of tracks that were just queued via {@code
|
||||
* queueAll}.
|
||||
*/
|
||||
private static Map<String, Object> queuedAllBody(List<Track> tracks, int queueSize) {
|
||||
Map<String, Object> body = new LinkedHashMap<>();
|
||||
body.put("status", "queued_all");
|
||||
body.put("tracks", tracks.stream().map(MusicRoutes::trackSummary).toList());
|
||||
body.put("queue_position", queueSize);
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link MusicManager} for the guild path parameter, creating it on first use.
|
||||
*/
|
||||
|
||||
@@ -11,11 +11,15 @@ package me.bobert.netneutrality.http.server.dto;
|
||||
*
|
||||
* @param userId the Discord user id to credit as the requester
|
||||
* @param searchId a search id previously returned by {@code /music/{guildId}/search}
|
||||
* @param index the index of the candidate to queue within the {@code searchId}'s results
|
||||
* @param index the index of the candidate to queue within the {@code searchId}'s results;
|
||||
* ignored when {@code queueAll} is {@code true}
|
||||
* @param queueAll when {@code true}, queues every candidate of the {@code searchId}'s results
|
||||
* instead of a single {@code index}
|
||||
*/
|
||||
public record QueueRequest(
|
||||
String userId,
|
||||
String searchId,
|
||||
Integer index
|
||||
Integer index,
|
||||
Boolean queueAll
|
||||
) {
|
||||
}
|
||||
@@ -14,11 +14,13 @@ import java.util.List;
|
||||
*
|
||||
* <p>Nothing is ever queued directly by {@code /music/{guildId}/search}: every resolved query is
|
||||
* stashed as a pending candidate, to be confirmed via a follow-up {@code /music/{guildId}/queue}
|
||||
* call carrying {@code searchId}/{@code index}. Fields are nullable since only a subset is populated depending
|
||||
* on {@code status}: {@code queued} fills {@code track}/{@code queue_position} (confirmed
|
||||
* selection), {@code pending_track} fills {@code search_id}/{@code search_id_ttl_seconds}/{@code track}, {@code
|
||||
* pending_playlist} fills {@code search_id}/{@code search_id_ttl_seconds}/{@code tracks}/{@code truncated}, and
|
||||
* {@code pending_search} fills {@code search_id}/{@code search_id_ttl_seconds}/{@code candidates}.
|
||||
* call carrying {@code searchId}/{@code index} (or {@code queueAll}). Fields are nullable since only a subset is
|
||||
* populated depending on {@code status}: {@code queued} fills {@code track}/{@code queue_position} (confirmed
|
||||
* selection), {@code queued_all} fills {@code tracks}/{@code queue_position} (confirmed bulk selection; {@code
|
||||
* queue_position} is the resulting queue size), {@code pending_track} fills {@code search_id}/{@code
|
||||
* search_id_ttl_seconds}/{@code track}, {@code pending_playlist} fills {@code search_id}/{@code
|
||||
* search_id_ttl_seconds}/{@code tracks}/{@code truncated}, and {@code pending_search} fills {@code search_id}/{@code
|
||||
* search_id_ttl_seconds}/{@code candidates}.
|
||||
* {@code search_id_ttl_seconds} indicates how many seconds remain before the {@code search_id} expires.
|
||||
*/
|
||||
public record QueueResponse(
|
||||
|
||||
Reference in new issue
Block a user