const { BrowserWindow, app, net, dialog, ipcMain, nativeImage, session, shell } = require("electron") const msmc = require("msmc") const os = require("os") const hwid = require("./modules/hwid") const path = require("node:path") const serverPing = require("./modules/serverPing") const config = require("./config.json") const { Authenticator } = require("minecraft-launcher-core") let launcherWindow, auth, skinPath async function createLauncherWindow() { if (net.isOnline()) { let win_width = 1550 let win_height = parseInt(win_width / (16/9)) const isLauncherNotBanned = await checkIfIAmBanned() launcherWindow = new BrowserWindow({ frame: false, width: win_width, height: win_height, minWidth: win_width, minHeight: win_height, titleBarStyle: "hidden", autoHideMenuBar: true, roundedCorners: false, resizable: false, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, "modules", "preload.js"), webviewTag: true } }) if (os.platform() == "darwin") { app.dock.setIcon(nativeImage.createFromPath(path.join(__dirname, "app", "assets", "img", "icon.png"))) } launcherWindow.setIcon(path.join(__dirname, "app", "assets", "img", "icon.png")) if (isLauncherNotBanned.success) { launcherWindow.loadFile(path.join(__dirname, "app", "login.html")) session.defaultSession.webRequest.onBeforeRequest({ urls: [ "https://embed.twitch.tv/*channel=*" ] }, (details, callback) => { const url = details.url const urlParams = new URLSearchParams(url.replace("https://embed.twitch.tv/", "")) if (urlParams.get("parent")) { callback({}) return } urlParams.set("parent", "localhost") urlParams.set("referrer", "https://localhost/") const redirectUrl = `https://embed.twitch.tv/?${urlParams.toString()}` callback({ cancel: false, redirectURL: redirectUrl }) }) session.defaultSession.webRequest.onHeadersReceived({ urls: [ "https://www.twitch.tv/*", "https://player.twitch.tv/*", "https://embed.twitch.tv/*" ] }, (details, callback) => { const responseHeaders = details.responseHeaders delete responseHeaders["Content-Security-Policy"] callback({ cancel: false, responseHeaders }) }) launcherWindow.webContents.openDevTools() } else { launcherWindow.loadFile(path.join(__dirname, "app", "banned.html")) launcherWindow.webContents.executeJavaScript(` setBannedBy("${isLauncherNotBanned.banned_by}") setBannedAt("${isLauncherNotBanned.banned_at}") setBannedBecause("${isLauncherNotBanned.reason}") `) } } else { dialog.showErrorBox("Connexion internet", "Le launcher requiert une connexion internet.") } } async function checkIfIAmBanned() { // if (net.isOnline()) { // try { // const reponse = await fetch(`${config.api.base}${config.api.endpoints.checkBanStatus}`, { // method: "post", // body: JSON.stringify({ // hwid: hwid.getHWID() // }) // }) // const json = await reponse.json() // return json // } catch (error) { // dialog.showErrorBox("Connexion à l'API", "Impossible de contacter l'API, fermeture du launcher.") // console.error(error) // app.exit() // } // } else { // dialog.showErrorBox("Connexion internet", "Le launcher requiert une connexion internet.") // } return { success: true } } app.whenReady().then(() => { createLauncherWindow() app.on("activate", async () => { if (BrowserWindow.getAllWindows().length === 0) await createLauncherWindow() }) }) app.on("window-all-closed", () => { app.quit() }) ipcMain.on("call", async (event, data) => { switch (data.method) { case "hardware::ramInformation": launcherWindow.webContents.send("hardware::ramInformation", { totalRam: Math.round(os.totalmem() / 1024 / 1024 * 100) / 100, avaibleRam: Math.round(os.freemem() / 1024 / 1024 * 100) / 100, }) break case "server::ping": const status = await serverPing.fetchServerStatus() launcherWindow.webContents.send("Response", status) break case "window::close": launcherWindow.close() app.quit() break case "skin::set": const file = await dialog.showOpenDialog(launcherWindow, { filters: [ { name: "Images", extensions: ["png", "jpg", "jpeg"] } ], properties: ["openFile", "dontAddToRecent", "showHiddenFiles"], title: "Sélectionner l'image de votre skin", securityScopedBookmarks: true }) if (!file.canceled) { const confirmDialog = await dialog.showMessageBox(launcherWindow, { type: "question", message: "Êtes-vous sûr de vouloir changer votre skin ?", buttons: [ "Oui", "Annuler" ], title: "Confirmer le changement de skin" }) confirmDialog.response == 0 ? skinPath = file.filePaths[0] : skinPath = null } break case "auth::mojang": if (data.args.trim() != "") { auth = Authenticator.getAuth(data.args.username, data.args.password) await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html")) } else { dialog.showErrorBox("Erreur", "Le mot de passe n'est pas défini. Les comptes crackés ne sont pas supporté par le launcher.") } break case "auth::microsoft": const authManager = new msmc.Auth("select_account") try { const xboxManager = await authManager.launch("raw") const token = await xboxManager.getMinecraft() auth = token.mclc() console.log(auth) await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html")) } catch (error) { console.log(error) if (error == "error.gui.closed") { launcherWindow.webContents.send("Response") } } break case "auth::refresh": const user = data.args.user if (user.meta?.type == "msa") { try { const authManager = new msmc.Auth("none") const xboxManager = await authManager.refresh(user.meta.refresh) const minecraft = await xboxManager.getMinecraft() auth = minecraft.mclc() await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html")) } catch (error) { dialog.showErrorBox("Erreur lors de la connexion via token", error) console.log(error) launcherWindow.webContents.send("Response") } } else { try { auth = Authenticator.refreshAuth(user.access_token, user.client_token) await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html")) } catch (error) { dialog.showErrorBox("Erreur lors de la connexion via token", error) console.log(error) launcherWindow.webContents.send("Response") } } break case "shell::openExternal": shell.openExternal(data.args.url) break case "audio::mute": launcherWindow.webContents.setAudioMuted(true) break case "audio::unmute": launcherWindow.webContents.setAudioMuted(false) break case "player::profile": await launcherWindow.webContents.send("Response", auth) break } })