From f4e172eec26de624b6736b68679b63574c39fc7e Mon Sep 17 00:00:00 2001 From: ochen1 Date: Sun, 9 Apr 2023 12:38:13 -0600 Subject: Add PATCH /guilds/#guild_id/roles/#role_id/member-ids API --- .../guilds/#guild_id/roles/#role_id/member-ids.ts | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts (limited to 'src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts') diff --git a/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts b/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts new file mode 100644 index 00000000..6353e1f6 --- /dev/null +++ b/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts @@ -0,0 +1,38 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { Router, Request, Response } from "express"; +import { Member } from "@spacebar/util"; +import { route } from "@spacebar/api"; + +const router = Router(); + +router.get("/", route({}), async (req: Request, res: Response) => { + const { guild_id, role_id } = req.params; + await Member.IsInGuildOrFail(req.user_id, guild_id); + const members = await Member.find({ + select: ["id"], + relations: ["roles"], + }); + const member_ids = members.filter((member) => { + return member.roles.map((role) => role.id).includes(role_id); + }).map((member) => member.id); + return res.json(member_ids); +}); + +export default router; -- cgit 1.4.1 From b91fca6d745edbc438a468bcb1826372029869f5 Mon Sep 17 00:00:00 2001 From: Madeline <46743919+MaddyUnderStars@users.noreply.github.com> Date: Tue, 11 Apr 2023 12:28:16 +1000 Subject: prettier --- .../guilds/#guild_id/roles/#role_id/member-ids.ts | 22 +++++---- .../guilds/#guild_id/roles/#role_id/members.ts | 56 ++++++++++++---------- 2 files changed, 43 insertions(+), 35 deletions(-) (limited to 'src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts') diff --git a/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts b/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts index 6353e1f6..e0e7bd20 100644 --- a/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts +++ b/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts @@ -23,16 +23,18 @@ import { route } from "@spacebar/api"; const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { - const { guild_id, role_id } = req.params; - await Member.IsInGuildOrFail(req.user_id, guild_id); - const members = await Member.find({ - select: ["id"], - relations: ["roles"], - }); - const member_ids = members.filter((member) => { - return member.roles.map((role) => role.id).includes(role_id); - }).map((member) => member.id); - return res.json(member_ids); + const { guild_id, role_id } = req.params; + await Member.IsInGuildOrFail(req.user_id, guild_id); + const members = await Member.find({ + select: ["id"], + relations: ["roles"], + }); + const member_ids = members + .filter((member) => { + return member.roles.map((role) => role.id).includes(role_id); + }) + .map((member) => member.id); + return res.json(member_ids); }); export default router; diff --git a/src/api/routes/guilds/#guild_id/roles/#role_id/members.ts b/src/api/routes/guilds/#guild_id/roles/#role_id/members.ts index 26359a69..a1238382 100644 --- a/src/api/routes/guilds/#guild_id/roles/#role_id/members.ts +++ b/src/api/routes/guilds/#guild_id/roles/#role_id/members.ts @@ -23,31 +23,37 @@ import { route } from "@spacebar/api"; const router = Router(); router.patch( - "/", - route({ permission: "MANAGE_ROLES" }), - async (req: Request, res: Response) => { - // Payload is JSON containing a list of member_ids, the new list of members to have the role - const { guild_id, role_id } = req.params; - const { member_ids } = req.body; - await Member.IsInGuildOrFail(req.user_id, guild_id); - const members = await Member.find({ - where: { guild_id }, - relations: ["roles"], - }); - const members_to_add = members.filter((member) => { - return member_ids.includes(member.id) && !member.roles.map((role) => role.id).includes(role_id); - }); - const members_to_remove = members.filter((member) => { - return !member_ids.includes(member.id) && member.roles.map((role) => role.id).includes(role_id); - }); - for (const member of members_to_add) { - Member.addRole(member.id, guild_id, role_id); - } - for (const member of members_to_remove) { - Member.removeRole(member.id, guild_id, role_id); - } - res.sendStatus(204); - } + "/", + route({ permission: "MANAGE_ROLES" }), + async (req: Request, res: Response) => { + // Payload is JSON containing a list of member_ids, the new list of members to have the role + const { guild_id, role_id } = req.params; + const { member_ids } = req.body; + await Member.IsInGuildOrFail(req.user_id, guild_id); + const members = await Member.find({ + where: { guild_id }, + relations: ["roles"], + }); + const members_to_add = members.filter((member) => { + return ( + member_ids.includes(member.id) && + !member.roles.map((role) => role.id).includes(role_id) + ); + }); + const members_to_remove = members.filter((member) => { + return ( + !member_ids.includes(member.id) && + member.roles.map((role) => role.id).includes(role_id) + ); + }); + for (const member of members_to_add) { + Member.addRole(member.id, guild_id, role_id); + } + for (const member of members_to_remove) { + Member.removeRole(member.id, guild_id, role_id); + } + res.sendStatus(204); + }, ); export default router; -- cgit 1.4.1 From 7a2a41be3ec8af8b155a241cbbc2507082f40eae Mon Sep 17 00:00:00 2001 From: Madeline <46743919+MaddyUnderStars@users.noreply.github.com> Date: Tue, 11 Apr 2023 13:17:51 +1000 Subject: Don't fetch the entire role relation when counting member ids --- .../guilds/#guild_id/roles/#role_id/member-ids.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts') diff --git a/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts b/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts index e0e7bd20..b086193e 100644 --- a/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts +++ b/src/api/routes/guilds/#guild_id/roles/#role_id/member-ids.ts @@ -24,17 +24,19 @@ const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id, role_id } = req.params; - await Member.IsInGuildOrFail(req.user_id, guild_id); + + // TODO: Is this route really not paginated? const members = await Member.find({ select: ["id"], - relations: ["roles"], + where: { + roles: { + id: role_id, + }, + guild_id, + }, }); - const member_ids = members - .filter((member) => { - return member.roles.map((role) => role.id).includes(role_id); - }) - .map((member) => member.id); - return res.json(member_ids); + + return res.json(members.map((x) => x.id)); }); export default router; -- cgit 1.4.1