From 62485e8694b539128eb5555c5da2dc37bf219861 Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Fri, 28 Jun 2024 18:17:38 -0300
Subject: [PATCH 001/163] Obliterate Sentry
---
scripts/generateReport.ts | 2 +
src/plugins/_core/noTrack.ts | 56 ++++++++++++++++++++++++
src/webpack/patchWebpack.ts | 82 ++++++++++++++++++------------------
3 files changed, 98 insertions(+), 42 deletions(-)
diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts
index 0b94aaf72..9ffe6fb08 100644
--- a/scripts/generateReport.ts
+++ b/scripts/generateReport.ts
@@ -289,6 +289,8 @@ page.on("console", async e => {
page.on("error", e => console.error("[Error]", e.message));
page.on("pageerror", e => {
+ if (e.message.includes("Sentry successfully disabled")) return;
+
if (!e.message.startsWith("Object") && !e.message.includes("Cannot find module")) {
console.error("[Page Error]", e.message);
report.otherErrors.push(e.message);
diff --git a/src/plugins/_core/noTrack.ts b/src/plugins/_core/noTrack.ts
index 26b36735a..ef2849bbc 100644
--- a/src/plugins/_core/noTrack.ts
+++ b/src/plugins/_core/noTrack.ts
@@ -18,6 +18,7 @@
import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
+import { Logger } from "@utils/Logger";
import definePlugin, { OptionType, StartAt } from "@utils/types";
const settings = definePluginSettings({
@@ -71,9 +72,64 @@ export default definePlugin({
startAt: StartAt.Init,
start() {
+ // Sentry is initialized in its own WebpackInstance.
+ // It has everything it needs preloaded, so, it doesn't include any chunk loading functionality.
+ // Because of that, its WebpackInstance doesnt export wreq.m or wreq.c
+
+ // To circuvent this and disable Sentry we are gonna hook when wreq.g of its WebpackInstance is set.
+ // When that happens we are gonna obtain a reference to its internal module cache (wreq.c) and proxy its prototype,
+ // so, when the first require to initialize the Sentry is attempted, we are gonna forcefully throw an error and abort everything.
+ Object.defineProperty(Function.prototype, "g", {
+ configurable: true,
+
+ set(v: any) {
+ Object.defineProperty(this, "g", {
+ value: v,
+ configurable: true,
+ enumerable: true,
+ writable: true
+ });
+
+ // Ensure this is most likely the Sentry WebpackInstance.
+ // Function.g is a very generic property and is not uncommon for another WebpackInstance (or even a React component: ) to include it
+ const { stack } = new Error();
+ if (!(stack?.includes("discord.com") || stack?.includes("discordapp.com")) || this.c != null || !String(this).includes("exports:{}")) {
+ return;
+ }
+
+ const cacheExtractSym = Symbol("vencord.cacheExtract");
+ Object.defineProperty(Object.prototype, cacheExtractSym, {
+ configurable: true,
+
+ get() {
+ // One more condition to check if this is the Sentry WebpackInstance
+ if (Array.isArray(this)) {
+ return { exports: {} };
+ }
+
+ new Logger("NoTrack", "#8caaee").info("Disabling Sentry by proxying its WebpackInstance cache");
+ Object.setPrototypeOf(this, new Proxy(this, {
+ get() {
+ throw new Error("Sentry successfully disabled");
+ }
+ }));
+
+ Reflect.deleteProperty(Object.prototype, cacheExtractSym);
+ Reflect.deleteProperty(window, "DiscordSentry");
+ return { exports: {} };
+ }
+ });
+
+ // WebpackRequire our fake module id
+ this(cacheExtractSym);
+ }
+ });
+
Object.defineProperty(window, "DiscordSentry", {
configurable: true,
+
set() {
+ new Logger("NoTrack", "#8caaee").error("Failed to disable Sentry. Falling back to deleting window.DiscordSentry");
Reflect.deleteProperty(window, "DiscordSentry");
}
});
diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts
index bd47cefad..4b3b28a8e 100644
--- a/src/webpack/patchWebpack.ts
+++ b/src/webpack/patchWebpack.ts
@@ -56,58 +56,56 @@ Object.defineProperty(window, WEBPACK_CHUNK, {
// normally, this is populated via webpackGlobal.push, which we patch below.
// However, Discord has their .m prepopulated.
// Thus, we use this hack to immediately access their wreq.m and patch all already existing factories
-//
-// Update: Discord now has TWO webpack instances. Their normal one and sentry
-// Sentry does not push chunks to the global at all, so this same patch now also handles their sentry modules
Object.defineProperty(Function.prototype, "m", {
configurable: true,
set(v: any) {
- // When using react devtools or other extensions, we may also catch their webpack here.
- // This ensures we actually got the right one
- const { stack } = new Error();
- if ((stack?.includes("discord.com") || stack?.includes("discordapp.com")) && !Array.isArray(v)) {
- const fileName = stack.match(/\/assets\/(.+?\.js)/)?.[1] ?? "";
-
- logger.info("Found Webpack module factory", fileName);
- patchFactories(v);
-
- // Define a setter for the bundlePath property of WebpackRequire. Only the main Webpack has this property.
- // So if the setter is called, this means we can initialize the internal references to WebpackRequire.
- Object.defineProperty(this, "p", {
- configurable: true,
-
- set(this: WebpackInstance, bundlePath: string) {
- Object.defineProperty(this, "p", {
- value: bundlePath,
- configurable: true,
- enumerable: true,
- writable: true
- });
-
- clearTimeout(setterTimeout);
-
- if (bundlePath !== "/assets/") return;
-
- logger.info(`Main Webpack found in ${fileName}, initializing internal references to WebpackRequire`);
- _initWebpack(this);
-
- for (const beforeInitListener of beforeInitListeners) {
- beforeInitListener(this);
- }
- }
- });
- // setImmediate to clear this property setter if this is not the main Webpack.
- // If this is the main Webpack, wreq.p will always be set before the timeout runs.
- const setterTimeout = setTimeout(() => Reflect.deleteProperty(this, "p"), 0);
- }
-
Object.defineProperty(this, "m", {
value: v,
configurable: true,
enumerable: true,
writable: true
});
+
+ // When using react devtools or other extensions, we may also catch their webpack here.
+ // This ensures we actually got the right one
+ const { stack } = new Error();
+ if (!(stack?.includes("discord.com") || stack?.includes("discordapp.com")) || Array.isArray(v)) {
+ return;
+ }
+
+ const fileName = stack.match(/\/assets\/(.+?\.js)/)?.[1] ?? "";
+ logger.info("Found Webpack module factory", fileName);
+
+ patchFactories(v);
+
+ // Define a setter for the bundlePath property of WebpackRequire. Only the main Webpack has this property.
+ // So if the setter is called, this means we can initialize the internal references to WebpackRequire.
+ Object.defineProperty(this, "p", {
+ configurable: true,
+
+ set(this: WebpackInstance, bundlePath: string) {
+ Object.defineProperty(this, "p", {
+ value: bundlePath,
+ configurable: true,
+ enumerable: true,
+ writable: true
+ });
+
+ clearTimeout(setterTimeout);
+ if (bundlePath !== "/assets/") return;
+
+ logger.info(`Main Webpack found in ${fileName}, initializing internal references to WebpackRequire`);
+ _initWebpack(this);
+
+ for (const beforeInitListener of beforeInitListeners) {
+ beforeInitListener(this);
+ }
+ }
+ });
+ // setImmediate to clear this property setter if this is not the main Webpack.
+ // If this is the main Webpack, wreq.p will always be set before the timeout runs.
+ const setterTimeout = setTimeout(() => Reflect.deleteProperty(this, "p"), 0);
}
});
From 5c1c786cf9065c8d2e510a655229713a85c1834e Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Fri, 28 Jun 2024 18:29:40 -0300
Subject: [PATCH 002/163] Fix ReviewDB patch
---
src/plugins/reviewDB/index.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx
index 800de4a1f..7fdc1509a 100644
--- a/src/plugins/reviewDB/index.tsx
+++ b/src/plugins/reviewDB/index.tsx
@@ -87,7 +87,7 @@ export default definePlugin({
}
},
{
- find: ".VIEW_FULL_PROFILE,",
+ find: ".BITE_SIZE,user:",
replacement: {
match: /(?<=\.BITE_SIZE,children:\[)\(0,\i\.jsx\)\(\i\.\i,\{user:(\i),/,
replace: "$self.BiteSizeReviewsButton({user:$1}),$&"
From 2fa56b80abee1bfea4c3435191db88141ab30c87 Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Sat, 29 Jun 2024 01:26:03 -0300
Subject: [PATCH 003/163] Harder conditions for Sentry patching
---
src/plugins/_core/noTrack.ts | 44 ++++++++++++++++--------------------
1 file changed, 20 insertions(+), 24 deletions(-)
diff --git a/src/plugins/_core/noTrack.ts b/src/plugins/_core/noTrack.ts
index ef2849bbc..de1c20562 100644
--- a/src/plugins/_core/noTrack.ts
+++ b/src/plugins/_core/noTrack.ts
@@ -77,8 +77,7 @@ export default definePlugin({
// Because of that, its WebpackInstance doesnt export wreq.m or wreq.c
// To circuvent this and disable Sentry we are gonna hook when wreq.g of its WebpackInstance is set.
- // When that happens we are gonna obtain a reference to its internal module cache (wreq.c) and proxy its prototype,
- // so, when the first require to initialize the Sentry is attempted, we are gonna forcefully throw an error and abort everything.
+ // When that happens we are gonna forcefully throw an error and abort everything.
Object.defineProperty(Function.prototype, "g", {
configurable: true,
@@ -93,35 +92,30 @@ export default definePlugin({
// Ensure this is most likely the Sentry WebpackInstance.
// Function.g is a very generic property and is not uncommon for another WebpackInstance (or even a React component: ) to include it
const { stack } = new Error();
- if (!(stack?.includes("discord.com") || stack?.includes("discordapp.com")) || this.c != null || !String(this).includes("exports:{}")) {
+ if (!(stack?.includes("discord.com") || stack?.includes("discordapp.com")) || !String(this).includes("exports:{}") || this.c != null) {
return;
}
- const cacheExtractSym = Symbol("vencord.cacheExtract");
- Object.defineProperty(Object.prototype, cacheExtractSym, {
- configurable: true,
+ const assetPath = stack?.match(/\/assets\/.+?\.js/)?.[0];
+ if (!assetPath) {
+ return;
+ }
- get() {
- // One more condition to check if this is the Sentry WebpackInstance
- if (Array.isArray(this)) {
- return { exports: {} };
- }
+ const srcRequest = new XMLHttpRequest();
+ srcRequest.open("GET", assetPath, false);
+ srcRequest.send();
- new Logger("NoTrack", "#8caaee").info("Disabling Sentry by proxying its WebpackInstance cache");
- Object.setPrototypeOf(this, new Proxy(this, {
- get() {
- throw new Error("Sentry successfully disabled");
- }
- }));
+ // Final condition to see if this is the Sentry WebpackInstance
+ if (!srcRequest.responseText.includes("window.DiscordSentry=")) {
+ return;
+ }
- Reflect.deleteProperty(Object.prototype, cacheExtractSym);
- Reflect.deleteProperty(window, "DiscordSentry");
- return { exports: {} };
- }
- });
+ new Logger("NoTrack", "#8caaee").info("Disabling Sentry by erroring its WebpackInstance");
- // WebpackRequire our fake module id
- this(cacheExtractSym);
+ Reflect.deleteProperty(Function.prototype, "g");
+ Reflect.deleteProperty(window, "DiscordSentry");
+
+ throw new Error("Sentry successfully disabled");
}
});
@@ -130,6 +124,8 @@ export default definePlugin({
set() {
new Logger("NoTrack", "#8caaee").error("Failed to disable Sentry. Falling back to deleting window.DiscordSentry");
+
+ Reflect.deleteProperty(Function.prototype, "g");
Reflect.deleteProperty(window, "DiscordSentry");
}
});
From bda0e1844ba94bd0728dc723f12ead91cc3ef3ad Mon Sep 17 00:00:00 2001
From: Vendicated
Date: Fri, 28 Jun 2024 18:04:05 +0200
Subject: [PATCH 004/163] browser: increase minimum browser versions
---
browser/manifest.json | 2 +-
browser/manifestv2.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/browser/manifest.json b/browser/manifest.json
index c527c75b8..357312b09 100644
--- a/browser/manifest.json
+++ b/browser/manifest.json
@@ -1,6 +1,6 @@
{
"manifest_version": 3,
- "minimum_chrome_version": "91",
+ "minimum_chrome_version": "111",
"name": "Vencord Web",
"description": "The cutest Discord mod now in your browser",
diff --git a/browser/manifestv2.json b/browser/manifestv2.json
index f5b08571a..0cb7cb32a 100644
--- a/browser/manifestv2.json
+++ b/browser/manifestv2.json
@@ -43,7 +43,7 @@
"browser_specific_settings": {
"gecko": {
"id": "vencord-firefox@vendicated.dev",
- "strict_min_version": "91.0"
+ "strict_min_version": "128.0"
}
}
}
From 169edcb5b7974069d9cae04d7b23d8fa5b543e8e Mon Sep 17 00:00:00 2001
From: Vendicated
Date: Sat, 29 Jun 2024 17:34:13 +0200
Subject: [PATCH 005/163] improve support helper
---
src/plugins/_core/supportHelper.tsx | 30 ++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx
index faea66bfc..de8e37c79 100644
--- a/src/plugins/_core/supportHelper.tsx
+++ b/src/plugins/_core/supportHelper.tsx
@@ -17,6 +17,7 @@
*/
import { addAccessory } from "@api/MessageAccessories";
+import { definePluginSettings } from "@api/Settings";
import { getUserSettingLazy } from "@api/UserSettings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Flex } from "@components/Flex";
@@ -32,12 +33,12 @@ import { onlyOnce } from "@utils/onlyOnce";
import { makeCodeblock } from "@utils/text";
import definePlugin from "@utils/types";
import { checkForUpdates, isOutdated, update } from "@utils/updater";
-import { Alerts, Button, Card, ChannelStore, Forms, GuildMemberStore, Parser, RelationshipStore, showToast, Toasts, UserStore } from "@webpack/common";
+import { Alerts, Button, Card, ChannelStore, Forms, GuildMemberStore, Parser, RelationshipStore, showToast, Text, Toasts, UserStore } from "@webpack/common";
import gitHash from "~git-hash";
import plugins, { PluginMeta } from "~plugins";
-import settings from "./settings";
+import SettingsPlugin from "./settings";
const VENCORD_GUILD_ID = "1015060230222131221";
const VENBOT_USER_ID = "1017176847865352332";
@@ -86,7 +87,7 @@ async function generateDebugInfoMessage() {
const info = {
Vencord:
`v${VERSION} • [${gitHash}]()` +
- `${settings.additionalInfo} - ${Intl.DateTimeFormat("en-GB", { dateStyle: "medium" }).format(BUILD_TIMESTAMP)}`,
+ `${SettingsPlugin.additionalInfo} - ${Intl.DateTimeFormat("en-GB", { dateStyle: "medium" }).format(BUILD_TIMESTAMP)}`,
Client: `${RELEASE_CHANNEL} ~ ${client}`,
Platform: window.navigator.platform
};
@@ -132,6 +133,10 @@ function generatePluginList() {
const checkForUpdatesOnce = onlyOnce(checkForUpdates);
+const settings = definePluginSettings({}).withPrivateSettings<{
+ dismissedDevBuildWarning?: boolean;
+}>();
+
export default definePlugin({
name: "SupportHelper",
required: true,
@@ -139,6 +144,8 @@ export default definePlugin({
authors: [Devs.Ven],
dependencies: ["CommandsAPI", "UserSettingsAPI", "MessageAccessoriesAPI"],
+ settings,
+
patches: [{
find: ".BEGINNING_DM.format",
replacement: {
@@ -207,17 +214,22 @@ export default definePlugin({
});
}
- const repo = await VencordNative.updater.getRepo();
- if (repo.ok && !repo.value.includes("Vendicated/Vencord")) {
+ if (!IS_STANDALONE && !settings.store.dismissedDevBuildWarning) {
return Alerts.show({
title: "Hold on!",
body:
- You are using a fork of Vencord, which we do not provide support for!
+ You are using a custom build of Vencord, which we do not provide support for!
+
- Please either switch to an officially supported version of Vencord, or
- contact your package maintainer for support instead.
+ We only provide support for official builds.
+ Either switch to an official build or figure your issue out yourself.
-
+
+ You will be banned from receiving support if you ignore this rule.
+ ,
+ confirmText: "Understood",
+ secondaryConfirmText: "Don't show again",
+ onConfirmSecondary: () => settings.store.dismissedDevBuildWarning = true
});
}
}
From 086c31c890ab264d5ad221d0eb8ce40e8c0ee396 Mon Sep 17 00:00:00 2001
From: Luna
Date: Sat, 29 Jun 2024 17:43:25 +0200
Subject: [PATCH 006/163] new plugin ShowAllRoles: show all roles in simplified
profiles (#2624)
Co-authored-by: vee
---
src/plugins/showAllRoles/README.md | 6 ++++++
src/plugins/showAllRoles/index.ts | 23 +++++++++++++++++++++++
2 files changed, 29 insertions(+)
create mode 100644 src/plugins/showAllRoles/README.md
create mode 100644 src/plugins/showAllRoles/index.ts
diff --git a/src/plugins/showAllRoles/README.md b/src/plugins/showAllRoles/README.md
new file mode 100644
index 000000000..d5d99c794
--- /dev/null
+++ b/src/plugins/showAllRoles/README.md
@@ -0,0 +1,6 @@
+# ShowAllRoles
+
+Display all roles on the new profiles instead of limiting them to the default two rows.
+
+![image](https://github.com/Vendicated/Vencord/assets/71079641/3f021f03-c6f9-4fe5-83ac-a1891b5e4b37)
+
diff --git a/src/plugins/showAllRoles/index.ts b/src/plugins/showAllRoles/index.ts
new file mode 100644
index 000000000..02d9f964c
--- /dev/null
+++ b/src/plugins/showAllRoles/index.ts
@@ -0,0 +1,23 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import { Devs } from "@utils/constants";
+import definePlugin from "@utils/types";
+
+export default definePlugin({
+ name: "ShowAllRoles",
+ description: "Show all roles in new profiles.",
+ authors: [Devs.Luna],
+ patches: [
+ {
+ find: ".Messages.VIEW_ALL_ROLES",
+ replacement: {
+ match: /return null!=\i(?=\?\i\.slice)/,
+ replace: "return false"
+ }
+ }
+ ]
+});
From 2d570a524b18cd9ca4585481a1ca5862fab82da3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Antti=20Ellil=C3=A4?=
Date: Sat, 29 Jun 2024 19:39:09 +0300
Subject: [PATCH 007/163] friendsSince: add support for new profiles (#2623)
Co-authored-by: vee
---
src/plugins/friendsSince/index.tsx | 96 +++++++++++++++++++++++------
src/plugins/friendsSince/styles.css | 12 ----
src/utils/constants.ts | 4 ++
3 files changed, 81 insertions(+), 31 deletions(-)
delete mode 100644 src/plugins/friendsSince/styles.css
diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx
index b290a4450..629e8e719 100644
--- a/src/plugins/friendsSince/index.tsx
+++ b/src/plugins/friendsSince/index.tsx
@@ -4,50 +4,64 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
-import { classNameFactory } from "@api/Styles";
import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants";
import { getCurrentChannel } from "@utils/discord";
import { Logger } from "@utils/Logger";
-import { classes } from "@utils/misc";
import definePlugin from "@utils/types";
-import { findByCodeLazy, findByPropsLazy } from "@webpack";
-import { Heading, React, RelationshipStore, Text } from "@webpack/common";
+import { findByCodeLazy, findByPropsLazy, findLazy } from "@webpack";
+import { Heading, RelationshipStore, Text } from "@webpack/common";
-const container = findByPropsLazy("memberSinceWrapper");
+const containerWrapper = findByPropsLazy("memberSinceWrapper");
+const container = findByPropsLazy("memberSince");
const getCreatedAtDate = findByCodeLazy('month:"short",day:"numeric"');
const locale = findByPropsLazy("getLocale");
const lastSection = findByPropsLazy("lastSection");
-
-const cl = classNameFactory("vc-friendssince-");
+const section = findLazy((m: any) => m.section !== void 0 && Object.values(m).length === 1);
export default definePlugin({
name: "FriendsSince",
description: "Shows when you became friends with someone in the user popout",
- authors: [Devs.Elvyra],
+ authors: [Devs.Elvyra, Devs.Antti],
patches: [
- // User popup
+ // User popup - old layout
{
find: ".USER_PROFILE}};return",
replacement: {
match: /,{userId:(\i.id).{0,30}}\)/,
- replace: "$&,$self.friendsSince({ userId: $1 })"
+ replace: "$&,$self.friendsSinceOld({ userId: $1 })"
}
},
- // User DMs "User Profile" popup in the right
+ // DM User Sidebar - old layout
{
find: ".PROFILE_PANEL,",
replacement: {
match: /,{userId:([^,]+?)}\)/,
- replace: "$&,$self.friendsSince({ userId: $1 })"
+ replace: "$&,$self.friendsSinceOld({ userId: $1 })"
}
},
- // User Profile Modal
+ // User Profile Modal - old layout
{
find: ".userInfoSectionHeader,",
replacement: {
match: /(\.Messages\.USER_PROFILE_MEMBER_SINCE.+?userId:(.+?),textClassName:)(\i\.userInfoText)}\)/,
- replace: (_, rest, userId, textClassName) => `${rest}!$self.getFriendSince(${userId}) ? ${textClassName} : void 0 }), $self.friendsSince({ userId: ${userId}, textClassName: ${textClassName} })`
+ replace: (_, rest, userId, textClassName) => `${rest}!$self.getFriendSince(${userId}) ? ${textClassName} : void 0 }), $self.friendsSinceOld({ userId: ${userId}, textClassName: ${textClassName} })`
+ }
+ },
+ // DM User Sidebar - new layout
+ {
+ find: ".PANEL}),nicknameIcons",
+ replacement: {
+ match: /USER_PROFILE_MEMBER_SINCE,.{0,100}userId:(\i\.id)}\)}\)/,
+ replace: "$&,$self.friendsSinceNew({userId:$1,isSidebar:true})"
+ }
+ },
+ // User Profile Modal - new layout
+ {
+ find: "action:\"PRESS_APP_CONNECTION\"",
+ replacement: {
+ match: /USER_PROFILE_MEMBER_SINCE,.{0,100}userId:(\i\.id),.{0,100}}\)}\),/,
+ replace: "$&,$self.friendsSinceNew({userId:$1,isSidebar:false}),"
}
}
],
@@ -63,7 +77,7 @@ export default definePlugin({
}
},
- friendsSince: ErrorBoundary.wrap(({ userId, textClassName }: { userId: string; textClassName?: string; }) => {
+ friendsSinceOld: ErrorBoundary.wrap(({ userId, textClassName }: { userId: string; textClassName?: string; }) => {
if (!RelationshipStore.isFriend(userId)) return null;
const friendsSince = RelationshipStore.getSince(userId);
@@ -71,11 +85,11 @@ export default definePlugin({
return (