diff --git a/src/plugins/roleMembers/README.md b/src/plugins/roleMembers/README.md new file mode 100644 index 000000000..7b114e5e0 --- /dev/null +++ b/src/plugins/roleMembers/README.md @@ -0,0 +1,32 @@ +# RoleMembersViewer + +A Vencord plugin that displays all members with a specific role when you right-click on a role in a user profile or when a message mentions roles. + +The plugin fetches as many members as possible, including offline ones, and organizes them in a nested submenu for a clear and efficient view. + +## Features + +- **Dev Context:** Right-click on a role in a user profile to see a list of all members with that role. +- **Message Context:** Right-click on a message containing role mentions to display a submenu with all the roles and their corresponding members. This also works if a message has multiple role mentions! +- **Automatic Member Fetching:** Uses FluxDispatcher to fetch as many members as possible, efficently. +- **Live Updates:** The plugin takes advantage of GuildMemberStore updates so that the list can reflect changes + +## Examples + +### Dev Context Menu + + + +### Message Context Menu + + + +## Installation + +- You can find installation instructions [here](https://docs.vencord.dev/installing/custom-plugins/) + +## Usage + +- **In User Profiles:** Right-click on a role to see the "View Members" submenu populated with all users having that role. +- **In Messages:** Right-click on a message with role mentions to open a submenu where you can view users for each mentioned role. Upon right-clicking on a message with multiple, it will display a submenu with all the roles that have been mentioned, and then you're free to view the members of each one! +- **In both scenarios**, you can click a user in the submenu to pop up their profile! diff --git a/src/plugins/roleMembers/index.tsx b/src/plugins/roleMembers/index.tsx new file mode 100644 index 000000000..d538ec89f --- /dev/null +++ b/src/plugins/roleMembers/index.tsx @@ -0,0 +1,144 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; +import { + FluxDispatcher, + GuildMemberStore, + GuildStore, + Menu, + SelectedChannelStore, + SelectedGuildStore, + UserProfileActions, + UserStore +} from "@webpack/common"; + +function fetchMembersWithRole(guildId: string, roleId: string, memberCount: number) { + const guildMembers = GuildMemberStore.getMembers(guildId); + if (Object.keys(guildMembers).length < memberCount) { + const chunk = 100; + const requestCount = Math.ceil(memberCount / chunk); + for (let i = 0; i < requestCount; i++) { + FluxDispatcher.dispatch({ + type: "GUILD_MEMBERS_REQUEST", + guildId, + userIds: [], + query: "", + limit: chunk, + withPresences: true, + notifyOnLimit: true + }); + } + } + const updatedGuildMembers = GuildMemberStore.getMembers(guildId); + return Object.values(updatedGuildMembers) + .filter(m => m.roles.includes(roleId)) + .map(m => ({ + ...m, + user: UserStore.getUser(m.userId) + })) + .sort((a, b) => a.user.username.localeCompare(b.user.username)); +} + +export default definePlugin({ + name: "RoleMembersViewer", + description: "Shows members with a role when right clicking roles in user profiles or role mentions in messages", + authors: [Devs.okiso], + + contextMenus: { + "dev-context"(children, { id }: { id: string; }) { + const guild = GuildStore.getGuild(SelectedGuildStore.getGuildId()); + if (!guild) return; + + const role = GuildStore.getRole(guild.id, id); + if (!role) return; + + const guildId = guild.id; + const membersWithRole = fetchMembersWithRole(guildId, id, role.memberCount); + + const memberItems = membersWithRole.map(member => ( +