chore: merge with main

This commit is contained in:
Hydra 2024-04-28 19:21:14 +01:00
commit 4636571a25
16 changed files with 1567 additions and 1173 deletions

View File

@ -19,7 +19,7 @@
"start": "electron-vite preview", "start": "electron-vite preview",
"dev": "electron-vite dev", "dev": "electron-vite dev",
"build": "npm run typecheck && electron-vite build", "build": "npm run typecheck && electron-vite build",
"postinstall": "electron-builder install-app-deps", "postinstall": "electron-builder install-app-deps && node ./postinstall.js",
"build:unpack": "npm run build && electron-builder --dir", "build:unpack": "npm run build && electron-builder --dir",
"build:win": "npm run build && electron-builder --win", "build:win": "npm run build && electron-builder --win",
"build:mac": "electron-vite build && electron-builder --mac", "build:mac": "electron-vite build && electron-builder --mac",
@ -56,7 +56,7 @@
"react-loading-skeleton": "^3.4.0", "react-loading-skeleton": "^3.4.0",
"react-redux": "^9.1.1", "react-redux": "^9.1.1",
"react-router-dom": "^6.22.3", "react-router-dom": "^6.22.3",
"tasklist": "^5.0.0", "tough-cookie": "^4.1.3",
"typeorm": "^0.3.20", "typeorm": "^0.3.20",
"windows-1251": "^3.0.4", "windows-1251": "^3.0.4",
"winston": "^3.13.0", "winston": "^3.13.0",

12
postinstall.cjs Normal file
View File

@ -0,0 +1,12 @@
const fs = require("fs");
if (process.platform === "win32") {
if (!fs.existsSync("resources/dist")) {
fs.mkdirSync("resources/dist");
}
fs.copyFileSync(
"node_modules/ps-list/vendor/fastlist-0.3.0-x64.exe",
"resources/dist/fastlist.exe"
);
}

View File

@ -16,8 +16,8 @@
"paused": "{{title}} (Pausado)", "paused": "{{title}} (Pausado)",
"downloading": "{{title}} ({{percentage}} - Descargando…)", "downloading": "{{title}} ({{percentage}} - Descargando…)",
"filter": "Filtrar biblioteca", "filter": "Filtrar biblioteca",
"home": "Hogar", "home": "Inicio",
"follow_us": "Síganos" "follow_us": "Síguenos"
}, },
"header": { "header": {
"search": "Buscar", "search": "Buscar",
@ -25,7 +25,7 @@
"downloads": "Descargas", "downloads": "Descargas",
"search_results": "Resultados de búsqueda", "search_results": "Resultados de búsqueda",
"settings": "Ajustes", "settings": "Ajustes",
"home": "Início" "home": "Inicio"
}, },
"bottom_panel": { "bottom_panel": {
"no_downloads_in_progress": "Sin descargas en progreso", "no_downloads_in_progress": "Sin descargas en progreso",
@ -70,7 +70,7 @@
"install": "Instalar", "install": "Instalar",
"play": "Jugar", "play": "Jugar",
"not_played_yet": "Aún no has jugado a {{title}}", "not_played_yet": "Aún no has jugado a {{title}}",
"close": "Cerca", "close": "Cerrar",
"deleting": "Eliminando instalador…", "deleting": "Eliminando instalador…",
"playing_now": "Jugando ahora", "playing_now": "Jugando ahora",
"last_time_played": "Jugado por última vez {{period}}" "last_time_played": "Jugado por última vez {{period}}"
@ -100,7 +100,7 @@
"checking_files": "Verificando archivos…", "checking_files": "Verificando archivos…",
"starting_download": "Iniciando descarga…", "starting_download": "Iniciando descarga…",
"remove_from_list": "Eliminar", "remove_from_list": "Eliminar",
"delete": "Quitar instalador", "delete": "Eliminar instalador",
"delete_modal_description": "Esto eliminará todos los archivos de instalación de su computadora.", "delete_modal_description": "Esto eliminará todos los archivos de instalación de su computadora.",
"delete_modal_title": "¿Está seguro?", "delete_modal_title": "¿Está seguro?",
"deleting": "Eliminando instalador…", "deleting": "Eliminando instalador…",
@ -112,8 +112,8 @@
"notifications": "Notificaciones", "notifications": "Notificaciones",
"enable_download_notifications": "Cuando se completa una descarga", "enable_download_notifications": "Cuando se completa una descarga",
"enable_repack_list_notifications": "Cuando se añade un repack nuevo", "enable_repack_list_notifications": "Cuando se añade un repack nuevo",
"telemetry": "Telemetria", "telemetry": "Telemetría",
"telemetry_description": "Habilitar estadísticas de uso anónimas" "telemetry_description": "Habilitar recopilación de datos de manera anónima"
}, },
"notifications": { "notifications": {
"download_complete": "Descarga completada", "download_complete": "Descarga completada",
@ -132,7 +132,7 @@
"binary_not_found_modal": { "binary_not_found_modal": {
"title": "Programas no instalados", "title": "Programas no instalados",
"description": "Los ejecutables de Wine o Lutris no se encontraron en su sistema", "description": "Los ejecutables de Wine o Lutris no se encontraron en su sistema",
"instructions": "Comprueba la forma correcta de instalar cualquiera de ellos en tu distro Linux para que el juego pueda ejecutarse con normalidad" "instructions": "Comprueba como instalar de forma correcta uno de los dos en tu distro de Linux para ejecutar el juego con normalidad"
}, },
"catalogue": { "catalogue": {
"next_page": "Siguiente página", "next_page": "Siguiente página",

View File

@ -25,7 +25,7 @@
"downloads": "Téléchargements", "downloads": "Téléchargements",
"search_results": "Résultats de la recherche", "search_results": "Résultats de la recherche",
"settings": "Paramètres", "settings": "Paramètres",
"home": "Maison" "home": "Accueil"
}, },
"bottom_panel": { "bottom_panel": {
"no_downloads_in_progress": "Aucun téléchargement en cours", "no_downloads_in_progress": "Aucun téléchargement en cours",

View File

@ -21,6 +21,8 @@ const getRandomGame = async () => {
} }
} }
} }
return null;
}); });
}; };

