diff --git a/src/core/plugins/quickInstall/url.tsx b/src/core/plugins/quickInstall/url.tsx index 09089d3..24a63c4 100644 --- a/src/core/plugins/quickInstall/url.tsx +++ b/src/core/plugins/quickInstall/url.tsx @@ -7,12 +7,12 @@ import { installTheme } from "@lib/managers/themes"; import { PROXY_PREFIX, THEMES_CHANNEL_ID } from "@lib/utils/constants"; import { channels, url } from "@metro/common"; import { byMutableProp } from "@metro/filters"; -import { find } from "@metro/finders"; +import { findExports } from "@metro/finders"; import { findByProps } from "@metro/utils"; import { showConfirmationAlert } from "@ui/alerts"; import { showToast } from "@ui/toasts"; -const showSimpleActionSheet = find(byMutableProp("showSimpleActionSheet")); +const showSimpleActionSheet = findExports(byMutableProp("showSimpleActionSheet")); const handleClick = findByProps("handleClick"); const { openURL } = url; const { getChannelId } = channels; diff --git a/src/core/vendettaObject.ts b/src/core/vendettaObject.ts index 3eb3dd0..cc2799e 100644 --- a/src/core/vendettaObject.ts +++ b/src/core/vendettaObject.ts @@ -29,10 +29,10 @@ export const initVendettaObject = (): any => { metro: { modules: window.modules, find: (filter: (m: any) => boolean) => { - return metro.find(metro.createSimpleFilter(filter, SparkMD5.hash(new Error().stack!))); + return metro.findExports(metro.createSimpleFilter(filter, SparkMD5.hash(new Error().stack!))); }, findAll: (filter: (m: any) => boolean) => { - return metro.findAll(metro.createSimpleFilter(filter, SparkMD5.hash(new Error().stack!))); + return metro.findAllExports(metro.createSimpleFilter(filter, SparkMD5.hash(new Error().stack!))); }, findByProps: (...props: any) => { // Decor fix hack diff --git a/src/lib/managers/themes.ts b/src/lib/managers/themes.ts index 56a6ef2..d476c31 100644 --- a/src/lib/managers/themes.ts +++ b/src/lib/managers/themes.ts @@ -11,7 +11,7 @@ import { findInReactTree, safeFetch } from "@lib/utils"; import { Author } from "@lib/utils/types"; import { chroma } from "@metro/common"; import { byMutableProp } from "@metro/filters"; -import { find } from "@metro/finders"; +import { findExports } from "@metro/finders"; import { findByName, findByProps, findByStoreName } from "@metro/utils"; import { ImageBackground, Platform, processColor } from "react-native"; @@ -251,7 +251,7 @@ function isDiscordTheme(name: string) { } function patchColor() { - const isThemeModule = find(byMutableProp("isThemeDark")); + const isThemeModule = findExports(byMutableProp("isThemeDark")); const callback = ([theme]: any[]) => theme === vdKey ? [vdThemeFallback] : void 0; Object.keys(color.RawColor).forEach(k => { diff --git a/src/lib/ui/components/discord/Redesign.tsx b/src/lib/ui/components/discord/Redesign.tsx index 7ba1fee..4cef9d4 100644 --- a/src/lib/ui/components/discord/Redesign.tsx +++ b/src/lib/ui/components/discord/Redesign.tsx @@ -1,4 +1,4 @@ -import { find } from "@metro/finders"; +import { findExports } from "@metro/finders"; import { createFilterDefinition, findByProps } from "@metro/utils"; import { RedesignModuleKeys } from "@ui/types"; import { useEffect } from "react"; @@ -9,7 +9,7 @@ const bySingularProp = createFilterDefinition<[string]>( prop => `bunny.ui.bySingularProp(${prop})` ); -const findSingular = (prop: string) => find(bySingularProp(prop))?.[prop]; +const findSingular = (prop: string) => findExports(bySingularProp(prop))?.[prop]; export const Redesign = findByProps("TableRow") as Record; diff --git a/src/metro/common/index.ts b/src/metro/common/index.ts index 67fb9ae..f05357b 100644 --- a/src/metro/common/index.ts +++ b/src/metro/common/index.ts @@ -1,4 +1,4 @@ -import { find } from "@metro/finders"; +import { findExports } from "@metro/finders"; import { Dispatcher } from "@metro/types"; import { createSimpleFilter, findByProps } from "@metro/utils"; @@ -12,7 +12,7 @@ export const assets = findByProps("registerAsset"); export const invites = findByProps("acceptInviteAndTransitionToInviteChannel"); export const commands = findByProps("getBuiltInCommands"); export const navigation = findByProps("pushLazy"); -export const toasts = find(createSimpleFilter( +export const toasts = findExports(createSimpleFilter( m => m.open && m.close && !m.startDrag && !m.init && !m.openReplay && !m.setAlwaysOnTop && !m.setAccountFlag, "bunny.metro.common.toasts" )); diff --git a/src/metro/finders.ts b/src/metro/finders.ts index a45f8cc..3358946 100644 --- a/src/metro/finders.ts +++ b/src/metro/finders.ts @@ -1,41 +1,62 @@ import { registerModuleFindCacheId, registerModuleFindFinished } from "./caches"; -import { getModules } from "./modules"; +import { getModules, requireModule } from "./modules"; import { FilterFn } from "./utils"; function testExports(moduleExports: any, moduleId: number, filter: FilterFn) { if (moduleExports.default && moduleExports.__esModule && filter(moduleExports.default, moduleId)) - return moduleExports.default; + return [moduleExports.default, true]; if (filter(moduleExports, moduleId)) - return moduleExports; + return [moduleExports, false]; + + return []; +} + +/** + * Returns the [id, defaultExports] of the first module where filter returns truthy, and undefined otherwise. + * @param filter find calls filter once for each enumerable module's exports until it finds one where filter returns a thruthy value. + */ +export function findModule(filter: FilterFn) { + for (const [id, moduleExports] of getModules(filter.serialized, false)) { + const [testedExports, defaultExp] = testExports(moduleExports, id, filter); + if (testedExports !== undefined) { + registerModuleFindCacheId(filter.serialized, id, false); + return [id, defaultExp]; + } + } + + registerModuleFindFinished(filter.serialized); + return []; +} + +/** + * Returns the id of the first module where filter returns truthy, and undefined otherwise. + * @param filter find calls filter once for each enumerable module's exports until it finds one where filter returns a thruthy value. + */ +export function findModuleId(filter: FilterFn) { + return findModule(filter)?.[0]; } /** * Returns the exports of the first module where filter returns truthy, and undefined otherwise. * @param filter find calls filter once for each enumerable module's exports until it finds one where filter returns a thruthy value. */ -export function find(filter: FilterFn) { - for (const [id, moduleExports] of getModules(filter.serialized, false)) { - const testedExports = testExports(moduleExports, id, filter); - if (testedExports !== undefined) { - registerModuleFindCacheId(filter.serialized, id, false); - return testedExports; - } - } - - registerModuleFindFinished(filter.serialized); +export function findExports(filter: FilterFn) { + const [id, defaultExp] = findModule(filter); + if (defaultExp == null) return; + return defaultExp ? requireModule(id).default : requireModule(id); } /** - * Returns the exports of all modules where filter returns truthy. + * Returns the [id, defaultExports] of all modules where filter returns truthy. * @param filter findAll calls filter once for each enumerable module's exports, adding the exports to the returned array when filter returns a thruthy value. */ -export function findAll(filter: FilterFn) { - const foundExports: any[] = []; +export function findAllModule(filter: FilterFn) { + const foundExports: [id: number, defaultExp: boolean][] = []; for (const [id, moduleExports] of getModules(filter.serialized, true)) { - const testedExports = testExports(moduleExports, id, filter); + const [testedExports, defaultExp] = testExports(moduleExports, id, filter); if (testedExports !== undefined) { - foundExports.push(testedExports); + foundExports.push([id, defaultExp]); registerModuleFindCacheId(filter.serialized, id, true); } } @@ -43,3 +64,23 @@ export function findAll(filter: FilterFn) { registerModuleFindFinished(filter.serialized); return foundExports; } + +/** + * Returns the ids of all modules where filter returns truthy. + * @param filter findAll calls filter once for each enumerable module's exports, adding the exports to the returned array when filter returns a thruthy value. + */ +export function findAllModuleId(filter: FilterFn) { + return findAllModule(filter).map(e => e[0]); +} + +/** + * Returns the ids of all exports where filter returns truthy. + * @param filter findAll calls filter once for each enumerable module's exports, adding the exports to the returned array when filter returns a thruthy value. + */ +export function findAllExports(filter: FilterFn) { + return findAllModule(filter).map(e => { + const [id, defaultExp] = e; + if (defaultExp == null) return; + return defaultExp ? requireModule(id).default : requireModule(id); + }); +} diff --git a/src/metro/utils.ts b/src/metro/utils.ts index e9964f4..5793b6a 100644 --- a/src/metro/utils.ts +++ b/src/metro/utils.ts @@ -1,5 +1,5 @@ import { byDisplayName, byFilePath, byName, byProps, byStoreName, byTypeName } from "./filters"; -import { find, findAll } from "./finders"; +import { findAllExports, findExports } from "./finders"; type ModuleExports = any; type FilterCheckDef = (args: A, m: any, id: number) => boolean; @@ -58,17 +58,17 @@ export function createSimpleFilter( )(); } -export const findByProps = (...props: string[]) => find(byProps(...props)); -export const findByPropsAll = (...props: string[]) => findAll(byProps(...props)); +export const findByProps = (...props: string[]) => findExports(byProps(...props)); +export const findByPropsAll = (...props: string[]) => findAllExports(byProps(...props)); -export const findByName = (name: string, expDefault = true) => find(expDefault ? byName(name) : byName.byDefault(name)); -export const findByNameAll = (name: string, expDefault = true) => findAll(expDefault ? byName(name) : byName.byDefault(name)); +export const findByName = (name: string, expDefault = true) => findExports(expDefault ? byName(name) : byName.byDefault(name)); +export const findByNameAll = (name: string, expDefault = true) => findAllExports(expDefault ? byName(name) : byName.byDefault(name)); -export const findByDisplayName = (name: string, expDefault = true) => find(expDefault ? byDisplayName(name) : byDisplayName.byDefault(name)); -export const findByDisplayNameAll = (name: string, expDefault = true) => findAll(expDefault ? byDisplayName(name) : byDisplayName.byDefault(name)); +export const findByDisplayName = (name: string, expDefault = true) => findExports(expDefault ? byDisplayName(name) : byDisplayName.byDefault(name)); +export const findByDisplayNameAll = (name: string, expDefault = true) => findAllExports(expDefault ? byDisplayName(name) : byDisplayName.byDefault(name)); -export const findByTypeName = (name: string, expDefault = true) => find(expDefault ? byTypeName(name) : byTypeName.byDefault(name)); -export const findByTypeNameAll = (name: string, expDefault = true) => findAll(expDefault ? byTypeName(name) : byTypeName.byDefault(name)); +export const findByTypeName = (name: string, expDefault = true) => findExports(expDefault ? byTypeName(name) : byTypeName.byDefault(name)); +export const findByTypeNameAll = (name: string, expDefault = true) => findAllExports(expDefault ? byTypeName(name) : byTypeName.byDefault(name)); -export const findByStoreName = (name: string) => find(byStoreName(name)); -export const findByFilePath = (path: string) => find(byFilePath(path)); +export const findByStoreName = (name: string) => findExports(byStoreName(name)); +export const findByFilePath = (path: string) => findExports(byFilePath(path));