Add new endpoints for queue management and playback control
Introduced `/music/{guildId}/queue` DELETE, `/music/{guildId}/leave`, and `/music/{guildId}/shuffle` endpoints for enhanced queue and playback operations. Added corresponding DTOs (`DeleteQueueResponse`, `LeaveResponse`, `ShuffleResponse`) and updated `MusicRoutes` with OpenAPI documentation. These changes improve queue handling, bot disconnection, and randomization functionality for guilds.
This commit is contained in:
1 parent
44b284fde8
commit
db86c133e6
4 files changed
+139
No files matched your search
@@ -18,8 +18,10 @@ import io.javalin.openapi.OpenApiParam;
|
|||||||
import io.javalin.openapi.OpenApiRequestBody;
|
import io.javalin.openapi.OpenApiRequestBody;
|
||||||
import io.javalin.openapi.OpenApiResponse;
|
import io.javalin.openapi.OpenApiResponse;
|
||||||
import me.bobert.netneutrality.http.server.dto.CommandResultResponse;
|
import me.bobert.netneutrality.http.server.dto.CommandResultResponse;
|
||||||
|
import me.bobert.netneutrality.http.server.dto.DeleteQueueResponse;
|
||||||
import me.bobert.netneutrality.http.server.dto.DjStatusResponse;
|
import me.bobert.netneutrality.http.server.dto.DjStatusResponse;
|
||||||
import me.bobert.netneutrality.http.server.dto.ErrorResponse;
|
import me.bobert.netneutrality.http.server.dto.ErrorResponse;
|
||||||
|
import me.bobert.netneutrality.http.server.dto.LeaveResponse;
|
||||||
import me.bobert.netneutrality.http.server.dto.MusicSourceResponse;
|
import me.bobert.netneutrality.http.server.dto.MusicSourceResponse;
|
||||||
import me.bobert.netneutrality.http.server.dto.MusicStatusResponse;
|
import me.bobert.netneutrality.http.server.dto.MusicStatusResponse;
|
||||||
import me.bobert.netneutrality.http.server.dto.QueueRequest;
|
import me.bobert.netneutrality.http.server.dto.QueueRequest;
|
||||||
@@ -30,6 +32,7 @@ import me.bobert.netneutrality.http.server.dto.ReorderResponse;
|
|||||||
import me.bobert.netneutrality.http.server.dto.SearchRequest;
|
import me.bobert.netneutrality.http.server.dto.SearchRequest;
|
||||||
import me.bobert.netneutrality.http.server.dto.SeekRequest;
|
import me.bobert.netneutrality.http.server.dto.SeekRequest;
|
||||||
import me.bobert.netneutrality.http.server.dto.SeekResponse;
|
import me.bobert.netneutrality.http.server.dto.SeekResponse;
|
||||||
|
import me.bobert.netneutrality.http.server.dto.ShuffleResponse;
|
||||||
import me.bobert.netneutrality.http.server.dto.VolumeRequest;
|
import me.bobert.netneutrality.http.server.dto.VolumeRequest;
|
||||||
import me.bobert.netneutrality.http.server.dto.VolumeResponse;
|
import me.bobert.netneutrality.http.server.dto.VolumeResponse;
|
||||||
import me.bobert.netneutrality.music.MusicManager;
|
import me.bobert.netneutrality.music.MusicManager;
|
||||||
@@ -78,8 +81,11 @@ public final class MusicRoutes {
|
|||||||
routes.post("/music/{guildId}/vote-skip/{userId}", ctx -> voteSkip(jdaSupplier, musicService, ctx));
|
routes.post("/music/{guildId}/vote-skip/{userId}", ctx -> voteSkip(jdaSupplier, musicService, ctx));
|
||||||
routes.get("/music/{guildId}/dj/{userId}", ctx -> dj(jdaSupplier, musicService, ctx));
|
routes.get("/music/{guildId}/dj/{userId}", ctx -> dj(jdaSupplier, musicService, ctx));
|
||||||
routes.post("/music/{guildId}/queue", ctx -> play(jdaSupplier, musicService, ctx));
|
routes.post("/music/{guildId}/queue", ctx -> play(jdaSupplier, musicService, ctx));
|
||||||
|
routes.delete("/music/{guildId}/queue", ctx -> deleteQueue(jdaSupplier, musicService, ctx));
|
||||||
routes.patch("/music/{guildId}/queue/reorder", ctx -> reorder(jdaSupplier, musicService, ctx));
|
routes.patch("/music/{guildId}/queue/reorder", ctx -> reorder(jdaSupplier, musicService, ctx));
|
||||||
routes.post("/music/{guildId}/search", ctx -> search(jdaSupplier, musicService, ctx));
|
routes.post("/music/{guildId}/search", ctx -> search(jdaSupplier, musicService, ctx));
|
||||||
|
routes.post("/music/{guildId}/leave", ctx -> leave(jdaSupplier, musicService, ctx));
|
||||||
|
routes.post("/music/{guildId}/shuffle", ctx -> shuffle(jdaSupplier, musicService, ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
@OpenApi(
|
@OpenApi(
|
||||||
@@ -496,6 +502,81 @@ public final class MusicRoutes {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OpenApi(
|
||||||
|
path = "/music/{guildId}/queue",
|
||||||
|
methods = HttpMethod.DELETE,
|
||||||
|
summary = "Clear the queue, or remove a single track from it when a position is provided",
|
||||||
|
tags = {"Music"},
|
||||||
|
pathParams = @OpenApiParam(name = "guildId", description = "The Discord guild id"),
|
||||||
|
queryParams = @OpenApiParam(name = "position", description = "1-based position of the track to remove (position 1 is the currently playing track); omit to clear the whole queue", required = false),
|
||||||
|
responses = {
|
||||||
|
@OpenApiResponse(status = "200", content = @OpenApiContent(from = DeleteQueueResponse.class)),
|
||||||
|
@OpenApiResponse(status = "400", content = @OpenApiContent(from = ErrorResponse.class)),
|
||||||
|
@OpenApiResponse(status = "404", content = @OpenApiContent(from = ErrorResponse.class))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
private static void deleteQueue(Supplier<JDA> jdaSupplier, MusicService musicService, Context ctx) {
|
||||||
|
MusicManager manager = manager(jdaSupplier, musicService, ctx);
|
||||||
|
String position = ctx.queryParam("position");
|
||||||
|
|
||||||
|
QueueActionResult result;
|
||||||
|
if (position == null || position.isBlank()) {
|
||||||
|
result = manager.getQueueManager().clearQueue();
|
||||||
|
} else {
|
||||||
|
int index;
|
||||||
|
try {
|
||||||
|
index = Integer.parseInt(position);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new BadRequestResponse("position must be an integer");
|
||||||
|
}
|
||||||
|
|
||||||
|
result = manager.getQueueManager().removeFromQueue(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.getStatus() == QueueActionResult.Status.ERROR) {
|
||||||
|
throw new BadRequestResponse(result.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
announce(manager, result.getMessage());
|
||||||
|
ctx.json(resultBodyWithQueue(result, manager));
|
||||||
|
}
|
||||||
|
|
||||||
|
@OpenApi(
|
||||||
|
path = "/music/{guildId}/leave",
|
||||||
|
methods = HttpMethod.POST,
|
||||||
|
summary = "Disconnect the bot from its current voice channel in a guild, stopping playback",
|
||||||
|
tags = {"Music"},
|
||||||
|
pathParams = @OpenApiParam(name = "guildId", description = "The Discord guild id"),
|
||||||
|
responses = {
|
||||||
|
@OpenApiResponse(status = "200", content = @OpenApiContent(from = LeaveResponse.class)),
|
||||||
|
@OpenApiResponse(status = "404", content = @OpenApiContent(from = ErrorResponse.class))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
private static void leave(Supplier<JDA> jdaSupplier, MusicService musicService, Context ctx) {
|
||||||
|
MusicManager manager = manager(jdaSupplier, musicService, ctx);
|
||||||
|
manager.disconnect();
|
||||||
|
announce(manager, "Leaving voice channel");
|
||||||
|
ctx.json(new LeaveResponse("ok", "Leaving voice channel"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@OpenApi(
|
||||||
|
path = "/music/{guildId}/shuffle",
|
||||||
|
methods = HttpMethod.POST,
|
||||||
|
summary = "Shuffle the queue, keeping the currently playing track in place",
|
||||||
|
tags = {"Music"},
|
||||||
|
pathParams = @OpenApiParam(name = "guildId", description = "The Discord guild id"),
|
||||||
|
responses = {
|
||||||
|
@OpenApiResponse(status = "200", content = @OpenApiContent(from = ShuffleResponse.class)),
|
||||||
|
@OpenApiResponse(status = "404", content = @OpenApiContent(from = ErrorResponse.class))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
private static void shuffle(Supplier<JDA> jdaSupplier, MusicService musicService, Context ctx) {
|
||||||
|
MusicManager manager = manager(jdaSupplier, musicService, ctx);
|
||||||
|
QueueActionResult result = manager.getQueueManager().shuffle();
|
||||||
|
announce(manager, result.getMessage());
|
||||||
|
ctx.json(resultBodyWithQueue(result, manager));
|
||||||
|
}
|
||||||
|
|
||||||
@OpenApi(
|
@OpenApi(
|
||||||
path = "/music/{guildId}/queue/reorder",
|
path = "/music/{guildId}/queue/reorder",
|
||||||
methods = HttpMethod.PATCH,
|
methods = HttpMethod.PATCH,
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package me.bobert.netneutrality.http.server.dto;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) anthorob
|
||||||
|
*
|
||||||
|
* https://discord.gg/qUa6zNFZsd
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenAPI schema for the {@code /music/{guildId}/queue} {@code DELETE} response, which extends
|
||||||
|
* the standard {@link CommandResultResponse} with the current queue listing so the caller can
|
||||||
|
* resync its state after clearing the queue or removing a single track from it.
|
||||||
|
*/
|
||||||
|
public record DeleteQueueResponse(
|
||||||
|
String status,
|
||||||
|
String message,
|
||||||
|
List<QueuedTrackResponse> queue
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package me.bobert.netneutrality.http.server.dto;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) anthorob
|
||||||
|
*
|
||||||
|
* https://discord.gg/qUa6zNFZsd
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenAPI schema for the {@code /music/{guildId}/leave} response.
|
||||||
|
*/
|
||||||
|
public record LeaveResponse(
|
||||||
|
String status,
|
||||||
|
String message
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package me.bobert.netneutrality.http.server.dto;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) anthorob
|
||||||
|
*
|
||||||
|
* https://discord.gg/qUa6zNFZsd
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenAPI schema for the {@code /music/{guildId}/shuffle} response, which extends the standard
|
||||||
|
* {@link CommandResultResponse} with the current queue listing so the caller can resync its
|
||||||
|
* state after a shuffle.
|
||||||
|
*/
|
||||||
|
public record ShuffleResponse(
|
||||||
|
String status,
|
||||||
|
String message,
|
||||||
|
List<QueuedTrackResponse> queue
|
||||||
|
) {
|
||||||
|
}
|
||||||
Reference in new issue
Block a user