This commit is contained in:
Gilles Lazures 2025-05-01 18:42:39 +02:00
parent 6ee1cd793f
commit 5657184b08
8 changed files with 1112 additions and 49 deletions

View File

@ -27,6 +27,9 @@
</button>
</summary>
<article>
<button class="classic" style="width: 100%;" onclick="system.call('app::devtools')">
Déconnexion
</button>
<button class="classic" style="background-color: #aa3939; width: 100%;" onclick="logout()">
Déconnexion
</button>

View File

@ -3,12 +3,15 @@
"base": "http://localhost:8535",
"endpoints": {
"fileHash": "/api/v1/file/hash/",
"checkBanStatus": "/api/v1/ban/iam"
"checkBanStatus": "/api/v1/ban/iam",
"telemetry": "/api/v1/telemetry",
"gameFiles": "/api/v1/file/game",
"downloadFile": "/api/v1/file/game/download"
},
"websockets": {
"base": "wss://localhost:8535",
"rooms": {
"updateGameFiles": "/game/updates"
"base": {
"host": "wss://localhost",
"port": "8535"
}
}
},

89
main.js
View File

@ -1,14 +1,24 @@
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 os = require("node:os")
const fs = require("node:fs")
const path = require("node:path")
const hwid = require("./modules/hwid")
const serverPing = require("./modules/serverPing")
const gameOptions = require("./modules/gameOptions")
const launcherSettings = require("./modules/launcherSettings")
const config = require("./config.json")
const { Authenticator } = require("minecraft-launcher-core")
let launcherWindow, auth
const { Authenticator, Client } = require("minecraft-launcher-core")
const fileManager = require("./modules/fileManager")
const launcher = new Client()
const { io } = require("socket.io-client")
const download = require("download")
const socket = io({
host: config.api.websockets.base.host,
port: config.api.websockets.base.port
})
let launcherWindow, auth, gamePlayable = false
async function createLauncherWindow() {
gameOptions.initOptions(path.join(app.getPath("appData"), ".catboat", "options.txt"))
@ -62,7 +72,6 @@ async function createLauncherWindow() {
redirectURL: redirectUrl
})
})
session.defaultSession.webRequest.onHeadersReceived({
urls: [
"https://www.twitch.tv/*",
@ -87,7 +96,7 @@ async function createLauncherWindow() {
`)
}
} catch (error) {
dialog.showErrorBox("Erreur", error)
dialog.showErrorBox("Erreur", error.toString())
}
} else {
dialog.showErrorBox("Connexion internet", "Le launcher requiert une connexion internet.")
@ -171,6 +180,7 @@ ipcMain.on("call", async (event, data) => {
case "auth::mojang":
if (data.args.trim() != "") {
auth = Authenticator.getAuth(data.args.username, data.args.password)
await fetch(`${config.api.base}${config.api.endpoints.telemetry}/${hwid.getHWID()}/${(await auth).uuid}`)
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.")
@ -182,10 +192,10 @@ ipcMain.on("call", async (event, data) => {
const xboxManager = await authManager.launch("raw")
const token = await xboxManager.getMinecraft()
auth = token.mclc()
console.log(auth)
await fetch(`${config.api.base}${config.api.endpoints.telemetry}/${hwid.getHWID()}/${auth.uuid}`)
await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html"))
} catch (error) {
console.log(error)
console.error(error)
if (error == "error.gui.closed") {
launcherWindow.webContents.send("Response<auth::microsoft>")
}
@ -200,18 +210,20 @@ ipcMain.on("call", async (event, data) => {
const minecraft = await xboxManager.getMinecraft()
auth = minecraft.mclc()
await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html"))
await fetch(`${config.api.base}${config.api.endpoints.telemetry}/${hwid.getHWID()}/${auth.uuid}`)
} catch (error) {
dialog.showErrorBox("Erreur lors de la connexion via token", error)
console.log(error)
console.error(error)
launcherWindow.webContents.send("Response<auth::refresh>")
}
} else {
try {
auth = Authenticator.refreshAuth(user.access_token, user.client_token)
await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html"))
await fetch(`${config.api.base}${config.api.endpoints.telemetry}/${hwid.getHWID()}/${(await auth).uuid}`)
} catch (error) {
dialog.showErrorBox("Erreur lors de la connexion via token", error)
console.log(error)
console.error(error)
launcherWindow.webContents.send("Response<auth::refresh>")
}
}
@ -255,5 +267,62 @@ ipcMain.on("call", async (event, data) => {
const $launcherSettings = launcherSettings.readSettings()
launcherWindow.webContents.send("Response<settings::read>", $launcherSettings)
break
case "game::launch":
const downloadQueue = []
const remoteFiles = await fileManager.getRemoteFiles()
const localFiles = fs.readdirSync(path.join(app.getPath("appData"), ".catboat"), { recursive: true })
launcherWindow.setProgressBar(10, {
mode: "indeterminate"
})
for (const remoteFile of remoteFiles) {
try {
const localFile = localFiles.find(file => file === remoteFile)
if (!localFile) {
downloadQueue.push(remoteFile)
continue
}
const localHash = await fileManager.getFileHash(path.join(app.getPath("appData"), ".catboat", localFile))
const remoteHash = await fileManager.getRemoteFileHash(localFile)
if (localHash != remoteHash) {
downloadQueue.push(localFile)
}
} catch (error) {
console.error(error)
break
}
}
for (const localFile of localFiles) {
if (!remoteFiles.find(remoteFile => remoteFile.path == localFile) && localFile.startsWith("/mods")) {
fs.unlinkSync(path.join(app.getPath("appData"), ".catboat", localFile))
}
}
for (const item of downloadQueue) {
const url = `${config.api.base}${config.api.endpoints.downloadFile}/${new String(item).replace(/\\/g, "/")}`
try {
await download(url, path.join(app.getPath("appData"), ".catboat", path.dirname(item)))
launcherWindow.setProgressBar(((downloadQueue.indexOf(item) + 1) / downloadQueue.length) * 100, {
mode: "normal"
})
} catch (error) {
launcherWindow.setProgressBar(((downloadQueue.indexOf(item) + 1) / downloadQueue.length) * 100, {
mode: "error"
})
dialog.showErrorBox("Erreur lors du téléchargement des fichiers", error.toString())
continue
}
}
launcherWindow.setProgressBar(0, {
mode: "none"
})
dialog.showMessageBox(launcherWindow, {
title: "Téléchargement des fichiers",
message: "Téléchargement fini."
})
break
case "app::devtools":
launcherWindow.webContents.openDevTools()
break
}
})

View File

@ -1,18 +0,0 @@
const msmc = require("msmc")
const { Authenticator } = require("minecraft-launcher-core")
async function getMicrosoftAuth() {
const authManager = new msmc.Auth("select_account")
const xboxManager = await authManager.launch("raw")
const token = await xboxManager.getMinecraft()
return token.mclc()
}
function getMojangAuth(username, password) {
return Authenticator.getAuth(username, password)
}
module.exports = {
getMicrosoftAuth,
getMojangAuth
}

View File

@ -4,6 +4,17 @@ const https = require("node:https")
const crypto = require("node:crypto")
const config = require("../config.json")
async function getRemoteFiles() {
try {
const response = await fetch(`${config.api.base}${config.api.endpoints.gameFiles}`)
console.log(response.url)
const json = await response.json()
return json
} catch (error) {
throw error
}
}
async function downloadFile(url, destination, hash) {
const file = fs.createWriteStream(destination)
const protocol = url.startsWith("https://") ? http : https
@ -73,8 +84,21 @@ async function checkFilesHash(root) {
}
}
async function getRemoteFileHash(filePath) {
try {
const response = await fetch(`${config.api.base}${config.api.endpoints.fileHash}/${filePath}`)
const text = await response.text()
return text
} catch (error) {
throw error
}
}
module.exports = {
getFileHash,
downloadFile,
checkFileHash,
checkFilesHash
checkFilesHash,
getRemoteFiles,
getRemoteFileHash
}

0
modules/gameFiles.js Normal file
View File

1013
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,7 @@
},
"dependencies": {
"discord-rpc": "^4.0.1",
"download": "^8.0.0",
"minecraft-launcher-core": "^3.18.2",
"msmc": "^5.0.5",
"socket.io-client": "^4.8.1"