Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignition Fix #659

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions bin/index.mts
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ async function buildPlugin({ watch, noInstall, production, noReload, addon }: Ar
esbuild.context(
overwrites({
...common,
format: "cjs",
entryPoints: [path.join(folderPath, manifest.plaintextPatches)],
outfile: `${distPath}/plaintextPatches.js`,
}),
Expand Down
2 changes: 1 addition & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"webauthn",
"weblate",
"Withs",
"YofukashiNo"
"yofukashino"
],
"ignoreWords": [],
"import": [],
Expand Down
4 changes: 2 additions & 2 deletions scripts/build-plugins/intl-loader.mts
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ export default {
getTranslationImport: (importPath) => `import("${importPath}")`,
debug: !production,
preGenerateBinds: false,
getPrelude: () => `import {waitForProps} from '@webpack';`,
getPrelude: () => `import {getByProps} from '@webpack';`,
}).getOutput();

return {
contents: transformedOutput.replace(
/require\('@discord\/intl'\);/,
"await waitForProps('createLoader','IntlManager');",
"getByProps('createLoader','IntlManager');",
),
loader: "js",
};
Expand Down
6 changes: 5 additions & 1 deletion scripts/build.mts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,12 @@ const contexts = await Promise.all([
entryPoints: ["src/renderer/index.ts"],
platform: "browser",
target: `chrome${CHROME_VERSION}`,
format: "iife",
footer: {
js: "//# sourceURL=replugged://RepluggedRenderer/renderer.js",
css: "/*# sourceURL=replugged://RepluggedRenderer/renderer.css */",
},
outfile: `${distDir}/renderer.js`,
format: "esm",
loader: {
".png": "dataurl",
},
Expand Down
6 changes: 3 additions & 3 deletions src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ electron.protocol.registerSchemesAsPrivileged([
},
]);

async function loadReactDevTools(): Promise<void> {
const rdtSetting = await getSetting("dev.replugged.Settings", "reactDevTools", false);
function loadReactDevTools(): void {
const rdtSetting = getSetting<boolean>("dev.replugged.Settings", "reactDevTools", false);

if (rdtSetting) {
void electron.session.defaultSession.loadExtension(CONFIG_PATHS["react-devtools"]);
Expand Down Expand Up @@ -180,7 +180,7 @@ electron.app.once("ready", () => {
cb({ path: filePath });
});

void loadReactDevTools();
loadReactDevTools();
});

// This module is required this way at runtime.
Expand Down
6 changes: 6 additions & 0 deletions src/main/ipc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import "./quick-css";
import "./react-devtools";
import "./settings";
import "./themes";
import { readFileSync } from "fs";
import { join } from "path";

ipcMain.on(RepluggedIpcChannels.GET_DISCORD_PRELOAD, (event) => {
event.returnValue = (event.sender as RepluggedWebContents).originalPreload;
});

ipcMain.on(RepluggedIpcChannels.GET_REPLUGGED_RENDERER, (event) => {
event.returnValue = readFileSync(join(__dirname, "./renderer.js"), "utf-8");
});
4 changes: 2 additions & 2 deletions src/main/ipc/installer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ async function github(
}

async function store(id: string): Promise<CheckResultSuccess | CheckResultFailure> {
const apiUrl = await getSetting("dev.replugged.Settings", "apiUrl", WEBSITE_URL);
const apiUrl = getSetting("dev.replugged.Settings", "apiUrl", WEBSITE_URL);
const STORE_BASE_URL = `${apiUrl}/api/v1/store`;
const manifestUrl = `${STORE_BASE_URL}/${id}`;
const asarUrl = `${manifestUrl}.asar`;
Expand Down Expand Up @@ -191,7 +191,7 @@ ipcMain.handle(
if (type === "replugged") {
// Manually set Path and URL for security purposes
path = "replugged.asar";
const apiUrl = await getSetting("dev.replugged.Settings", "apiUrl", WEBSITE_URL);
const apiUrl = getSetting("dev.replugged.Settings", "apiUrl", WEBSITE_URL);
url = `${apiUrl}/api/v1/store/dev.replugged.Replugged.asar`;
}

Expand Down
82 changes: 46 additions & 36 deletions src/main/ipc/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ IPC events:
- REPLUGGED_UNINSTALL_PLUGIN: returns whether a plugin by the provided name was successfully uninstalled
*/

import { readFile, readdir, readlink, rm, stat } from "fs/promises";
import { rm } from "fs/promises";
import { extname, join, sep } from "path";
import { ipcMain, shell } from "electron";
import { RepluggedIpcChannels, type RepluggedPlugin } from "../../types";
import { plugin } from "../../types/addon";
import type { Dirent, Stats } from "fs";
import { type Dirent, type Stats, readFileSync, readdirSync, readlinkSync, statSync } from "fs";
import { CONFIG_PATHS } from "src/util.mjs";

const PLUGINS_DIR = CONFIG_PATHS.plugins;
Expand All @@ -18,15 +18,15 @@ export const isFileAPlugin = (f: Dirent | Stats, name: string): boolean => {
return f.isDirectory() || (f.isFile() && extname(name) === ".asar");
};

async function getPlugin(pluginName: string): Promise<RepluggedPlugin> {
function getPlugin(pluginName: string): RepluggedPlugin {
const manifestPath = join(PLUGINS_DIR, pluginName, "manifest.json");
if (!manifestPath.startsWith(`${PLUGINS_DIR}${sep}`)) {
// Ensure file changes are restricted to the base path
throw new Error("Invalid plugin name");
}

const manifest: unknown = JSON.parse(
await readFile(manifestPath, {
readFileSync(manifestPath, {
encoding: "utf-8",
}),
);
Expand All @@ -38,56 +38,66 @@ async function getPlugin(pluginName: string): Promise<RepluggedPlugin> {
};

const cssPath = data.manifest.renderer?.replace(/\.js$/, ".css");
const hasCSS =
cssPath &&
(await stat(join(PLUGINS_DIR, pluginName, cssPath))
.then(() => true)
.catch(() => false));
try {
const hasCSS = cssPath && statSync(join(PLUGINS_DIR, pluginName, cssPath));

if (hasCSS) data.hasCSS = true;
if (hasCSS) data.hasCSS = true;
} catch {
data.hasCSS = false;
}

return data;
}

ipcMain.handle(
RepluggedIpcChannels.GET_PLUGIN,
async (_, pluginName: string): Promise<RepluggedPlugin | undefined> => {
try {
return await getPlugin(pluginName);
} catch {}
},
);
ipcMain.on(RepluggedIpcChannels.GET_PLUGIN, (event, pluginName: string) => {
try {
event.returnValue = getPlugin(pluginName);
} catch {}
});

ipcMain.handle(RepluggedIpcChannels.LIST_PLUGINS, async (): Promise<RepluggedPlugin[]> => {
ipcMain.on(RepluggedIpcChannels.LIST_PLUGINS, (event) => {
const plugins = [];

const pluginDirs = (
await Promise.all(
(
await readdir(PLUGINS_DIR, {
withFileTypes: true,
})
).map(async (f) => {
if (isFileAPlugin(f, f.name)) return f;
if (f.isSymbolicLink()) {
const actualPath = await readlink(join(PLUGINS_DIR, f.name));
const actualFile = await stat(actualPath);
const pluginDirs = readdirSync(PLUGINS_DIR, {
withFileTypes: true,
})
.map((f) => {
if (isFileAPlugin(f, f.name)) return f;
if (f.isSymbolicLink()) {
try {
const actualPath = readlinkSync(join(PLUGINS_DIR, f.name));
const actualFile = statSync(actualPath);

if (isFileAPlugin(actualFile, actualPath)) return f;
}
}),
)
).filter(Boolean) as Dirent[];
} catch {}
}

return void 0;
})
.filter(Boolean) as Dirent[];

for (const pluginDir of pluginDirs) {
try {
plugins.push(await getPlugin(pluginDir.name));
plugins.push(getPlugin(pluginDir.name));
} catch (e) {
console.error(`Invalid plugin: ${pluginDir.name}`);
console.error(e);
}
}
event.returnValue = plugins;
});

ipcMain.on(RepluggedIpcChannels.READ_PLUGIN_PLAINTEXT_PATCHES, (event, pluginName) => {
const plugin = getPlugin(pluginName);
if (!plugin.manifest.plaintextPatches) return;

const path = join(CONFIG_PATHS.plugins, pluginName, plugin.manifest.plaintextPatches);
if (!path.startsWith(`${PLUGINS_DIR}${sep}`)) {
// Ensure file changes are restricted to the base path
throw new Error("Invalid plugin name");
}

return plugins;
if (path) event.returnValue = readFileSync(path, "utf-8");
});

ipcMain.handle(RepluggedIpcChannels.UNINSTALL_PLUGIN, async (_, pluginName: string) => {
Expand Down
2 changes: 1 addition & 1 deletion src/main/ipc/react-devtools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const OUTPUT_PATH = join(CONFIG_PATHS["react-devtools"]);
const ZIP_PATH = join(OUTPUT_PATH, "extension.zip");

ipcMain.handle(RepluggedIpcChannels.DOWNLOAD_REACT_DEVTOOLS, async () => {
const apiUrl = await getSetting("dev.replugged.Settings", "apiUrl", WEBSITE_URL);
const apiUrl = getSetting("dev.replugged.Settings", "apiUrl", WEBSITE_URL);
const REACT_DEVTOOLS_URL = `${apiUrl}/api/v1/react-devtools`;

let buffer;
Expand Down
Loading