View File

@ -1,12 +1,33 @@
import psList from "ps-list"; import psList from "ps-list";
import { tasklist } from "tasklist"; import path from "node:path";
import childProcess from "node:child_process";
import { promisify } from "node:util";
import { app } from "electron";
const TEN_MEGABYTES = 1000 * 1000 * 10;
const execFile = promisify(childProcess.execFile);
export const getProcesses = async () => { export const getProcesses = async () => {
if (process.platform === "win32") { if (process.platform == "win32") {
return tasklist().then((tasks) => const binaryPath = app.isPackaged
tasks.map((task) => ({ ...task, name: task.imageName })) ? path.join(process.resourcesPath, "dist", "fastlist.exe")
); : path.join(__dirname, "..", "..", "resources", "dist", "fastlist.exe");
}
const { stdout } = await execFile(binaryPath, {
maxBuffer: TEN_MEGABYTES,
windowsHide: true,
});
return stdout
.trim()
.split("\r\n")
.map((line) => line.split("\t"))
.map(([pid, ppid, name]) => ({
pid: Number.parseInt(pid, 10),
ppid: Number.parseInt(ppid, 10),
name,
}));
} else {
return psList(); return psList();
}
}; };

View File

@ -48,7 +48,7 @@ Promise.all([writePipe.createPipe(), readPipe.createPipe()]).then(async () => {
}); });
} }
readPipe.socket.on("data", (data) => { readPipe.socket?.on("data", (data) => {
TorrentClient.onSocketData(data); TorrentClient.onSocketData(data);
}); });
}); });

View File

