diff --git a/src/main/events/catalogue/get-trending-games.ts b/src/main/events/catalogue/get-trending-games.ts index 03faa9cd..98b09136 100644 --- a/src/main/events/catalogue/get-trending-games.ts +++ b/src/main/events/catalogue/get-trending-games.ts @@ -6,7 +6,7 @@ import type { TrendingGame } from "@types"; const getTrendingGames = async (_event: Electron.IpcMainInvokeEvent) => { const language = await db .get(levelKeys.language, { - valueEncoding: "utf-8", + valueEncoding: "utf8", }) .then((language) => language || "en"); diff --git a/src/main/events/misc/get-badges.ts b/src/main/events/misc/get-badges.ts index 7f4bc3ea..c1d62782 100644 --- a/src/main/events/misc/get-badges.ts +++ b/src/main/events/misc/get-badges.ts @@ -6,7 +6,7 @@ import { db, levelKeys } from "@main/level"; const getBadges = async (_event: Electron.IpcMainInvokeEvent) => { const language = await db .get(levelKeys.language, { - valueEncoding: "utf-8", + valueEncoding: "utf8", }) .then((language) => language || "en"); diff --git a/src/main/events/user-preferences/update-user-preferences.ts b/src/main/events/user-preferences/update-user-preferences.ts index 7a481837..b3224f1c 100644 --- a/src/main/events/user-preferences/update-user-preferences.ts +++ b/src/main/events/user-preferences/update-user-preferences.ts @@ -16,7 +16,7 @@ const updateUserPreferences = async ( if (preferences.language) { await db.put(levelKeys.language, preferences.language, { - valueEncoding: "utf-8", + valueEncoding: "utf8", }); i18next.changeLanguage(preferences.language); diff --git a/src/main/index.ts b/src/main/index.ts index 6999cf42..ebe59b36 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -59,9 +59,11 @@ app.whenReady().then(async () => { await loadState(); - const language = await db.get(levelKeys.language, { - valueEncoding: "utf-8", - }); + const language = await db + .get(levelKeys.language, { + valueEncoding: "utf8", + }) + .catch(() => "en"); if (language) i18n.changeLanguage(language); diff --git a/src/main/level/sublevels/keys.ts b/src/main/level/sublevels/keys.ts index 871bb996..cab7c4f7 100644 --- a/src/main/level/sublevels/keys.ts +++ b/src/main/level/sublevels/keys.ts @@ -15,4 +15,5 @@ export const levelKeys = { userPreferences: "userPreferences", language: "language", screenState: "screenState", + rpcPassword: "rpcPassword", }; diff --git a/src/main/services/achievements/get-game-achievement-data.ts b/src/main/services/achievements/get-game-achievement-data.ts index c18ad4cc..0f351dcb 100644 --- a/src/main/services/achievements/get-game-achievement-data.ts +++ b/src/main/services/achievements/get-game-achievement-data.ts @@ -25,7 +25,7 @@ export const getGameAchievementData = async ( const language = await db .get(levelKeys.language, { - valueEncoding: "utf-8", + valueEncoding: "utf8", }) .then((language) => language || "en"); diff --git a/src/main/services/python-rpc.ts b/src/main/services/python-rpc.ts index f3ad1fb0..2179ffdc 100644 --- a/src/main/services/python-rpc.ts +++ b/src/main/services/python-rpc.ts @@ -7,7 +7,8 @@ import crypto from "node:crypto"; import { pythonRpcLogger } from "./logger"; import { Readable } from "node:stream"; -import { app, dialog } from "electron"; +import { app, dialog, safeStorage } from "electron"; +import { db, levelKeys } from "@main/level"; interface GamePayload { game_id: string; @@ -30,17 +31,12 @@ const rustBinaryNameByPlatform: Partial> = { export class PythonRPC { public static readonly BITTORRENT_PORT = "5881"; public static readonly RPC_PORT = "8084"; - private static readonly RPC_PASSWORD = crypto.randomBytes(32).toString("hex"); - - private static pythonProcess: cp.ChildProcess | null = null; - public static readonly rpc = axios.create({ baseURL: `http://localhost:${this.RPC_PORT}`, - headers: { - "x-hydra-rpc-password": this.RPC_PASSWORD, - }, }); + private static pythonProcess: cp.ChildProcess | null = null; + private static logStderr(readable: Readable | null) { if (!readable) return; @@ -48,14 +44,37 @@ export class PythonRPC { readable.on("data", pythonRpcLogger.log); } - public static spawn( + private static async getRPCPassword() { + const existingPassword = await db.get(levelKeys.rpcPassword, { + valueEncoding: "utf8", + }); + + if (existingPassword) + return safeStorage.decryptString(Buffer.from(existingPassword, "hex")); + + const newPassword = crypto.randomBytes(32).toString("hex"); + + await db.put( + levelKeys.rpcPassword, + safeStorage.encryptString(newPassword).toString("hex"), + { + valueEncoding: "utf8", + } + ); + + return newPassword; + } + + public static async spawn( initialDownload?: GamePayload, initialSeeding?: GamePayload[] ) { + const rpcPassword = await this.getRPCPassword(); + const commonArgs = [ this.BITTORRENT_PORT, this.RPC_PORT, - this.RPC_PASSWORD, + rpcPassword, initialDownload ? JSON.stringify(initialDownload) : "", initialSeeding ? JSON.stringify(initialSeeding) : "", app.isPackaged @@ -116,6 +135,8 @@ export class PythonRPC { this.pythonProcess = childProcess; } + + this.rpc.defaults.headers.common["x-hydra-rpc-password"] = rpcPassword; } public static kill() {