From e0ec43813d5b4cfa2f536a6203be1afd1584b8e0 Mon Sep 17 00:00:00 2001 From: anthorob Date: Fri, 9 Oct 2026 12:43:44 -0400 Subject: [PATCH] Add admin status check endpoint to guild routes Introduced `/guilds/members/{guildId}/{userId}/admin` endpoint to determine if a guild member is an admin. Added `AdminStatusResponse` DTO and documented the new route with OpenAPI annotations. This feature allows for efficient admin status verification with fallback to REST fetch on cache miss. --- .../http/server/GuildRoutes.java | 35 +++++++++++++++++++ .../http/server/dto/AdminStatusResponse.java | 17 +++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/main/java/me/bobert/netneutrality/http/server/dto/AdminStatusResponse.java diff --git a/src/main/java/me/bobert/netneutrality/http/server/GuildRoutes.java b/src/main/java/me/bobert/netneutrality/http/server/GuildRoutes.java index 3edc56a..efa4487 100644 --- a/src/main/java/me/bobert/netneutrality/http/server/GuildRoutes.java +++ b/src/main/java/me/bobert/netneutrality/http/server/GuildRoutes.java @@ -19,6 +19,7 @@ import io.javalin.openapi.OpenApiRequestBody; import io.javalin.openapi.OpenApiResponse; import me.bobert.netneutrality.db.service.GuildService; import me.bobert.netneutrality.db.service.GuildServiceProvider; +import me.bobert.netneutrality.http.server.dto.AdminStatusResponse; import me.bobert.netneutrality.http.server.dto.ChannelSummaryResponse; import me.bobert.netneutrality.http.server.dto.ErrorResponse; import me.bobert.netneutrality.http.server.dto.GuildBooleanUpdateRequest; @@ -31,6 +32,7 @@ import me.bobert.netneutrality.http.server.dto.MemberSummaryResponse; import me.bobert.netneutrality.http.server.dto.OwnerResponse; import me.bobert.netneutrality.http.server.dto.RoleSummaryResponse; import me.bobert.netneutrality.http.server.dto.VoiceChannelSummaryResponse; +import me.bobert.netneutrality.utils.UserFunction; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; @@ -59,6 +61,7 @@ public final class GuildRoutes { routes.get("/guilds/roles/{guildId}", ctx -> roles(jdaSupplier, ctx)); routes.get("/guilds/members/{guildId}/{userId}", ctx -> member(jdaSupplier, ctx)); routes.get("/guilds/members/{guildId}/{userId}/roles", ctx -> memberRoles(jdaSupplier, ctx)); + routes.get("/guilds/members/{guildId}/{userId}/admin", ctx -> memberAdmin(jdaSupplier, ctx)); routes.get("/guilds/voice-channels/{guildId}", ctx -> voiceChannels(jdaSupplier, ctx)); routes.get("/guilds/voice-channels/{guildId}/{channelId}", ctx -> voiceChannel(jdaSupplier, ctx)); routes.get("/guilds/config/{guildId}", ctx -> config(jdaSupplier, guildServices, ctx)); @@ -235,6 +238,38 @@ public final class GuildRoutes { ); } + @OpenApi( + path = "/guilds/members/{guildId}/{userId}/admin", + methods = HttpMethod.GET, + summary = "Check whether a guild member is an admin of the guild, falling back to a REST fetch on a member cache miss", + tags = {"Guilds"}, + pathParams = { + @io.javalin.openapi.OpenApiParam(name = "guildId", description = "The Discord guild id"), + @io.javalin.openapi.OpenApiParam(name = "userId", description = "The Discord user id") + }, + responses = { + @OpenApiResponse(status = "200", content = @OpenApiContent(from = AdminStatusResponse.class)), + @OpenApiResponse(status = "404", content = @OpenApiContent(from = ErrorResponse.class)) + } + ) + private static void memberAdmin(Supplier jdaSupplier, Context ctx) { + Guild guild = guild(jdaSupplier, ctx); + String userId = ctx.pathParam("userId"); + + CacheOrFetch.resolve( + ctx, + () -> guild.getMemberById(userId), + () -> guild.retrieveMemberById(userId), + member -> { + Map summary = new LinkedHashMap<>(); + summary.put("guild_id", guild.getId()); + summary.put("user_id", member.getId()); + summary.put("is_admin", UserFunction.isAdmin(member)); + return summary; + } + ); + } + /** * Builds the {@code /guilds/members/{guildId}/{userId}} response for a resolved member. */ diff --git a/src/main/java/me/bobert/netneutrality/http/server/dto/AdminStatusResponse.java b/src/main/java/me/bobert/netneutrality/http/server/dto/AdminStatusResponse.java new file mode 100644 index 0000000..8732812 --- /dev/null +++ b/src/main/java/me/bobert/netneutrality/http/server/dto/AdminStatusResponse.java @@ -0,0 +1,17 @@ +package me.bobert.netneutrality.http.server.dto; + +/* + * Copyright (c) anthorob + * + * https://discord.gg/qUa6zNFZsd + */ + +/** + * OpenAPI schema for the {@code /guilds/members/{guildId}/{userId}/admin} response. + */ +public record AdminStatusResponse( + String guildId, + String userId, + boolean isAdmin +) { +}