@ -1,7 +1,6 @@
import path from "node:path"; import path from "node:path";
import { IsNull, Not } from "typeorm"; import { IsNull, Not } from "typeorm";
import { gameRepository } from "@main/repository"; import { gameRepository } from "@main/repository";
import { getProcesses } from "@main/helpers"; import { getProcesses } from "@main/helpers";
import { WindowManager } from "./window-manager"; import { WindowManager } from "./window-manager";
@ -9,27 +8,34 @@ import { WindowManager } from "./window-manager";
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
export const startProcessWatcher = async () => { export const startProcessWatcher = async () => {
const sleepTime = 100; const sleepTime = 300;
const gamesPlaytime = new Map<number, number>(); const gamesPlaytime = new Map<number, number>();
// eslint-disable-next-line no-constant-condition // eslint-disable-next-line no-constant-condition
while (true) { while (true) {
await sleep(sleepTime);
const games = await gameRepository.find({ const games = await gameRepository.find({
where: { where: {
executablePath: Not(IsNull()), executablePath: Not(IsNull()),
}, },
}); });
if (games.length == 0) {
continue;
}
const processes = await getProcesses(); const processes = await getProcesses();
for (const game of games) { for (const game of games) {
const gameProcess = processes.find((runningProcess) => { const executablePath = game.executablePath!;
const basename = path.win32.basename(game.executablePath); const basename = path.win32.basename(executablePath);
const basenameWithoutExtension = path.win32.basename( const basenameWithoutExtension = path.win32.basename(
game.executablePath, executablePath,
path.extname(game.executablePath) path.extname(executablePath)
); );
const gameProcess = processes.find((runningProcess) => {
if (process.platform === "win32") { if (process.platform === "win32") {
return runningProcess.name === basename; return runningProcess.name === basename;
} }
@ -41,7 +47,7 @@ export const startProcessWatcher = async () => {
if (gameProcess) { if (gameProcess) {
if (gamesPlaytime.has(game.id)) { if (gamesPlaytime.has(game.id)) {
const zero = gamesPlaytime.get(game.id); const zero = gamesPlaytime.get(game.id) ?? 0;
const delta = performance.now() - zero; const delta = performance.now() - zero;
if (WindowManager.mainWindow) { if (WindowManager.mainWindow) {
@ -55,26 +61,15 @@ export const startProcessWatcher = async () => {
gameRepository.update(game.id, { gameRepository.update(game.id, {
lastTimePlayed: new Date().toUTCString(), lastTimePlayed: new Date().toUTCString(),
}); });
gamesPlaytime.set(game.id, performance.now());
await sleep(sleepTime);
continue;
} }
gamesPlaytime.set(game.id, performance.now()); gamesPlaytime.set(game.id, performance.now());
} else if (gamesPlaytime.has(game.id)) {
await sleep(sleepTime);
continue;
}
if (gamesPlaytime.has(game.id)) {
gamesPlaytime.delete(game.id); gamesPlaytime.delete(game.id);
if (WindowManager.mainWindow) { if (WindowManager.mainWindow) {
WindowManager.mainWindow.webContents.send("on-game-close", game.id); WindowManager.mainWindow.webContents.send("on-game-close", game.id);
} }
} }
await sleep(sleepTime);
} }
} }
}; };

View File

@ -1,13 +1,9 @@
import type { Repack } from "@main/entity";
import { repackRepository } from "@main/repository"; import { repackRepository } from "@main/repository";
import type { GameRepack } from "@types"; import { QueryDeepPartialEntity } from "typeorm/query-builder/QueryPartialEntity";
export type GameRepackInput = Omit< export const savePage = async (repacks: QueryDeepPartialEntity<Repack>[]) =>
GameRepack,
"id" | "repackerFriendlyName" | "createdAt" | "updatedAt"
>;
export const savePage = async (repacks: GameRepackInput[]) =>
Promise.all( Promise.all(
repacks.map((repack) => repackRepository.insert(repack).catch(() => {})) repacks.map((repack) => repackRepository.insert(repack).catch(() => {}))
); );

View File

@ -31,11 +31,12 @@ const formatXatabDownloadSize = (str: string) =>
const getXatabRepack = async (url: string) => { const getXatabRepack = async (url: string) => {
const data = await requestWebPage(url); const data = await requestWebPage(url);
const { window } = new JSDOM(data); const { window } = new JSDOM(data);
const { document } = window;
const $uploadDate = window.document.querySelector(".entry__date"); const $uploadDate = document.querySelector(".entry__date");
const $size = window.document.querySelector(".entry__info-size"); const $size = document.querySelector(".entry__info-size");
const $downloadButton = window.document.querySelector( const $downloadButton = document.querySelector(
".download-torrent" ".download-torrent"
) as HTMLAnchorElement; ) as HTMLAnchorElement;
@ -74,8 +75,10 @@ export const getNewRepacksFromXatab = async (
...repack, ...repack,
page, page,
}); });
} catch (err) { } catch (err: unknown) {
logger.error(err.message, { method: "getNewRepacksFromXatab" }); logger.error((err as Error).message, {
method: "getNewRepacksFromXatab",
});
} }
} }

View File

@ -13,8 +13,8 @@ export const requestSteam250 = async (path: string) => {
const steamGameUrl = ($title as HTMLAnchorElement).href; const steamGameUrl = ($title as HTMLAnchorElement).href;
return { return {
title: $title.textContent, title: $title.textContent!,
objectID: steamGameUrl.split("/").pop(), objectID: steamGameUrl.split("/").pop()!,
}; };
}); });
}); });

