diff --git a/src/main/events/catalogue/get-trending-games.ts b/src/main/events/catalogue/get-trending-games.ts index 364ceeb9..55a47219 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..aed0c2fa 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -60,7 +60,7 @@ app.whenReady().then(async () => { await loadState(); const language = await db.get(levelKeys.language, { - valueEncoding: "utf-8", + valueEncoding: "utf8", }); if (language) i18n.changeLanguage(language); diff --git a/src/main/level/sublevels/keys.ts b/src/main/level/sublevels/keys.ts index 12143917..801fc916 100644 --- a/src/main/level/sublevels/keys.ts +++ b/src/main/level/sublevels/keys.ts @@ -14,4 +14,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..2bf8ff41 100644 --- a/src/main/services/python-rpc.ts +++ b/src/main/services/python-rpc.ts @@ -1,4 +1,4 @@ -import axios from "axios"; +import axios, { AxiosInstance } from "axios"; import cp from "node:child_process"; import fs from "node:fs"; @@ -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,10 @@ 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"); + public static rpc: AxiosInstance; 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 logStderr(readable: Readable | null) { if (!readable) return; @@ -48,14 +42,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 +133,13 @@ export class PythonRPC { this.pythonProcess = childProcess; } + + this.rpc = axios.create({ + baseURL: `http://localhost:${this.RPC_PORT}`, + headers: { + "x-hydra-rpc-password": rpcPassword, + }, + }); } public static kill() {