From cb36cf5706b68e28aa5857e21269ca9f81c1634e Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Thu, 31 Jul 2025 16:31:33 -0400 Subject: [PATCH] fix Plugins broken by recent Discord changes (#3569) Co-authored-by: Vendicated --- .../src/stores/GuildRoleStore.d.ts | 5 +++-- src/plugins/ircColors/index.ts | 4 ++-- .../components/RolesAndUsersPermissions.tsx | 2 +- .../components/UserPermissions.tsx | 4 ++-- src/plugins/permissionsViewer/index.tsx | 6 +++--- src/plugins/permissionsViewer/utils.ts | 13 ++++++------- src/plugins/serverInfo/GuildInfoModal.tsx | 2 +- src/plugins/showHiddenChannels/index.tsx | 6 +++--- src/plugins/showHiddenThings/index.ts | 17 ++++++++++++++--- src/plugins/typingIndicator/index.tsx | 2 +- src/webpack/common/stores.ts | 7 ++----- 11 files changed, 38 insertions(+), 30 deletions(-) diff --git a/packages/discord-types/src/stores/GuildRoleStore.d.ts b/packages/discord-types/src/stores/GuildRoleStore.d.ts index bf0d4042..faf586a0 100644 --- a/packages/discord-types/src/stores/GuildRoleStore.d.ts +++ b/packages/discord-types/src/stores/GuildRoleStore.d.ts @@ -1,7 +1,8 @@ import { FluxStore, Role } from ".."; +// TODO: add the rest of the methods for GuildRoleStore export class GuildRoleStore extends FluxStore { getRole(guildId: string, roleId: string): Role; - getRoles(guildId: string): Record; - getAllGuildRoles(): Record>; + getSortedRoles(guildId: string): Role[]; + getRolesSnapshot(guildId: string): Record; } diff --git a/src/plugins/ircColors/index.ts b/src/plugins/ircColors/index.ts index b6f18572..ce007a57 100644 --- a/src/plugins/ircColors/index.ts +++ b/src/plugins/ircColors/index.ts @@ -74,8 +74,8 @@ export default definePlugin({ { find: "#{intl::GUILD_OWNER}),children:", replacement: { - match: /(?<=roleName:\i,)color:/, - replace: "color:$self.calculateNameColorForListContext(arguments[0]),originalColor:" + match: /(?<=roleName:\i,)(colorString:)/, + replace: "$1$self.calculateNameColorForListContext(arguments[0]),originalColor:" }, predicate: () => settings.store.memberListColors } diff --git a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx index 28beabe1..608aa74f 100644 --- a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx +++ b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx @@ -84,7 +84,7 @@ function RolesAndUsersPermissionsComponent({ permissions, guild, modalProps, hea const [selectedItemIndex, selectItem] = useState(0); const selectedItem = permissions[selectedItemIndex]; - const roles = GuildRoleStore.getRoles(guild.id); + const roles = GuildRoleStore.getRolesSnapshot(guild.id); return ( { const userPermissions: UserPermissions = []; - const userRoles = getSortedRoles(guild, guildMember); + const userRoles = getSortedRolesForMember(guild, guildMember); const rolePermissions: Array = userRoles.map(role => ({ type: PermissionType.Role, diff --git a/src/plugins/permissionsViewer/index.tsx b/src/plugins/permissionsViewer/index.tsx index ed2471fb..1f96e66e 100644 --- a/src/plugins/permissionsViewer/index.tsx +++ b/src/plugins/permissionsViewer/index.tsx @@ -31,7 +31,7 @@ import { Button, ChannelStore, Dialog, GuildMemberStore, GuildRoleStore, GuildSt import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "./components/RolesAndUsersPermissions"; import UserPermissions from "./components/UserPermissions"; -import { getSortedRoles, sortPermissionOverwrites } from "./utils"; +import { getSortedRolesForMember, sortPermissionOverwrites } from "./utils"; const PopoutClasses = findByPropsLazy("container", "scroller", "list"); const RoleButtonClasses = findByPropsLazy("button", "buttonInner", "icon", "banner"); @@ -73,7 +73,7 @@ function MenuItem(guildId: string, id?: string, type?: MenuItemParentType) { .with(MenuItemParentType.User, () => { const member = GuildMemberStore.getMember(guildId, id!)!; - const permissions: RoleOrUserPermission[] = getSortedRoles(guild, member) + const permissions: RoleOrUserPermission[] = getSortedRolesForMember(guild, member) .map(role => ({ type: PermissionType.Role, ...role @@ -107,7 +107,7 @@ function MenuItem(guildId: string, id?: string, type?: MenuItemParentType) { }; }) .otherwise(() => { - const permissions = Object.values(GuildRoleStore.getRoles(guild.id)).map(role => ({ + const permissions = GuildRoleStore.getSortedRoles(guild.id).map(role => ({ type: PermissionType.Role, ...role })); diff --git a/src/plugins/permissionsViewer/utils.ts b/src/plugins/permissionsViewer/utils.ts index 022dca6e..27e7494b 100644 --- a/src/plugins/permissionsViewer/utils.ts +++ b/src/plugins/permissionsViewer/utils.ts @@ -28,12 +28,11 @@ export const { getGuildPermissionSpecMap } = findByPropsLazy("getGuildPermission export const cl = classNameFactory("vc-permviewer-"); -export function getSortedRoles({ id }: Guild, member: GuildMember) { - const roles = GuildRoleStore.getRoles(id); - - return [...member.roles, id] - .map(id => roles[id]) - .sort((a, b) => b.position - a.position); +export function getSortedRolesForMember({ id: guildId }: Guild, member: GuildMember) { + // the guild id is the @everyone role + return GuildRoleStore + .getSortedRoles(guildId) + .filter(role => role.id === guildId || member.roles.includes(role.id)); } export function sortUserRoles(roles: Role[]) { @@ -48,7 +47,7 @@ export function sortUserRoles(roles: Role[]) { } export function sortPermissionOverwrites(overwrites: T[], guildId: string) { - const roles = GuildRoleStore.getRoles(guildId); + const roles = GuildRoleStore.getRolesSnapshot(guildId); return overwrites.sort((a, b) => { if (a.type !== PermissionType.Role || b.type !== PermissionType.Role) return 0; diff --git a/src/plugins/serverInfo/GuildInfoModal.tsx b/src/plugins/serverInfo/GuildInfoModal.tsx index 2fa687e8..ac57e976 100644 --- a/src/plugins/serverInfo/GuildInfoModal.tsx +++ b/src/plugins/serverInfo/GuildInfoModal.tsx @@ -200,7 +200,7 @@ function ServerInfoTab({ guild }: GuildProps) { "Verification Level": ["None", "Low", "Medium", "High", "Highest"][guild.verificationLevel] || "?", "Server Boosts": `${guild.premiumSubscriberCount ?? 0} (Level ${guild.premiumTier ?? 0})`, "Channels": GuildChannelStore.getChannels(guild.id)?.count - 1 || "?", // - null category - "Roles": Object.keys(GuildRoleStore.getRoles(guild.id)).length - 1, // - @everyone + "Roles": GuildRoleStore.getSortedRoles(guild.id).length - 1, // - @everyone }; return ( diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index a0ef38a6..d582c8c7 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -178,7 +178,7 @@ export default definePlugin({ }, // Add the hidden eye icon if the channel is hidden { - match: /\.name,{.{0,140}\.children.+?:null(?<=,channel:(\i).+?)/, + match: /\.Children\.count.+?:null(?<=,channel:(\i).+?)/, replace: (m, channel) => `${m},$self.isHiddenChannel(${channel})?$self.HiddenChannelIcon():null` }, // Make voice channels also appear as muted if they are muted @@ -302,8 +302,8 @@ export default definePlugin({ }, { // Include the @everyone role in the allowed roles list for Hidden Channels - match: /sortBy.{0,30}?\.filter\(\i=>(?<=channel:(\i).+?)/, - replace: (m, channel) => `${m}$self.isHiddenChannel(${channel})?true:` + match: /getSortedRoles.+?\.filter\(\i=>(?=!)/, + replace: m => `${m}$self.isHiddenChannel(arguments[0].channel)?true:` }, { // If the @everyone role has the required permissions, make the array only contain it diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index d80691fe..96ebf169 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -18,7 +18,9 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; +import { Logger } from "@utils/Logger"; import definePlugin, { OptionType, PluginSettingDef } from "@utils/types"; +import { GuildMember, Role } from "@vencord/discord-types"; const opt = (description: string) => ({ type: OptionType.BOOLEAN, @@ -70,8 +72,8 @@ export default definePlugin({ find: "#{intl::GUILD_MEMBER_MOD_VIEW_PERMISSION_GRANTED_BY_ARIA_LABEL}),allowOverflow:", predicate: () => settings.store.showModView, replacement: { - match: /(role:)\i(?=,guildId.{0,100}role:(\i\[))/, - replace: "$1$2arguments[0].member.highestRoleId]", + match: /(role:)\i(?<=\i\.roles,\i\.highestRoleId,(\i)\].+)/, + replace: "$1$self.findHighestRole(arguments[0],$2)", } }, // allows you to open mod view on yourself @@ -83,5 +85,14 @@ export default definePlugin({ replace: "false" } } - ] + ], + + findHighestRole({ member }: { member: GuildMember; }, roles: Role[]): Role | undefined { + try { + return roles.find(role => role.id === member.highestRoleId); + } catch (e) { + new Logger("ShowHiddenThings").error("Failed to find highest role", e); + return undefined; + } + } }); diff --git a/src/plugins/typingIndicator/index.tsx b/src/plugins/typingIndicator/index.tsx index 29cc3c21..0a0cd53a 100644 --- a/src/plugins/typingIndicator/index.tsx +++ b/src/plugins/typingIndicator/index.tsx @@ -173,7 +173,7 @@ export default definePlugin({ { find: "UNREAD_IMPORTANT:", replacement: { - match: /\.name,{.{0,140}\.children.+?:null(?<=,channel:(\i).+?)/, + match: /\.Children\.count.+?:null(?<=,channel:(\i).+?)/, replace: "$&,$self.TypingIndicator($1.id,$1.getGuildId())" } }, diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 4165af8e..71abd729 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -17,7 +17,7 @@ */ import * as t from "@vencord/discord-types"; -import { findByCodeLazy, findByPropsLazy, waitFor } from "@webpack"; +import { findByCodeLazy, findByPropsLazy } from "@webpack"; import { waitForStore } from "./internal"; @@ -71,6 +71,7 @@ waitForStore("PermissionStore", m => PermissionStore = m); waitForStore("PresenceStore", m => PresenceStore = m); waitForStore("ReadStateStore", m => ReadStateStore = m); waitForStore("GuildChannelStore", m => GuildChannelStore = m); +waitForStore("GuildRoleStore", m => GuildRoleStore = m); waitForStore("MessageStore", m => MessageStore = m); waitForStore("WindowStore", m => WindowStore = m); waitForStore("EmojiStore", m => EmojiStore = m); @@ -79,7 +80,3 @@ waitForStore("ThemeStore", m => { // Importing this directly can easily cause circular imports. For this reason, use a non import access here. Vencord.QuickCss.initQuickCssThemeStore(); }); - -// GuildRoleStore is new, this code is for stable + canary compatibility -// TODO: Change to waitForStore once GuildRoleStore is on stable -waitFor(["getRole", "getRoles"], m => GuildRoleStore = m);