View File

@ -47,7 +47,7 @@ export class TorrentClient {
const commonArgs = [BITTORRENT_PORT, writePipePath, readPipePath]; const commonArgs = [BITTORRENT_PORT, writePipePath, readPipePath];
if (app.isPackaged) { if (app.isPackaged) {
const binaryName = binaryNameByPlatform[process.platform]; const binaryName = binaryNameByPlatform[process.platform]!;
const binaryPath = path.join( const binaryPath = path.join(
process.resourcesPath, process.resourcesPath,
"hydra-download-manager", "hydra-download-manager",
@ -133,7 +133,7 @@ export class TorrentClient {
relations: { repack: true }, relations: { repack: true },
}); });
if (game.progress === 1) { if (game?.progress === 1) {
const userPreferences = await userPreferencesRepository.findOne({ const userPreferences = await userPreferencesRepository.findOne({
where: { id: 1 }, where: { id: 1 },
}); });
@ -153,7 +153,7 @@ export class TorrentClient {
} }
} }
if (WindowManager.mainWindow) { if (WindowManager.mainWindow && game) {
const progress = this.getGameProgress(game); const progress = this.getGameProgress(game);
WindowManager.mainWindow.setProgressBar(progress === 1 ? -1 : progress); WindowManager.mainWindow.setProgressBar(progress === 1 ? -1 : progress);

View File

@ -6,7 +6,7 @@ import { ShopDetails } from "@types";
import { getSteamLanguage, steamUrlBuilder } from "@renderer/helpers"; import { getSteamLanguage, steamUrlBuilder } from "@renderer/helpers";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
const FEATURED_GAME_ID = "377160"; const FEATURED_GAME_ID = "253230";
export function Hero() { export function Hero() {
const [featuredGameDetails, setFeaturedGameDetails] = const [featuredGameDetails, setFeaturedGameDetails] =
@ -36,7 +36,7 @@ export function Hero() {
> >
<div className={styles.backdrop}> <div className={styles.backdrop}>
<AsyncImage <AsyncImage
src="https://cdn2.steamgriddb.com/hero/e7a7ba56b1be30e178cd52820e063396.png" src="https://cdn2.steamgriddb.com/hero/a6115ed32394915aac1e5502382eaaea.jpg"
alt={featuredGameDetails?.name} alt={featuredGameDetails?.name}
className={styles.heroMedia} className={styles.heroMedia}
/> />

View File

@ -38,11 +38,6 @@ export interface SteamAppDetails {
}; };
} }
export type ShopDetails = SteamAppDetails & {
objectID: string;
repacks: GameRepack[];
};
export interface GameRepack { export interface GameRepack {
id: number; id: number;
title: string; title: string;
@ -55,6 +50,11 @@ export interface GameRepack {
updatedAt: Date; updatedAt: Date;
} }
export type ShopDetails = SteamAppDetails & {
objectID: string;
repacks: GameRepack[];
};
export interface TorrentFile { export interface TorrentFile {
path: string; path: string;
length: number; length: number;

2581
yarn.lock

File diff suppressed because it is too large Load Diff