This commit is contained in:
thororen1234 2024-07-18 23:54:25 -04:00
commit a64eae919a
20 changed files with 251 additions and 441 deletions

View file

@ -1,44 +0,0 @@
/*
* 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: "ModViewBypass",
description: "Open the mod view sidebar in guilds you don't have moderator permissions in, or where the experiment is disabled.",
authors: [Devs.Sqaaakoi],
patches: [
{
find: "canAccessGuildMemberModViewWithExperiment:",
replacement: {
match: /canAccessGuildMemberModViewWithExperiment:function\(\){return\s\i/,
replace: "canAccessGuildMemberModViewWithExperiment:function(){return ()=>true;",
},
},
{
find: "useCanAccessGuildMemberModView:",
replacement: {
match: /\i.default.hasAny\(/,
replace: "true; (",
},
},
{
find: "isInGuildMemberModViewExperiment:",
replacement: {
match: /isInGuildMemberModViewExperiment:function\(\){return\s\i/,
replace: "isInGuildMemberModViewExperiment:function(){return ()=>true;",
},
},
{
find: "useGuildMemberModViewExperiment:",
replacement: {
match: /useGuildMemberModViewExperiment:function\(\){return\s\i/,
replace: "useGuildMemberModViewExperiment:function(){return ()=>true;",
},
},
],
});

View file

@ -13,13 +13,6 @@ export default definePlugin({
authors: [EquicordDevs.kvba],
patches: [
{
find: "\"APP_TAG\"",
replacement: {
match: /"APP_TAG":".*?"/,
replace: "\"APP_TAG\":\"BOT\""
}
},
{
find: ",APP_TAG:\"",
replacement: {

View file

@ -29,7 +29,7 @@ export default definePlugin({
patches: [
{
find: "Messages.ACCOUNT_A11Y_LABEL",
find: "isFullscreenInContext());",
replacement: {
match: /(?<=function)( \i\i\(\i\)(?={).)(.{0,1000}\i\.\i\.isFullscreenInContext\(\).+?\)]}\))\}/,
replace: "$1 return $self.replacedUserPanelComponent(function(){$2}, this, arguments)}"

View file

@ -62,13 +62,12 @@ export default definePlugin({
name: "TextToSpeech",
description: "Reads out chat messages with openai tts",
authors: [Devs.Samwich],
flux:
{
flux: {
async MESSAGE_CREATE({ optimistic, type, message, channelId }) {
if (optimistic || type !== "MESSAGE_CREATE") return;
if (message.state === "SENDING") return;
if (!message.content) return;
if (message.channel_id !== getCurrentChannel().id) return;
if (message.channel_id !== getCurrentChannel()?.id ?? 0) return;
readOutText(message.content);
}

View file

@ -1,70 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { definePluginSettings } from "@api/Settings";
import { EquicordDevs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
const settings = definePluginSettings({
spoilerFilenames: {
description: "Strings in filenames that should be spoilered. Comma separated.",
type: OptionType.STRING,
default: "",
},
spoilerLinks: {
description: "Strings in link attachments that should be spoilered. Comma separated.",
type: OptionType.STRING,
default: ""
},
gifSpoilersOnly: {
description: "Should the links only be gifs?",
type: OptionType.BOOLEAN,
default: true
},
});
export default definePlugin({
name: "TriggerWarning",
authors: [EquicordDevs.Joona],
description: "Spoiler attachments based on filenames and links.",
patches: [
{
find: "SimpleMessageAccessories:",
replacement: [
{
match: /function \i\((\i),\i\){return/,
replace: "$& $self.shouldSpoiler($1.originalItem.filename) || "
},
{
match: /(\i)=\(0,\i\.getOb.{27,35}\);(?=if\((\i).type)/,
replace: "$&$1=$self.spoilerLink($1,$2.url,$2.type);"
}
]
}
],
settings,
shouldSpoiler(filename: string): string | null {
const { spoilerFilenames } = settings.store;
if (!filename || !spoilerFilenames) return null;
const strings = spoilerFilenames.split(",").map(s => s.trim());
return strings.some(s => filename.includes(s)) ? "spoiler" : null;
},
spoilerLink(alreadySpoilered: string, link: string, type: string): string | null {
if (alreadySpoilered) return alreadySpoilered;
const { spoilerLinks, gifSpoilersOnly } = settings.store;
if (!link || !spoilerLinks) return null;
const strings = spoilerLinks.split(",").map(s => s.trim());
const isLinkSpoiler = strings.some(s => link.includes(s));
if (gifSpoilersOnly) {
return type === "gifv" && isLinkSpoiler ? "spoiler" : null;
} else {
return isLinkSpoiler ? "spoiler" : null;
}
}
});

View file

@ -1,147 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Settings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
import { findExportedComponentLazy } from "@webpack";
import { Menu, Popout, useState } from "@webpack/common";
import type { ReactNode } from "react";
function toggle(name: string, onClose: () => void) {
Settings.plugins.TextModifiers[name] = !Settings.plugins.TextModifiers[name];
onClose();
}
function isEnabled(name: string) {
return Settings.plugins.TextModifiers[name];
}
const HeaderBarIcon = findExportedComponentLazy("Icon", "Divider");
function utilityDockPopout(onClose: () => void) {
return (
<Menu.Menu
navId="utilityDock"
onClose={onClose}
>
<Menu.MenuCheckboxItem
id="utilityDock-quickcss-toggle"
checked={Settings.useQuickCss}
label={"QuickCSS"}
action={() => {
Settings.useQuickCss = !Settings.useQuickCss;
onClose();
}}
/>
<Menu.MenuItem
id="utilityDock-quickcss"
label="Edit QuickCSS"
action={() => VencordNative.quickCss.openEditor()}
/>
</Menu.Menu>
);
}
function utilityDockIcon(isShown: boolean) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width={24} height={24}>
<path fill="currentColor" d={isShown ?
"M20 8H17V6C17 4.9 16.1 4 15 4H9C7.9 4 7 4.9 7 6V8H4C2.9 8 2 8.9 2 10V20H22V10C22 8.9 21.1 8 20 8M9 6H15V8H9V6M20 18H4V15H6V16H8V15H16V16H18V15H20V18M18 13V12H16V13H8V12H6V13H4V10H20V13H18Z"
:
"M18 16H16V15H8V16H6V15H2V20H22V15H18V16M20 8H17V6C17 4.9 16.1 4 15 4H9C7.9 4 7 4.9 7 6V8H4C2.9 8 2 8.9 2 10V14H6V12H8V14H16V12H18V14H22V10C22 8.9 21.1 8 20 8M15 8H9V6H15V8Z"} />
</svg>
);
}
function VencordPopoutButton() {
const [show, setShow] = useState(false);
return (
<Popout
position="bottom"
align="right"
animation={Popout.Animation.NONE}
shouldShow={show}
onRequestClose={() => setShow(false)}
renderPopout={() => utilityDockPopout(() => setShow(false))}
>
{(_, { isShown }) => (
<HeaderBarIcon
className="vc-toolbox-btn"
onClick={() => setShow(v => !v)}
tooltip={isShown ? null : "Utility Dock"}
icon={() => utilityDockIcon(isShown)}
selected={isShown}
/>
)}
</Popout>
);
}
function utilityDock({ children }: { children: ReactNode[]; }) {
children.splice(
children.length - 1, 0,
<ErrorBoundary noop={true}>
<VencordPopoutButton />
</ErrorBoundary>
);
return <>{children}</>;
}
export default definePlugin({
name: "UtilityDock",
description: "Adds a button on your titlebar with multiple useful features",
authors: [Devs.Samwich],
patches: [
{
find: "toolbar:function",
replacement: {
match: /(?<=toolbar:function.{0,100}\()\i.Fragment,/,
replace: "$self.utilityDock,"
}
}
],
utilityDock: ErrorBoundary.wrap(utilityDock, {
fallback: () => <p style={{ color: "red" }}>Failed to render :(</p>
})
});
export function TextPlugin({ pluginName, onClose }) {
return (
<Menu.MenuCheckboxItem
id={`vc-toolbox-${pluginName}-toggle`}
checked={Settings.plugins[pluginName].enabled}
label={pluginName}
action={() => {
Settings.plugins[pluginName].isEnabled = !Settings.plugins[pluginName].isEnabled;
onClose();
}}
/>
);
}

View file

@ -43,11 +43,9 @@ if (IS_VESKTOP || !IS_VANILLA) {
}
switch (url) {
case "renderer.js.map":
case "vencordDesktopRenderer.js.map":
case "preload.js.map":
case "vencordDesktopPreload.js.map":
case "patcher.js.map":
case "vencordDesktopMain.js.map":
case "main.js.map":
cb(join(__dirname, url));
break;
default:

View file

@ -119,7 +119,7 @@ ipcMain.handle(IpcEvents.OPEN_MONACO_EDITOR, async () => {
autoHideMenuBar: true,
darkTheme: true,
webPreferences: {
preload: join(__dirname, IS_DISCORD_DESKTOP ? "preload.js" : "vencordDesktopPreload.js"),
preload: join(__dirname, "preload.js"),
contextIsolation: true,
nodeIntegration: false,
sandbox: false

View file

@ -26,14 +26,18 @@ import { IS_VANILLA } from "./utils/constants";
console.log("[Equicord] Starting up...");
// FIXME: remove at some point
const isLegacyNonAsarVencord = IS_STANDALONE && !__dirname.endsWith(".asar");
if (isLegacyNonAsarVencord) {
console.warn("This is a legacy non asar install! Migrating to asar and restarting...");
require("./updater/http").migrateLegacyToAsar();
}
// Our injector file at app/index.js
const injectorPath = require.main!.filename;
// special discord_arch_electron injection method
const asarName = require.main!.path.endsWith("app.asar") ? "_app.asar" : "app.asar";
// The original app.asar
const asarPath = join(dirname(injectorPath), "..", asarName);
const asarPath = join(dirname(injectorPath), "..", "_app.asar");
const discordPkg = require(join(asarPath, "package.json"));
require.main!.filename = join(asarPath, discordPkg.main);
@ -41,7 +45,7 @@ require.main!.filename = join(asarPath, discordPkg.main);
// @ts-ignore Untyped method? Dies from cringe
app.setAppPath(asarPath);
if (!IS_VANILLA) {
if (!IS_VANILLA && !isLegacyNonAsarVencord) {
const settings = RendererSettings.store;
// Repatch after host updates on Windows
if (process.platform === "win32") {
@ -71,7 +75,7 @@ if (!IS_VANILLA) {
constructor(options: BrowserWindowConstructorOptions) {
if (options?.webPreferences?.preload && options.title) {
const original = options.webPreferences.preload;
options.webPreferences.preload = join(__dirname, IS_DISCORD_DESKTOP ? "preload.js" : "vencordDesktopPreload.js");
options.webPreferences.preload = join(__dirname, "preload.js");
options.webPreferences.sandbox = false;
// work around discord unloading when in background
options.webPreferences.backgroundThrottling = false;
@ -157,5 +161,7 @@ if (!IS_VANILLA) {
console.log("[Equicord] Running in vanilla mode. Not loading Equicord");
}
console.log("[Equicord] Loading original Discord app.asar");
require(require.main!.filename);
if (!isLegacyNonAsarVencord) {
console.log("[Equicord] Loading original Discord app.asar");
require(require.main!.filename);
}

View file

@ -16,12 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export const VENCORD_FILES = [
IS_DISCORD_DESKTOP ? "patcher.js" : "vencordDesktopMain.js",
IS_DISCORD_DESKTOP ? "preload.js" : "vencordDesktopPreload.js",
IS_DISCORD_DESKTOP ? "renderer.js" : "vencordDesktopRenderer.js",
IS_DISCORD_DESKTOP ? "renderer.css" : "vencordDesktopRenderer.css",
];
export const ASAR_FILE = IS_VESKTOP
? "vesktop.asar"
: "desktop.asar";
export function serializeErrors(func: (...args: any[]) => any) {
return async function () {

View file

@ -18,25 +18,21 @@
import { IpcEvents } from "@shared/IpcEvents";
import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent";
import axios from "axios";
import { ipcMain } from "electron";
import { writeFile } from "fs/promises";
import { app, dialog, ipcMain } from "electron";
import { writeFileSync as originalWriteFileSync } from "original-fs";
import { join } from "path";
import gitHash from "~git-hash";
import gitRemote from "~git-remote";
import { serializeErrors, VENCORD_FILES } from "./common";
import { get } from "../utils/simpleGet";
import { ASAR_FILE, serializeErrors } from "./common";
const API_BASE = `https://api.github.com/repos/${gitRemote}`;
let PendingUpdates = [] as [string, string][];
let PendingUpdate: string | null = null;
async function githubGet(endpoint: string) {
return axios({
method: "get",
responseType: "json",
url: API_BASE + endpoint,
return get(API_BASE + endpoint, {
headers: {
Accept: "application/vnd.github+json",
// "All API requests MUST include a valid User-Agent header.
@ -52,7 +48,8 @@ async function calculateGitChanges() {
const res = await githubGet(`/compare/${gitHash}...HEAD`);
return res.data.commits.map((c: any) => ({
const data = JSON.parse(res.toString("utf-8"));
return data.commits.map((c: any) => ({
// github api only sends the long sha
hash: c.sha.slice(0, 7),
author: c.author.login,
@ -63,32 +60,26 @@ async function calculateGitChanges() {
async function fetchUpdates() {
const release = await githubGet("/releases/latest");
const hash = release.data.name.slice(release.data.name.lastIndexOf(" ") + 1);
const data = JSON.parse(release.toString());
const hash = data.name.slice(data.name.lastIndexOf(" ") + 1);
if (hash === gitHash)
return false;
release.data.assets.forEach(({ name, browser_download_url }) => {
if (VENCORD_FILES.some(s => name.startsWith(s))) {
PendingUpdates.push([name, browser_download_url]);
}
});
const asset = data.assets.find(a => a.name === ASAR_FILE);
PendingUpdate = asset.browser_download_url;
return true;
}
async function applyUpdates() {
await Promise.all(PendingUpdates.map(
async ([name, data]) => {
writeFile(
join(__dirname, name),
(await axios({
method: "get",
responseType: "arraybuffer",
url: data,
})).data
);
}
));
PendingUpdates = [];
if (!PendingUpdate) return true;
const data = await get(PendingUpdate);
originalWriteFileSync(__dirname, data);
PendingUpdate = null;
return true;
}
@ -96,3 +87,28 @@ ipcMain.handle(IpcEvents.GET_REPO, serializeErrors(() => `https://github.com/${g
ipcMain.handle(IpcEvents.GET_UPDATES, serializeErrors(calculateGitChanges));
ipcMain.handle(IpcEvents.UPDATE, serializeErrors(fetchUpdates));
ipcMain.handle(IpcEvents.BUILD, serializeErrors(applyUpdates));
export async function migrateLegacyToAsar() {
try {
const isFlatpak = process.platform === "linux" && !!process.env.FLATPAK_ID;
if (isFlatpak) throw "Flatpak Discord can't automatically be migrated.";
const data = await get(`https://github.com/${gitRemote}/releases/latest/download/desktop.asar`);
originalWriteFileSync(join(__dirname, "../vencord.asar"), data);
originalWriteFileSync(__filename, '// Legacy shim for new asar\n\nrequire("../vencord.asar");');
app.relaunch();
app.exit();
} catch (e) {
console.error("Failed to migrate to asar", e);
app.whenReady().then(() => {
dialog.showErrorBox(
"Legacy Install",
"The way Vencord loaded was changed and the updater failed to migrate. Please reinstall using the Vencord Installer!"
);
app.exit(1);
});
}
}

View file

@ -16,7 +16,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import axios from "axios";
import { session } from "electron";
import { unzip } from "fflate";
import { constants as fsConstants } from "fs";
@ -25,6 +24,7 @@ import { join } from "path";
import { DATA_DIR } from "./constants";
import { crxToZip } from "./crxToZip";
import { get } from "./simpleGet";
const extensionCacheDir = join(DATA_DIR, "ExtensionCache");
@ -73,15 +73,12 @@ export async function installExt(id: string) {
// Unfortunately, Google does not serve old versions, so this is the only way
? "https://raw.githubusercontent.com/Vendicated/random-files/f6f550e4c58ac5f2012095a130406c2ab25b984d/fmkadmapgofadopljbjfkapdkoienihi.zip"
: `https://clients2.google.com/service/update2/crx?response=redirect&acceptformat=crx2,crx3&x=id%3D${id}%26uc&prodversion=32`;
const response = await axios({
method: "get",
responseType: "blob",
url: url,
const buf = await get(url, {
headers: {
"User-Agent": "Vencord (https://github.com/Vendicated/Vencord)"
"User-Agent": "Equicord (https://github.com/Equicord/Equicord)"
}
});
await extract(crxToZip(Buffer.from(response.data, "binary")), extDir).catch(console.error);
await extract(crxToZip(buf), extDir).catch(console.error);
}
session.defaultSession.loadExtension(extDir);

View file

@ -28,13 +28,7 @@ contextBridge.exposeInMainWorld("VencordNative", VencordNative);
// Discord
if (location.protocol !== "data:") {
// #region cssInsert
let rendererPath;
if (IS_VESKTOP || IS_EQUIBOP) {
rendererPath = "vencordDesktopRenderer.css";
} else {
rendererPath = "renderer.css";
}
const rendererCss = join(__dirname, rendererPath);
const rendererCss = join(__dirname, "renderer.css");
const style = document.createElement("style");
style.id = "vencord-css-core";