diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 06fe1fd..792fa40 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,15 +4,16 @@ First of all, thank you for contributing! :3 To ensure your contribution is robust, please follow the below guide! +For a friendly introduction to plugins, see [Megu's Plugin Guide!](docs/2_PLUGINS.md) + ## Style Guide -- This project has a very minimal .editorconfig. Make sure your editor supports this! - If you are using VSCode, it should automatically recommend you the extension; If not, - please install the Editorconfig extension -- Try to follow the formatting in the rest of the project and stay consistent -- Follow the file naming convention. File names should usually be camelCase, unless they export a Class - or React Component, in which case they should be PascalCase - +- This project has a very minimal .editorconfig. Make sure your editor supports this! + If you are using VSCode, it should automatically recommend you the extension; If not, + please install the Editorconfig extension +- Try to follow the formatting in the rest of the project and stay consistent +- Follow the file naming convention. File names should usually be camelCase, unless they export a Class + or React Component, in which case they should be PascalCase ## Contributing a Plugin @@ -23,7 +24,6 @@ This way we can ensure compatibility and high quality patches. Follow the below guide to make your first plugin! - ### Finding the right module to patch If the thing you want to patch is an action performed when interacting with a part of the UI, use React DevTools. @@ -50,20 +50,22 @@ This is the regex that will operate on the module found with "find". Just like i this only matches exactly the part you want to patch and no other parts in the file. The easiest way to write and test your regex is the following: -- Get the ID of the module you want to patch. To do this, go to it in the sources tab and scroll up until you - see something like `447887: (e,t,n)=>{` (Obviously the number will differ). -- Now paste the following into the console: `Vencord.Webpack.wreq.m[447887].toString()` (Changing the number to your ID) -- Now either test regexes on this string in the console or use a tool like https://regex101.com + +- Get the ID of the module you want to patch. To do this, go to it in the sources tab and scroll up until you + see something like `447887: (e,t,n)=>{` (Obviously the number will differ). +- Now paste the following into the console: `Vencord.Webpack.wreq.m[447887].toString()` (Changing the number to your ID) +- Now either test regexes on this string in the console or use a tool like https://regex101.com Also pay attention to the following: -- Never hardcode variable or parameter names or any other minified names. They will change in the future. The only Exception to this rule - are the react props parameter which seems to always be `e`, but even then only rely on this if it is necessary. - Instead, use one of the following approaches where applicable: - - Match 1 or 2 of any character: `.{1,2}`, for example to match the variable name in `var a=b`, `var (.{1,2})=` - - Match any but a guaranteed terminating character: `[^;]+`, for example to match the entire assigned value in `var a=b||c||func();`, - `var .{1,2}=([^;]+);` - - If you don't care about that part, just match a bunch of chars: `.{0,50}`, for example to extract the variable "b" in `createElement("div",{a:"foo",c:"bar"},b)`, `createElement\("div".{0,30},(.{1,2})\),`. Note the `.{0,30}`, this is essentially the same as `.+`, but safer as you can't end up accidently eating thousands of characters -- Additionally, as you might have noticed, all of the appove approaches use regex groups (`(...)`) to capture the variable name. You can then use those groups in your replacement to access those variables dynamically + +- Never hardcode variable or parameter names or any other minified names. They will change in the future. The only Exception to this rule + are the react props parameter which seems to always be `e`, but even then only rely on this if it is necessary. + Instead, use one of the following approaches where applicable: + - Match 1 or 2 of any character: `.{1,2}`, for example to match the variable name in `var a=b`, `var (.{1,2})=` + - Match any but a guaranteed terminating character: `[^;]+`, for example to match the entire assigned value in `var a=b||c||func();`, + `var .{1,2}=([^;]+);` + - If you don't care about that part, just match a bunch of chars: `.{0,50}`, for example to extract the variable "b" in `createElement("div",{a:"foo",c:"bar"},b)`, `createElement\("div".{0,30},(.{1,2})\),`. Note the `.{0,30}`, this is essentially the same as `.+`, but safer as you can't end up accidently eating thousands of characters +- Additionally, as you might have noticed, all of the appove approaches use regex groups (`(...)`) to capture the variable name. You can then use those groups in your replacement to access those variables dynamically #### "replace" @@ -75,6 +77,6 @@ and use those in your replacement Make sure your replacement does not introduce any whitespace. While this might seem weird, random whitespace may mess up other patches. This includes spaces, tabs and especially newlines -___ +--- And that's it! Now open a Pull Request with your Plugin diff --git a/README.md b/README.md index 50ba1ed..43db4c8 100644 --- a/README.md +++ b/README.md @@ -4,64 +4,38 @@ A Discord client mod that does things differently ## Features -- Works on Discord's latest update that breaks all other mods -- Browser Support (experimental): Run Vencord in your Browser instead of the desktop app -- Custom Css and Themes: Manually edit `%appdata%/Vencord/settings/quickCss.css` / `~/.config/Vencord/settings/quickCss.css` with your favourite editor and the client will automatically apply your changes. To import BetterDiscord themes, just add `@import url(theUrl)` on the top of this file. (Make sure the url is a github raw URL or similar and only contains plain text, and NOT a nice looking website) -- Many Usefulâ„¢ plugins - [List](https://github.com/Vendicated/Vencord/tree/main/src/plugins) -- Experiments -- Proper context isolation -> Works in newer Electron versions (Confirmed working on versions 13-21) -- Inline patches: Patch Discord's code with regex replacements! See [the experiments plugin](src/plugins/experiments.ts) for an example. While being more complex, this is more powerful than monkey patching since you can patch only small parts of functions instead of fully replacing them, access non exported/local variables and even replace constants (like in the aforementioned experiments patch!) +- Works on Discord's latest update that breaks all other mods +- Browser Support (experimental): Run Vencord in your Browser instead of the desktop app +- Custom Css and Themes: Manually edit `%appdata%/Vencord/settings/quickCss.css` / `~/.config/Vencord/settings/quickCss.css` with your favourite editor and the client will automatically apply your changes. To import BetterDiscord themes, just add `@import url(theUrl)` on the top of this file. (Make sure the url is a github raw URL or similar and only contains plain text, and NOT a nice looking website) +- Many Usefulâ„¢ plugins - [List](https://github.com/Vendicated/Vencord/tree/main/src/plugins) +- Experiments +- Proper context isolation -> Works in newer Electron versions (Confirmed working on versions 13-21) +- Inline patches: Patch Discord's code with regex replacements! See [the experiments plugin](src/plugins/experiments.ts) for an example. While being more complex, this is more powerful than monkey patching since you can patch only small parts of functions instead of fully replacing them, access non exported/local variables and even replace constants (like in the aforementioned experiments patch!) +## Installing / Uninstalling -## Installing - -If you can't follow the following instructions, please just use BetterDiscord. -This was never meant to be a noob friendly mod. - -Install [Node.js](https://nodejs.org/en/download/) and [git](https://git-scm.com/downloads) - -Open a Terminal and run the following commands. -If any of them failed, you didn't properly install Node.js and git (see above). -> :warning: On Windows, DO NOT run the terminal as Administrator. If you open it and the path says system32, you opened it as Administrator. - -```sh -npm i -g pnpm -git clone https://github.com/Vendicated/Vencord -cd Vencord -pnpm i -pnpm build -``` -Don't close your terminal just yet! - -Now to patch vencord into your Discord client, run the following command and follow the interactive prompt. - -```sh -pnpm inject -``` - -Now fully close Discord. Start and confirm Vencord successfully installed by checking if you have a new Vencord section in Settings. - -If you ever need to get back to the Vencord folder, just open a new terminal and type `cd Vencord` - -All plugins are disabled by default, so your first step should be opening Settings and enabling the plugins you want. - -You can unpatch Vencord using `pnpm uninject` - +Read [Megu's Installation Guide!](docs/1_INSTALLING.md) ## Installing on Browser Run the same commands as in the regular install method. Now run + ```sh pnpm buildWeb ``` + You will find the built extension at dist/extension.zip. Now just install this extension in your Browser ## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) and [Megu's Plugin Guide!](docs/2_PLUGINS.md) + [contribute]: CONTRIBUTING.md [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] [contribute] ## Join + [join]: https://discord.gg/D9uwnFnqmd [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] [join] diff --git a/docs/1_INSTALLING.md b/docs/1_INSTALLING.md new file mode 100644 index 0000000..3ce2841 --- /dev/null +++ b/docs/1_INSTALLING.md @@ -0,0 +1,194 @@ +# Installation Guide + +Welcome to Megu's Installation Guide! In this file, you will learn about how to download, install, and uninstall Vencord! + +## Sections + +- [Dependencies](#dependencies) +- [Installing Vencord](#installing-vencord) +- [Updating Vencord](#updating-vencord) +- [Uninstalling Vencord](#uninstalling-vencord) +- [Manually Installing Vencord](#manually-installing-vencord) +- [Manually Uninstalling Vencord](#manually-uninstalling-vencord) + +## Dependencies + +- Install Git from https://git-scm.com/download +- Install Node.JS LTS from here: https://nodejs.dev/en/ + +## Installing Vencord + +> :exclamation: If this doesn't work, see [Manually Installing Vencord](#manually-installing-vencord) + +Install `pnpm`: + +> :exclamation: this may need to be run as admin depending on your system, and you may need to close and reopen your terminal. + +```shell +npm i -g pnpm +``` + +Clone Vencord: + +```shell +git clone https://github.com/Vendicated/Vencord +cd Vencord +``` + +Install dependencies: + +```shell +pnpm install +``` + +Build Vencord: + +```shell +pnpm build +``` + +Inject vencord into your client: + +```shell +pnpm inject +``` + +Then fully close Discord from your taskbar or task manager, and restart it. Vencord should be injected - you can check this by looking for the Vencord section in Discord settings. + +## Updating Vencord + +If you're using Discord already, go into the `Updater` tab in settings. + +Sometimes it may be neccessary to manually update if the GUI updater fails. + +To pull latest changes: + +```shell +git pull +``` + +If this fails, you likely need to reset your local changes to vencord to resolve merge errors: + +> :exclamation: This command will remove any local changes you've made to vencord. Make sure you back up if you made any code changes you don't want to lose! + +```shell +git reset --hard +git pull +``` + +and then to build the changes: + +```shell +pnpm build +``` + +Then just refresh your client + +## Uninstalling Vencord + +Simply run: + +```shell +pnpm uninject +``` + +The above command may ask you to also run: + +```shell +pnpm install +pnpm uninject +``` + +## Manually Installing Vencord + +- [Windows](#on-windows) +- [Linux](#on-linux) +- [MacOS](#on-macos) + +### On Windows + +Press Win+R and enter: `%LocalAppData%` and hit enter. In this page, find the page (Discord, DiscordPTB, DiscordCanary, etc) that you want to patch. + +Now follow the instructions at [Manual Patching](#manual-patching) + +### On Linux + +The Discord folder is usually in one of the following paths: + +- /usr/share +- /usr/lib64 +- /opt +- /home/$USER/.local/share + +If you use flatpak, it will usually be in one of the following paths: + +- /var/lib/flatpak/app/com.discordapp.Discord/current/active/files +- /home/$USER/.local/share/flatpak/app/com.discordapp.Discord/current/active/files + +You will need to give flatpak access to vencord with one of the following commands: + +> :exclamation: If not on stable, replace `com.discordapp.Discord` with your branch name, e.g., `com.discordapp.DiscordCanary` + +> :exclamation: Replace `/path/to/vencord/` with the path to your vencord folder (NOT the dist folder) + +If Discord flatpak install is in /home/: + +```shell +flatpak override --user com.discordapp.Discord --filesystem="/path/to/vencord/" +``` + +If Discord flatpak install not in /home/: + +```shell +sudo flatpak override com.discordapp.Discord --filesystem="/path/to/vencord" +``` + +Now follow the instructions at [Manual Patching](#manual-patching) + +### On MacOS + +Open finder and go to your Applications folder. Right-Click on the Discord application you want to patch, and view contents. + +Go to the `Contents/Resources` folder. + +Now follow the instructions at [Manual Patching](#manual-patching) + +### Manual Patching + +> :exclamation: If using Flatpak on linux, go to the folder that contains the `app.asar` file, and skip to where we create the `app` folder below. + +> :exclamation: On Linux/MacOS, there's a chance there won't be an `app-` folder, but there probably is a `resources` folder, so keep reading :) + +Inside there, look for the `app-` folders. If you have multiple, use the highest number. If that doesn't work, do it for the rest of the `app-` folders. + +Inside there, go to the `resources` folder. There should be a file called `app.asar`. If there isn't, look at a different `app-` folder instead. + +Make a new folder in `resources` called `app`. In here, we will make two files: + +`package.json` and `index.js` + +In `index.js`: + +> :exclamation: Replace the path in the first line with the path to `patcher.js` in your vencord dist folder. +> On Windows, you can get this by shift-rightclicking the patcher.js file and selecting "copy as path" + +```js +require("C:/Users//path/to/vencord/dist/patcher.js"); +require("../app.asar"); +``` + +And in `package.json`: + +```json +{ "name": "discord", "main": "index.js" } +``` + +Finally, fully close & reopen your Discord client and check to see that `Vencord` appears in settings! + +### Manually Uninstalling Vencord + +> :exclamation: Do not delete `app.asar` - Only delete the `app` folder we created. + +Use the instructions above to find the `app` folder, and delete it. Then Close & Reopen Discord. + +If you need more help, ask in the support channel in our [Discord Server](https://discord.gg/D9uwnFnqmd). diff --git a/docs/2_PLUGINS.md b/docs/2_PLUGINS.md new file mode 100644 index 0000000..71ec7f9 --- /dev/null +++ b/docs/2_PLUGINS.md @@ -0,0 +1,103 @@ +# Plugins Guide + +Welcome to Megu's Plugin Guide! In this file, you will learn about how to write your own plugin! + +You don't need to run `pnpm build` every time you make a change. Instead, use `pnpm watch` - this will auto-compile Vencord whenever you make a change. If using code patches (recommended), you will need to CTRL+R to load the changes. + +## Plugin Entrypoint + +1. Create a folder in `src/plugins/` with the name of your plugin. For example, `src/plugins/epicPlugin/` - All of your plugin files will go here. + +2. Create a file in that folder called `index.ts` + +3. In `index.ts`, copy-paste the following template code: + +```ts +import definePlugin from "../../utils/types"; + +export default definePlugin({ + name: "Epic Plugin", + description: "This plugin is absolutely epic", + authors: [ + { + id: "your discord user id goes here", + name: "Your Name", + }, + ], + patches: [], + // Delete these two below if you are only using code patches + start() {}, + stop() {}, +}); +``` + +Change the name, description, and authors to your own information. + +## How Plugins Work In Vencord + +Vencord uses a different way of making mods than you're used to. +Instead of monkeypatching webpack, we directly modify the code before Discord loads it. + +This is _significantly_ more efficient than monkeypatching webpack, and is surprisingly easy, but it may be confusing at first. + +## Making your patch + +For an in-depth guide into patching code, see [CONTRIBUTING.md](../CONTRIBUTING.md) + +in the `index.ts` file we made earlier, you'll see a `patches` array. + +> You'll see examples of how patches are used in all the existing plugins, and it'll be easier to understand by looking at those examples, so do that first, and then return here! + +> For a good example of a plugin using code patches AND runtime patching, check `src/plugins/unindent.ts`, which uses code patches to run custom runtime code. + +One of the patches in the `isStaff` plugin, looks like this: + +```ts +{ + match: /(\w+)\.isStaff=function\(\){return\s*!1};/, + replace: "$1.isStaff=function(){return true};", +}, +``` + +The above regex matches the string in discord that will look something like: + +```js +abc.isStaff = function () { + return !1; +}; +``` + +Remember that Discord code is minified, so there won't be any newlines, and there will only be spaces where necessary. So the source code looks something like: + +``` +abc.isStaff=function(){return!1;} +``` + +You can find these snippets by opening the devtools (`ctrl+shift+i`) and pressing `ctrl+shift+f`, searching for what you're looking to modify in there, and beautifying the file to make it more readable. + +In the `match` regex in the example shown above, you'll notice at the start there is a `(\w+)`. +Anything in the brackets will be accessible in the `replace` string using `$`. e.g., the first pair of brackets will be `$1`, the second will be `$2`, etc. + +The replacement string we used is: + +``` +"$1.isStaff=function(){return true;};" +``` + +Which, using the above example, would replace the code with: + +> :exclamation: In this example, `$1` becomes `abc` + +```js +abc.isStaff = function () { + return true; +}; +``` + +The match value _can_ be a string, rather than regex, however usually regex will be better suited, as it can work with unknown values, whereas strings must be exact matches. + +Once you've made your plugin, make sure you run `pnpm lint` and make sure your code is nice and clean, and then open a PR on github :) + +> :exclamation: Make sure you've read [CONTRIBUTING.md](../CONTRIBUTING.md) before opening a PR + +If you need more help, ask in the support channel in our [Discord Server](https://discord.gg/D9uwnFnqmd).