Webpack Modules
Discord is made using Webpack, which is a module bundler. Webpack splits the code into modules and bundles them together. Each module is a JavaScript object that contains various exports, such as constants, methods, and React components.
Your editor may suggest importing a module directly from within replugged/dist/whatever
, but this
will not work. You should always import from replugged
itself and destructure the module you want.
Finding modules
In order to use a module, you will need to find it first. There are a few ways to do this:
Common modules
Replugged comes with a bunch of modules that are commonly used. Common modules are documented here.
Get module
You can write a function that will be used to find the module. This functions similar to the Array.find parameter.
import { webpack } from "replugged";
const { getModule } = webpack;
export function start() {
const typingModule = getModule((m) => /* your code here */ someFn(m));
}
Replugged also comes with a filters
object with a few common filters. These are described below.
Wait for module
When Discord is starting, a module may not be available yet. For example, Replugged provides a
waitForModule
function that will wait for a module to be available before continuing. This works
similar to getModule
, but it returns a promise. The all
option is not available for this
function since it will only wait for one module.
import { webpack } from "replugged";
const { filters, waitForModule } = webpack;
export async function start() {
const typingMod = await waitForModule(filters.bySource("HORIZONTAL_REVERSE:"));
}
For props filters, use waitForProps
instead.
By default, waitForModule
will wait indefinitely. You can set a timeout using the
timeout
option.
Get by props
Most util/method modules can be found by using getByProps
. This function takes an array of strings
and finds a module that has all of the properties in the array.
import { webpack } from "replugged";
const { filters, getByProps, waitForModule } = webpack;
export function start() {
const typingModule = getByProps("getChannelId", "addChangeListener");
// or:
const typingModule = getModule(filters.byProps("getChannelId", "addChangeListener"));
}
Wait for props
Works like getByProps
, but waits for the module to be available like with
waitForModule
.
import { webpack } from "replugged";
const { waitForProps } = webpack;
export function start() {
const typingModule = await waitForProps("getChannelId", "addChangeListener");
}
Get by source
For modules that do not have human-readable properties (such as components), you can use
getBySource
to find a module by its source code. To use this, you will need to find the source
code of your module in the Discord DevTools. Once you find it, you will need to come up with a
unique string (or regex) that is only present in that module. You can then use this string to find
the module.
import { webpack } from "replugged";
const { filters, getBySource, waitForModule } = webpack;
export function start() {
const flexMod = getBySource("HORIZONTAL_REVERSE:");
// or:
const flexMod = getModule(filters.bySource("HORIZONTAL_REVERSE:"));
}
Randomized variable names within the source code (usually 1-2 characters, alphanumeric) can change between Discord updates and should not be considered stable. This means that your plugin may break if Discord updates. If the string you are using contains one of these variables, you should use a regular expression to make it more stable.
Note that this function looks at the minified source code, so your query will need to match the minified code.
You should make sure that your query will only match one module. If it matches multiple modules, you
might sometimes get the wrong module and your plugin could break. To test your query, you can call
the function in Discord DevTools with {all: true}
and see if it returns multiple modules.
replugged.webpack.getBySource("HORIZONTAL_REVERSE", { all: true });
In this case, there are 4 different modules that match the query. We can improve the query by
appending a :
, which only exists in the module we're looking for.
Get by store name
This function finds flux stores matching a specific name.
import { webpack } from "replugged";
const { getByStoreName } = webpack;
export function start() {
const store = getByStoreName("ChannelStore");
}
To get a list of stores, run replugged.common.flux.Store.getAll()
in Discord DevTools. The names
can be found with the .getName()
function on each store.
Get by ID
Webpack modules have an id
property that is used to separate them. This is a number, usually
around 6 digits. You'll see a bunch of functions in the Discord source code that are getting a
module by its ID.
Module IDs are not stable and will change between Discord updates. This can be used in development to find a module you already know the ID of, but you should not use this in production unless you're dynamically finding the ID.
import { webpack } from "replugged";
const { getById } = webpack;
export function start() {
const typingModule = getById(123456);
}
Processing modules
Get exports for props
When using filters.byProps
, the actual properties you need may be nested under a random key. To
get the actual export, you can use getExportsForProps
.
import { webpack } from "replugged";
const { filters, getExportsForProps, waitForModule } = webpack;
export async function start() {
const typingModuleRaw = await waitForModule(filters.byProps("getChannelId", "addChangeListener"));
const typingModule = getExportsForProps(typingModuleRaw, ["getChannelId", "addChangeListener"]);
}
This function is not needed when using getByProps
or
waitForProps
because they already do this for you.
Get function by source
This function will find a function in an object that matches the given source code (string or regex).
import { webpack } from "replugged";
const { getBySource, getFunctionBySource } = webpack;
export function start() {
const module = getBySource("YOUR QUERY HERE");
const functionInModule = getFunctionBySource(module, "YOUR QUERY HERE");
}
Get function key by source
Works like getFunctionBySource
, but returns the key of the function
instead of the function itself. Useful for getting the property name to use for
injecting.
import { Injector, webpack } from "replugged";
const { getBySource, getFunctionKeyBySource } = webpack;
const injector = new Injector();
export function start() {
const module = getBySource("YOUR QUERY HERE");
const keyInModule = getFunctionKeyBySource(module, "YOUR QUERY HERE");
injector.after(module, keyInModule, (args, res) => {
console.log("Function was called!", { args, res });
});
}
Options
All functions that find modules take an options object as the last parameter.
For getByProps
, you will need to put the props in an array to specify the options:
getByProps(["getChannelId", "addChangeListener"], { all: true });
all
Not available for waitForModule
or waitForProps
.
This option will return all modules that match the query instead of just the first one. If there are multiple modules that match your query, you can use this and then filter the results to find the one you want.
getByProps(["getChannelId", "addChangeListener"], { all: true });
raw
Replugged usually does some extra processing on the modules to make them easier to use. However, this can sometimes cause the properties you need to be lost. If you need the raw module, you can use this option.
getByProps(["getChannelId", "addChangeListener"], { raw: true });
timeout
Only available for waitForModule
and waitForProps
.
By default, these functions will wait forever for a module to be available. If you set a timeout, it will reject the promise after the specified time (milliseconds).
waitForModule(filters.byProps("getChannelId", "addChangeListener"), { timeout: 10_000 });