[Global] Initial progress

This commit is contained in:
Beef 2022-10-18 23:04:55 +01:00
commit 7ec0c3c82d
11 changed files with 581 additions and 0 deletions

45
src/def.d.ts vendored Normal file
View file

@ -0,0 +1,45 @@
import * as _spitroast from "spitroast";
type MetroModules = { [id: number]: any };
// Helper types for API functions
type PropIntellisense<P extends string | symbol> = Record<P, any> & Record<PropertyKey, any>;
type PropsFinder = <T extends string | symbol>(...props: T[]) => PropIntellisense<T>;
type PropsFinderAll = <T extends string | symbol>(...props: T[]) => PropIntellisense<T>[];
type LoggerFunction = (...messages: any[]) => void;
interface Logger {
log: LoggerFunction,
info: LoggerFunction,
warn: LoggerFunction,
error: LoggerFunction,
time: LoggerFunction,
trace: LoggerFunction,
verbose: LoggerFunction,
}
interface VendettaObject {
patcher: {
after: typeof _spitroast.after;
before: typeof _spitroast.before;
instead: typeof _spitroast.instead;
unpatchAll: typeof _spitroast.unpatchAll;
}
metro: {
findByProps: PropsFinder;
findByPropsAll: PropsFinderAll;
findByDisplayName: (name: string, defaultExp: boolean) => any;
findByDisplayNameAll: (name: string, defaultExp: boolean) => any[];
// TODO: Proper typing for common modules
common: Object;
}
logger: Logger;
}
declare global {
interface Window {
[key: PropertyKey]: any;
modules: MetroModules;
vendetta: VendettaObject;
}
}

18
src/index.ts Normal file
View file

@ -0,0 +1,18 @@
import patcher from "@lib/patcher";
import logger from "@lib/logger";
import * as metro from "@metro/filters";
import * as common from "@metro/common";
console.log("Hello from Vendetta!");
try {
window.vendetta = {
patcher: patcher,
metro: { ...metro, common: common },
logger: logger,
};
logger.log("Vendetta is ready!");
} catch (e: Error | any) {
alert(`Vendetta failed to initialize...\n${e.stack || e.toString()}`);
}

7
src/lib/logger.ts Normal file
View file

@ -0,0 +1,7 @@
import { Logger } from "@types";
import { findByProps } from "@metro/filters";
const logModule = findByProps("setLogFn").default;
const logger: Logger = new logModule("Vendetta");
export default logger;

6
src/lib/metro/common.ts Normal file
View file

@ -0,0 +1,6 @@
import { findByProps } from "@metro/filters";
// Discord
export const Constants = findByProps("API_HOST");
export const channels = findByProps("getVoiceChannelId");
export const i18n = findByProps("Messages");

80
src/lib/metro/filters.ts Normal file
View file

@ -0,0 +1,80 @@
import { MetroModules, PropsFinder, PropsFinderAll } from "@types";
// Metro require
declare const __r: (moduleId: number) => any;
let moment: any;
// Function to blacklist a module, preventing it from being searched again
function blacklist(id: number) {
Object.defineProperty(window.modules, id, {
value: window.modules[id],
enumerable: false,
configurable: true,
writable: true
})
}
// Blacklist any "bad-actor" modules
for (const key in window.modules) {
const id = Number(key);
const module = window.modules[id].publicModule.exports;
if (!moment && module && module.isMoment) moment = module;
if (!module || module === window || module["proxygone"] === null) {
blacklist(id);
continue;
}
}
// Get the previous moment locale
const previousLocale = moment?.locale();
// Function to filter through modules
export const filterModules = (modules: MetroModules, single = false) => (filter: (m: any) => boolean) => {
const found = [];
for (const key in modules) {
const id = Number(key);
const module = modules[id].publicModule.exports;
if (!modules[id].isInitialized) try {
__r(id);
// Set moment locale, sort of crappy fix but works I guess
if (previousLocale) moment.locale(previousLocale);
} catch {};
if (!module) {
blacklist(id);
continue;
};
try {
if (module.default && module.__esModule && filter(module.default)) {
if (single) return module.default;
found.push(module.default);
}
if(filter(module)) {
if (single) return module;
else found.push(module);
}
} catch (e: Error | any) {
console.error(`Failed to getModule... ${e.stack || e.toString()}`);
}
}
if (!single) return found;
}
export const modules = window.modules;
export const find = filterModules(modules, true);
export const findAll = filterModules(modules);
const propsFilter = (props: (string | symbol)[]) => (m: any) => props.every((p) => m[p] !== undefined);
const dNameFilter = (name: string, defaultExp: boolean) => (defaultExp ? (m: any) => m.name === name : (m: any) => m?.default?.name === name);
export const findByProps: PropsFinder = (...props) => find(propsFilter(props));
export const findByPropsAll: PropsFinderAll = (...props) => findAll(propsFilter(props));
export const findByDisplayName = (name: string, defaultExp = true) => find(dNameFilter(name, defaultExp));
export const findByDisplayNameAll = (name: string, defaultExp = true) => findAll(dNameFilter(name, defaultExp));

4
src/lib/patcher.ts Normal file
View file

@ -0,0 +1,4 @@
import * as _spitroast from "spitroast";
export * from "spitroast";
export default { ..._spitroast };