this repo has no description
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

Entrypoint cleanup

+80 -111
+13 -15
packages/core-extensions/src/disableSentry/node.ts
··· 5 5 6 6 const logger = moonlightNode.getLogger("disableSentry"); 7 7 8 - if (!ipcRenderer.sendSync(constants.ipcGetIsMoonlightDesktop)) { 9 - const preloadPath = ipcRenderer.sendSync(constants.ipcGetOldPreloadPath); 10 - try { 11 - const sentryPath = require.resolve(resolve(preloadPath, "..", "node_modules", "@sentry", "electron")); 12 - require.cache[sentryPath] = new Module(sentryPath, require.cache[require.resolve(preloadPath)]); 13 - require.cache[sentryPath]!.exports = { 14 - init: () => {}, 15 - setTag: () => {}, 16 - setUser: () => {}, 17 - captureMessage: () => {} 18 - }; 19 - logger.debug("Stubbed Sentry node side!"); 20 - } catch (err) { 21 - logger.error("Failed to stub Sentry:", err); 22 - } 8 + const preloadPath = ipcRenderer.sendSync(constants.ipcGetOldPreloadPath); 9 + try { 10 + const sentryPath = require.resolve(resolve(preloadPath, "..", "node_modules", "@sentry", "electron")); 11 + require.cache[sentryPath] = new Module(sentryPath, require.cache[require.resolve(preloadPath)]); 12 + require.cache[sentryPath]!.exports = { 13 + init: () => {}, 14 + setTag: () => {}, 15 + setUser: () => {}, 16 + captureMessage: () => {} 17 + }; 18 + logger.debug("Stubbed Sentry node side!"); 19 + } catch (err) { 20 + logger.error("Failed to stub Sentry:", err); 23 21 }
+47 -84
packages/injector/src/index.ts
··· 6 6 } from "electron"; 7 7 import Module from "node:module"; 8 8 import { constants, MoonlightBranch } from "@moonlight-mod/types"; 9 - import { readConfig } from "@moonlight-mod/core/config"; 9 + import { readConfig, writeConfig } from "@moonlight-mod/core/config"; 10 10 import { getExtensions } from "@moonlight-mod/core/extension"; 11 11 import Logger, { initLogger } from "@moonlight-mod/core/util/logger"; 12 12 import { loadExtensions, loadProcessedExtensions } from "@moonlight-mod/core/extension/loader"; 13 13 import EventEmitter from "node:events"; 14 - import { join, resolve } from "node:path"; 14 + import path from "node:path"; 15 15 import persist from "@moonlight-mod/core/persist"; 16 16 import createFS from "@moonlight-mod/core/fs"; 17 + import { getConfigOption, getManifest, setConfigOption } from "@moonlight-mod/core/util/config"; 18 + import { getExtensionsPath, getMoonlightDir } from "@moonlight-mod/core/util/data"; 17 19 18 20 const logger = new Logger("injector"); 19 21 20 22 let oldPreloadPath: string | undefined; 21 23 let corsAllow: string[] = []; 22 24 let blockedUrls: RegExp[] = []; 23 - let isMoonlightDesktop = false; 24 - let hasOpenAsar = false; 25 - let openAsarConfigPreload: string | undefined; 25 + let injectorConfig: InjectorConfig | undefined; 26 26 27 27 const scriptUrls = ["web.", "sentry."]; 28 28 const blockedScripts = new Set<string>(); ··· 34 34 ipcMain.on(constants.ipcGetAppData, (e) => { 35 35 e.returnValue = app.getPath("appData"); 36 36 }); 37 - ipcMain.on(constants.ipcGetIsMoonlightDesktop, (e) => { 38 - e.returnValue = isMoonlightDesktop; 37 + ipcMain.on(constants.ipcGetInjectorConfig, (e) => { 38 + e.returnValue = injectorConfig; 39 39 }); 40 40 ipcMain.handle(constants.ipcMessageBox, (_, opts) => { 41 41 electron.dialog.showMessageBoxSync(opts); ··· 114 114 headers[csp] = [stringified]; 115 115 } 116 116 117 - function removeOpenAsarEventIfPresent(eventHandler: (...args: any[]) => void) { 118 - const code = eventHandler.toString(); 119 - if (code.indexOf("bw.webContents.on('dom-ready'") > -1) { 120 - electron.app.off("browser-window-created", eventHandler); 121 - } 122 - } 123 - 124 117 class BrowserWindow extends ElectronBrowserWindow { 125 118 constructor(opts: BrowserWindowConstructorOptions) { 126 119 const isMainWindow = opts.webPreferences!.preload!.indexOf("discord_desktop_core") > -1; ··· 185 178 // this is needed because multiple webRequest handlers cannot be registered at once 186 179 cb({ cancel: blockedUrls.some((u) => u.test(details.url)) }); 187 180 }); 188 - 189 - if (hasOpenAsar) { 190 - // Remove DOM injections 191 - // Settings can still be opened via: 192 - // `DiscordNative.ipc.send("DISCORD_UPDATED_QUOTES","o")` 193 - // @ts-expect-error Electron internals 194 - const events = electron.app._events["browser-window-created"]; 195 - if (Array.isArray(events)) { 196 - for (const event of events) { 197 - removeOpenAsarEventIfPresent(event); 198 - } 199 - } else if (events != null) { 200 - removeOpenAsarEventIfPresent(events); 201 - } 202 - 203 - // Config screen fails to context bridge properly 204 - // Less than ideal, but better than disabling it everywhere 205 - if (opts.webPreferences!.preload === openAsarConfigPreload) { 206 - opts.webPreferences!.sandbox = false; 207 - } 208 - } 209 181 } 210 182 } 211 183 ··· 226 198 writable: false 227 199 }); 228 200 229 - export async function inject(asarPath: string) { 230 - isMoonlightDesktop = asarPath === "moonlightDesktop"; 201 + type InjectorConfig = { disablePersist?: boolean; disableLoad?: boolean }; 202 + export async function inject(asarPath: string, _injectorConfig?: InjectorConfig) { 203 + injectorConfig = _injectorConfig; 204 + 231 205 global.moonlightNodeSandboxed = { 232 206 fs: createFS(), 233 207 // These aren't supposed to be used from host 234 - addCors(url) {}, 235 - addBlocked(url) {} 208 + addCors() {}, 209 + addBlocked() {} 236 210 }; 237 211 238 212 try { 239 - const config = await readConfig(); 213 + let config = await readConfig(); 240 214 initLogger(config); 241 215 const extensions = await getExtensions(); 216 + const processedExtensions = await loadExtensions(extensions); 217 + const moonlightDir = await getMoonlightDir(); 218 + const extensionsPath = await getExtensionsPath(); 242 219 243 220 // Duplicated in node-preload... oops 244 221 function getConfig(ext: string) { ··· 248 225 } 249 226 250 227 global.moonlightHost = { 228 + get config() { 229 + return config; 230 + }, 231 + extensions, 232 + processedExtensions, 251 233 asarPath, 252 - config, 253 234 events: new EventEmitter(), 254 - extensions, 255 - processedExtensions: { 256 - extensions: [], 257 - dependencyGraph: new Map() 258 - }, 259 235 260 236 version: MOONLIGHT_VERSION, 261 237 branch: MOONLIGHT_BRANCH as MoonlightBranch, 262 238 263 239 getConfig, 264 - getConfigOption: <T>(ext: string, name: string) => { 265 - const config = getConfig(ext); 266 - if (config == null) return undefined; 267 - const option = config[name]; 268 - if (option == null) return undefined; 269 - return option as T; 240 + getConfigOption(ext, name) { 241 + const manifest = getManifest(extensions, ext); 242 + return getConfigOption(ext, name, config, manifest?.settings); 243 + }, 244 + setConfigOption(ext, name, value) { 245 + setConfigOption(config, ext, name, value); 246 + this.writeConfig(config); 247 + }, 248 + async writeConfig(newConfig) { 249 + await writeConfig(newConfig); 250 + config = newConfig; 270 251 }, 271 - getLogger: (id: string) => { 252 + 253 + getLogger(id) { 272 254 return new Logger(id); 255 + }, 256 + getMoonlightDir() { 257 + return moonlightDir; 258 + }, 259 + getExtensionDir: (ext: string) => { 260 + return path.join(extensionsPath, ext); 273 261 } 274 262 }; 275 263 276 - // Check if we're running with OpenAsar 277 - try { 278 - require.resolve(join(asarPath, "updater", "updater.js")); 279 - hasOpenAsar = true; 280 - openAsarConfigPreload = resolve(asarPath, "config", "preload.js"); 281 - // eslint-disable-next-line no-empty 282 - } catch {} 283 - 284 - if (hasOpenAsar) { 285 - // Disable command line switch injection 286 - // I personally think that the command line switches should be vetted by 287 - // the user and not just "trust that these are sane defaults that work 288 - // always". I'm not hating on Ducko or anything, I'm just opinionated. 289 - // Someone can always make a command line modifier plugin, thats the point 290 - // of having host modules. 291 - try { 292 - const cmdSwitchesPath = require.resolve(join(asarPath, "cmdSwitches.js")); 293 - require.cache[cmdSwitchesPath] = new Module(cmdSwitchesPath, require.cache[require.resolve(asarPath)]); 294 - require.cache[cmdSwitchesPath]!.exports = () => {}; 295 - } catch (error) { 296 - logger.error("Failed to disable OpenAsar's command line flags:", error); 297 - } 298 - } 299 - 300 264 patchElectron(); 301 265 302 - global.moonlightHost.processedExtensions = await loadExtensions(extensions); 303 266 await loadProcessedExtensions(global.moonlightHost.processedExtensions); 304 267 } catch (error) { 305 268 logger.error("Failed to inject:", error); 306 269 } 307 270 308 - if (isMoonlightDesktop) return; 309 - 310 - if (!hasOpenAsar && !isMoonlightDesktop) { 271 + if (injectorConfig?.disablePersist !== true) { 311 272 persist(asarPath); 312 273 } 313 274 314 - // Need to do this instead of require() or it breaks require.main 315 - // @ts-expect-error Module internals 316 - Module._load(asarPath, Module, true); 275 + if (injectorConfig?.disableLoad !== true) { 276 + // Need to do this instead of require() or it breaks require.main 277 + // @ts-expect-error Module internals 278 + Module._load(asarPath, Module, true); 279 + } 317 280 } 318 281 319 282 function patchElectron() {
+4 -5
packages/node-preload/src/index.ts
··· 66 66 setConfigOption(config, ext, name, value); 67 67 this.writeConfig(config); 68 68 }, 69 + async writeConfig(newConfig) { 70 + await writeConfig(newConfig); 71 + config = newConfig; 72 + }, 69 73 70 74 getNatives: (ext: string) => global.moonlightNode.nativesCache[ext], 71 75 getLogger: (id: string) => { 72 76 return new Logger(id); 73 77 }, 74 - 75 78 getMoonlightDir() { 76 79 return moonlightDir; 77 80 }, 78 81 getExtensionDir: (ext: string) => { 79 82 return path.join(extensionsPath, ext); 80 - }, 81 - async writeConfig(newConfig) { 82 - await writeConfig(newConfig); 83 - config = newConfig; 84 83 } 85 84 }; 86 85
+1 -1
packages/types/src/constants.ts
··· 8 8 export const ipcGetOldPreloadPath = "_moonlight_getOldPreloadPath"; 9 9 10 10 export const ipcGetAppData = "_moonlight_getAppData"; 11 - export const ipcGetIsMoonlightDesktop = "_moonlight_getIsMoonlightDesktop"; 11 + export const ipcGetInjectorConfig = "_moonlight_getInjectorConfig"; 12 12 export const ipcMessageBox = "_moonlight_messageBox"; 13 13 export const ipcSetCorsList = "_moonlight_setCorsList"; 14 14 export const ipcSetBlockedList = "_moonlight_setBlockedList";
+11 -5
packages/types/src/globals.ts
··· 8 8 import { MoonlightFS } from "./fs"; 9 9 10 10 export type MoonlightHost = { 11 - asarPath: string; 12 11 config: Config; 13 - events: EventEmitter; 14 12 extensions: DetectedExtension[]; 15 13 processedExtensions: ProcessedExtensions; 14 + asarPath: string; 15 + events: EventEmitter; 16 16 17 17 version: string; 18 18 branch: MoonlightBranch; 19 19 20 20 getConfig: (ext: string) => ConfigExtension["config"]; 21 21 getConfigOption: <T>(ext: string, name: string) => T | undefined; 22 + setConfigOption: <T>(ext: string, name: string, value: T) => void; 23 + writeConfig: (config: Config) => Promise<void>; 24 + 22 25 getLogger: (id: string) => Logger; 26 + getMoonlightDir: () => string; 27 + getExtensionDir: (ext: string) => string; 23 28 }; 24 29 25 30 export type MoonlightNode = { ··· 35 40 getConfig: (ext: string) => ConfigExtension["config"]; 36 41 getConfigOption: <T>(ext: string, name: string) => T | undefined; 37 42 setConfigOption: <T>(ext: string, name: string, value: T) => void; 43 + writeConfig: (config: Config) => Promise<void>; 38 44 39 45 getNatives: (ext: string) => any | undefined; 40 46 getLogger: (id: string) => Logger; 41 - 42 47 getMoonlightDir: () => string; 43 48 getExtensionDir: (ext: string) => string; 44 - writeConfig: (config: Config) => Promise<void>; 45 49 }; 46 50 47 51 export type MoonlightNodeSandboxed = { ··· 54 58 unpatched: Set<IdentifiedPatch>; 55 59 pendingModules: Set<IdentifiedWebpackModule>; 56 60 enabledExtensions: Set<string>; 57 - apiLevel: number; 58 61 events: MoonlightEventEmitter<EventType, EventPayloads>; 59 62 patchingInternals: { 60 63 onModuleLoad: (moduleId: string | string[], callback: (moduleId: string) => void) => void; ··· 65 68 66 69 version: string; 67 70 branch: MoonlightBranch; 71 + apiLevel: number; 68 72 69 73 // Re-exports for ease of use 70 74 getConfig: MoonlightNode["getConfig"]; 71 75 getConfigOption: MoonlightNode["getConfigOption"]; 72 76 setConfigOption: MoonlightNode["setConfigOption"]; 77 + writeConfig: MoonlightNode["writeConfig"]; 73 78 74 79 getNatives: (ext: string) => any | undefined; 75 80 getLogger: (id: string) => Logger; 81 + 76 82 lunast: LunAST; 77 83 moonmap: Moonmap; 78 84 };
+4 -1
packages/web-preload/src/index.ts
··· 15 15 const logger = new Logger("web-preload"); 16 16 17 17 window.moonlight = { 18 - apiLevel: constants.apiLevel, 19 18 unpatched: new Set(), 20 19 pendingModules: new Set(), 21 20 enabledExtensions: new Set(), 21 + 22 22 events: createEventEmitter<EventType, EventPayloads>(), 23 23 patchingInternals: { 24 24 onModuleLoad, ··· 29 29 30 30 version: MOONLIGHT_VERSION, 31 31 branch: MOONLIGHT_BRANCH as MoonlightBranch, 32 + apiLevel: constants.apiLevel, 32 33 33 34 getConfig: moonlightNode.getConfig.bind(moonlightNode), 34 35 getConfigOption: moonlightNode.getConfigOption.bind(moonlightNode), 35 36 setConfigOption: moonlightNode.setConfigOption.bind(moonlightNode), 37 + writeConfig: moonlightNode.writeConfig.bind(moonlightNode), 36 38 37 39 getNatives: moonlightNode.getNatives.bind(moonlightNode), 38 40 getLogger(id) { 39 41 return new Logger(id); 40 42 }, 43 + 41 44 lunast: new LunAST(), 42 45 moonmap: new Moonmap() 43 46 };