import type { AnyFunction, CommandOptions, ContextMenuTypes, GetButtonItem, GetContextItem, ObjectExports, RepluggedCommand } from "src/types"; import { type ContextMenuProps } from "../coremods/contextMenu"; /** * Code to run before the original function * @param args Arguments passed to the original function * @param self The module the injected function is on * @returns New arguments to pass to the original function, or undefined to leave them unchanged */ export type BeforeCallback = (args: A, self: I) => A | undefined | void; /** * Code to run instead of the original function * @param args Arguments passed to the original function * @param orig The original function * @param self The module the injected function is on * @returns New result to return */ export type InsteadCallback = (args: A, orig: (...args: A) => R, self: I) => R | void; /** * Code to run after the original function * @param args Arguments passed to the original function * @param res Result of the original function * @param self The module the injected function is on * @returns New result to return, or undefined to leave it unchanged */ export type AfterCallback = (args: A, res: R, self: I) => R | undefined | void; /** * Inject code into Discord's webpack modules. * * @example * ``` * import { Injector, webpack } from "replugged"; * * const injector = new Injector(); * * export async function start() { * const typingMod = (await webpack.waitForModule<{ * startTyping: (channelId: string) => void; * }>( * webpack.filters.byProps("startTyping") * )); * * injector.after(typingMod, "startTyping", ([channel]) => { * console.log(`Typing in channel ID ${channel}`); * }); * } * * export function stop() { * injector.uninjectAll(); * } * ``` */ export declare class Injector { #private; /** * Run code before a native module * @param obj Module to inject to * @param funcName Function name on that module to inject * @param cb Code to run * @returns Uninject function */ before, U extends keyof T & string, A extends unknown[] = Parameters, I = ObjectExports>(obj: T, funcName: U, cb: BeforeCallback): () => void; /** * Run code instead of a native module * @param obj Module to inject to * @param funcName Function name on that module to inject * @param cb Code to run * @returns Uninject function */ instead, U extends keyof T & string, A extends unknown[] = Parameters, R = ReturnType, I = ObjectExports>(obj: T, funcName: U, cb: InsteadCallback): () => void; /** * Run code after a native module * @param obj Module to inject to * @param funcName Function name on that module to inject * @param cb Code to run * @returns Uninject function */ after, U extends keyof T & string, A extends unknown[] = Parameters, R = ReturnType, I = ObjectExports>(obj: T, funcName: U, cb: AfterCallback): () => void; /** * A few utils to add stuff in frequent modules. */ utils: { /** * A utility function to add a button to any message popover. * @param item The function that creates the button to add * @returns Uninject Function. * * @example * ``` * import { Injector, webpack } from "replugged"; * * const injector = new Injector(); * * export function start() { * injector.utils.addPopoverButton((msg: Message, channel: Channel) => { * return { * label: "Click the button!", * icon: myVeryCoolIcon(), // Cool icon * onClick: () => { * // do stuff here when someone left clicks the button * }, * onContextMenu: () => { * // do other stuff here when someone right clicks the button * }, * }; * }); * } * * export function stop() { * injector.uninjectAll(); * } * ``` */ addPopoverButton: (item: GetButtonItem) => () => void; /** * A utility function to add an item to any context menu. * By default, items are placed in a group for custom items, though that can be customized with `sectionId` and `indexInSection` * @param navId The id of the menu to add to * @param item The function that creates the item to add * @param sectionId — The number of the section to add to. Defaults to Replugged's section * @param indexInSection — The index in the section to add to. Defaults to the end position * @returns A callback to de-register the function * * @example * ``` * import { Injector, components, types } from "replugged"; * const { ContextMenu: { MenuItem } } = components; * const { ContextMenuTypes } = types; * * const injector = new Injector(); * * export function start() { * injector.utils.addMenuItem(ContextMenuTypes.UserContext, // Right-clicking a user * (data, menu) => { * return console.log(data)} * /> * } * ) * } * * export function stop() { * injector.uninjectAll(); * } * ``` */ addMenuItem: = Record>(navId: ContextMenuTypes, item: GetContextItem, sectionId?: number | ((props: ContextMenuProps) => number), indexInSection?: number | ((props: ContextMenuProps) => number)) => () => void; /** * A utility function to add a custom slash command. * @param cmd The slash command to add to register * @returns A callback to de-register the command * * @example * ``` * import { Injector, types } from "replugged"; * * const injector = new Injector(); * * export function start() { * injector.utils.registerSlashCommand({ * name: "use", * description: "a command meant to be used", * usage: "/use", * executor: (interaction) => {}, * }) * } * * export function stop() { * injector.uninjectAll(); * } * ``` */ registerSlashCommand: (cmd: RepluggedCommand) => () => void; }; /** * Remove all injections made by this injector */ uninjectAll(): void; }