this repo has no description
at v1.2.3 3.8 kB view raw
1import { webFrame, ipcRenderer, contextBridge } from "electron"; 2import fs from "node:fs"; 3import path from "node:path"; 4 5import { readConfig, writeConfig } from "@moonlight-mod/core/config"; 6import { constants, MoonlightBranch } from "@moonlight-mod/types"; 7import { getExtensions } from "@moonlight-mod/core/extension"; 8import { getExtensionsPath, getMoonlightDir } from "@moonlight-mod/core/util/data"; 9import Logger, { initLogger } from "@moonlight-mod/core/util/logger"; 10import { loadExtensions, loadProcessedExtensions } from "@moonlight-mod/core/extension/loader"; 11import createFS from "@moonlight-mod/core/fs"; 12import { registerCors, registerBlocked, getDynamicCors } from "@moonlight-mod/core/cors"; 13 14let initialized = false; 15 16function setCors() { 17 const data = getDynamicCors(); 18 ipcRenderer.invoke(constants.ipcSetCorsList, data.cors); 19 ipcRenderer.invoke(constants.ipcSetBlockedList, data.blocked); 20} 21 22async function injectGlobals() { 23 global.moonlightNodeSandboxed = { 24 fs: createFS(), 25 addCors(url) { 26 registerCors(url); 27 if (initialized) setCors(); 28 }, 29 addBlocked(url) { 30 registerBlocked(url); 31 if (initialized) setCors(); 32 } 33 }; 34 35 const config = await readConfig(); 36 initLogger(config); 37 const extensions = await getExtensions(); 38 const processedExtensions = await loadExtensions(extensions); 39 const moonlightDir = await getMoonlightDir(); 40 const extensionsPath = await getExtensionsPath(); 41 42 function getConfig(ext: string) { 43 const val = config.extensions[ext]; 44 if (val == null || typeof val === "boolean") return undefined; 45 return val.config; 46 } 47 48 global.moonlightNode = { 49 config, 50 extensions, 51 processedExtensions, 52 nativesCache: {}, 53 isBrowser: false, 54 55 version: MOONLIGHT_VERSION, 56 branch: MOONLIGHT_BRANCH as MoonlightBranch, 57 58 getConfig, 59 getConfigOption: <T>(ext: string, name: string) => { 60 const config = getConfig(ext); 61 if (config == null) return undefined; 62 const option = config[name]; 63 if (option == null) return undefined; 64 return option as T; 65 }, 66 getNatives: (ext: string) => global.moonlightNode.nativesCache[ext], 67 getLogger: (id: string) => { 68 return new Logger(id); 69 }, 70 71 getMoonlightDir() { 72 return moonlightDir; 73 }, 74 getExtensionDir: (ext: string) => { 75 return path.join(extensionsPath, ext); 76 }, 77 writeConfig 78 }; 79 80 await loadProcessedExtensions(processedExtensions); 81 contextBridge.exposeInMainWorld("moonlightNode", moonlightNode); 82 83 const extCors = moonlightNode.processedExtensions.extensions.flatMap((x) => x.manifest.cors ?? []); 84 for (const cors of extCors) { 85 registerCors(cors); 86 } 87 88 for (const repo of moonlightNode.config.repositories) { 89 const url = new URL(repo); 90 url.pathname = "/"; 91 registerCors(url.toString()); 92 } 93 94 const extBlocked = moonlightNode.processedExtensions.extensions.flatMap((e) => e.manifest.blocked ?? []); 95 for (const blocked of extBlocked) { 96 registerBlocked(blocked); 97 } 98 99 setCors(); 100 101 initialized = true; 102} 103 104async function loadPreload() { 105 const webPreloadPath = path.join(__dirname, "web-preload.js"); 106 const webPreload = fs.readFileSync(webPreloadPath, "utf8"); 107 await webFrame.executeJavaScript(webPreload); 108} 109 110async function init(oldPreloadPath: string) { 111 try { 112 await injectGlobals(); 113 await loadPreload(); 114 } catch (e) { 115 const message = e instanceof Error ? e.stack : e; 116 await ipcRenderer.invoke(constants.ipcMessageBox, { 117 title: "moonlight node-preload error", 118 message: message 119 }); 120 } 121 122 // Let Discord start even if we fail 123 if (oldPreloadPath) require(oldPreloadPath); 124} 125 126const oldPreloadPath: string = ipcRenderer.sendSync(constants.ipcGetOldPreloadPath); 127init(oldPreloadPath);