first commit

-  Discord RPC 🕹
  -  File protection 🔏
  -  Authentication 🔑
This commit is contained in:
Gilles Lazures 2025-04-26 08:09:46 +02:00
parent 36c728dfb7
commit 3a81447b9c
10 changed files with 5728 additions and 0 deletions

2
.gitignore vendored
View File

@ -130,3 +130,5 @@ dist
.yarn/install-state.gz
.pnp.*
# tests
test.js

0
app/assets/css/index.css Normal file
View File

0
app/index.html Normal file
View File

8
config.json Normal file
View File

@ -0,0 +1,8 @@
{
"api": {
"base": "http://localhost:8535",
"endpoints": {
"fileHash": "/api/v1/file/hash/"
}
}
}

36
main.js Normal file
View File

@ -0,0 +1,36 @@
const { BrowserWindow, app, net, dialog } = require("electron")
const path = require("node:path")
let launcherWindow
async function createLauncherWindow() {
if (net.isOnline()) {
launcherWindow = new BrowserWindow({
frame: false,
width: 900,
height: 600,
minWidth: 900,
minHeight: 600,
titleBarStyle: "hidden",
autoHideMenuBar: true,
roundedCorners: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, "app", "index.html")
}
})
} else {
dialog.showErrorBox("Le launcher requiert une connexion internet.")
}
}
app.whenReady().then(() => {
createLauncherWindow()
app.on("activate", async () => {
if (BrowserWindow.getAllWindows().length === 0) await createLauncherWindow()
})
})
app.on("window-all-closed", () => {
app.quit()
})

17
modules/authenticate.js Normal file
View File

@ -0,0 +1,17 @@
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
}

80
modules/fileManager.js Normal file
View File

@ -0,0 +1,80 @@
const fs = require("node:fs")
const http = require("node:http")
const https = require("node:https")
const crypto = require("node:crypto")
const config = require("../config.json")
async function downloadFile(url, destination, hash) {
const file = fs.createWriteStream(destination)
const protocol = url.startsWith("https://") ? http : https
protocol.get(url, (response) => {
response.pipe(file)
file.on("error", (error) => {
throw error
})
file.on("finish", async () => {
file.close()
try {
if (getFileHash(destination) != hash) {
fs.unlinkSync(destination)
await downloadFile(url, destination, hash)
}
} catch (error) {
reject(error)
}
})
})
}
function getFileHash(filePath) {
return new Promise((resolve, reject) => {
const hash = crypto.createHash("sha256")
const file = fs.createReadStream(filePath)
file.on("error", (err) => {
reject(err)
})
file.on("data", (chunk) => {
hash.update(chunk)
})
file.on("end", () => {
resolve(hash.digest("hex"))
})
})
}
async function checkFileHash(filePath) {
try {
const response = await fetch(`${config.api.base}${config.api.endpoints.fileHash}${filePath}`)
const json = await response.json()
if (json.error) {
return json
} else {
if ((await getFileHash(filePath)) !== json.hash) {
return false
} else {
return true
}
}
} catch (error) {
throw error
}
}
async function checkFilesHash(root) {
const files = await fs.promises.readdir(root, { recursive: true })
for (const file of files) {
try {
await checkFileHash(file)
} catch (error) {
throw error
}
}
}
module.exports = {
downloadFile,
checkFileHash,
checkFilesHash
}

50
modules/rpc.js Normal file
View File

@ -0,0 +1,50 @@
const RPC = require("discord-rpc")
class DiscordRPC {
constructor() {
readonly: this.activity = {
details: "Actif dans le launcher",
assets: {
large_image: "logo",
large_text: "CatBoat Minecraft Launcher"
},
buttons: [
{
label: "Discord",
url: "https://discord.com/invite/catboat"
},
{
label: "CatBoat",
url: "https://catboat.fr/"
}
],
instance: true
}
readonly: this.client = new RPC.Client({ transport: "ipc" })
this.isEnabled = false
}
startRichPresence() {
if (!this.isEnabled) {
this.client.on("ready", () => {
this.client.request("SET_ACTIVITY", { pid: process.pid, activity: this.activity })
console.log("The Discord Rich Presence has been set successfully.")
})
this.client.login({ clientId: "1365563093157154868" }).catch(e => {
console.log(e)
console.log("Silent client detected: the activity status has been disabled.")
this.isEnabled = false
}).then(r => this.isEnabled = true)
.catch(err => console.log)
}
}
stopRichPresence() {
if (this.isEnabled) {
this.client.destroy()
this.isEnabled = false
}
}
}
module.exports = new DiscordRPC()

5507
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

28
package.json Normal file
View File

@ -0,0 +1,28 @@
{
"name": "catboat-launcher",
"version": "0.0.1-alpha",
"description": "a simple minecraft launcher for catboat",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://gitea.azures.fr/azures04/CatBoat-Launcher.git"
},
"author": {
"email": "gilleslazure04@gmail.com",
"name": "Gilles Lazure <azures04>",
"url": "https://gitea.azures.fr"
},
"license": "AGPL-3.0-or-later",
"devDependencies": {
"electron": "^35.2.1",
"electron-builder": "^26.0.12"
},
"dependencies": {
"discord-rpc": "^4.0.1",
"minecraft-launcher-core": "^3.18.2",
"msmc": "^5.0.5"
}
}