mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-16 00:43:00 -03:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e089ca8705 | ||
|
|
bf8fd0dacf | ||
|
|
c9b289cbde | ||
|
|
45b822ba10 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hydralauncher",
|
||||
"version": "3.6.1",
|
||||
"version": "3.6.2",
|
||||
"description": "Hydra",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "Los Broxas",
|
||||
|
||||
@@ -101,8 +101,13 @@ def process_list():
|
||||
auth_error = validate_rpc_password()
|
||||
if auth_error:
|
||||
return auth_error
|
||||
|
||||
iter_list = ['exe', 'pid', 'name']
|
||||
if sys.platform != 'win32':
|
||||
iter_list.append('cwd')
|
||||
iter_list.append('environ')
|
||||
|
||||
process_list = [proc.info for proc in psutil.process_iter(['exe', 'cwd', 'pid', 'name', 'environ'])]
|
||||
process_list = [proc.info for proc in psutil.process_iter(iter_list)]
|
||||
return jsonify(process_list), 200
|
||||
|
||||
@app.route("/profile-image", methods=["POST"])
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
"allow_nsfw_content": "Continuar",
|
||||
"refuse_nsfw_content": "No, gracias",
|
||||
"stats": "Estadísticas",
|
||||
"download_count": "Downloads",
|
||||
"download_count": "Descargas",
|
||||
"player_count": "Jugadores activos",
|
||||
"download_error": "Esta opción de descarga no está disponible.",
|
||||
"download": "Descargar",
|
||||
@@ -199,12 +199,12 @@
|
||||
"download_error_gofile_quota_exceeded": "Has excedido la cuota mensual de Gofile. Por favor espera a que se reinicie la cuota.",
|
||||
"download_error_real_debrid_account_not_authorized": "Tu cuenta de Real-Debrid no está autorizada para nueva descargas. Por favor, revisa los ajustes de tu cuenta e intenta de nuevo.",
|
||||
"download_error_not_cached_on_real_debrid": "Esta descarga no está disponible en Real-Debrid y el estado de descarga del sondeo de Real-Debrid aún no está disponible.",
|
||||
"download_error_not_cached_on_torbox": "Esta descarga no está disponible en TorBox y el estado de descarga del sondeo aún no está disponible.",
|
||||
"download_error_not_cached_on_torbox": "Esta descarga no está disponible en TorBox y aún no se puede verificar el estado de la descarga.",
|
||||
"game_added_to_favorites": "Juego añadido a favoritos",
|
||||
"game_removed_from_favorites": "Juego removido de favoritos",
|
||||
"invalid_wine_prefix_path": "Ruta de prefixo Wine inválida",
|
||||
"invalid_wine_prefix_path_description": "La ruta al prefixo Wine es inválida. Por favor, verifica la ruta y vuelve a intentarlo.",
|
||||
"missing_wine_prefix": ""
|
||||
"invalid_wine_prefix_path": "Ruta de prefijo de Wine inválida",
|
||||
"invalid_wine_prefix_path_description": "La ruta del prefijo Wine es inválida. Por favor, checa la ruta y vuelve a intentarlo.",
|
||||
"missing_wine_prefix": "Se requiere el prefijo Wine para crear una copia de seguridad en Linux"
|
||||
},
|
||||
"activation": {
|
||||
"title": "Activar Hydra",
|
||||
|
||||
@@ -1,17 +1,38 @@
|
||||
import type { GameShop, GameStats } from "@types";
|
||||
import { registerEvent } from "../register-event";
|
||||
import { HydraApi } from "@main/services";
|
||||
import { gamesStatsCacheSublevel, levelKeys } from "@main/level";
|
||||
|
||||
const LOCAL_CACHE_EXPIRATION = 1000 * 60 * 30; // 30 minutes
|
||||
|
||||
const getGameStats = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
objectId: string,
|
||||
shop: GameShop
|
||||
) => {
|
||||
const cachedStats = await gamesStatsCacheSublevel.get(
|
||||
levelKeys.game(shop, objectId)
|
||||
);
|
||||
|
||||
if (
|
||||
cachedStats &&
|
||||
cachedStats.updatedAt + LOCAL_CACHE_EXPIRATION > Date.now()
|
||||
) {
|
||||
return cachedStats;
|
||||
}
|
||||
|
||||
return HydraApi.get<GameStats>(
|
||||
`/games/stats`,
|
||||
{ objectId, shop },
|
||||
{ needsAuth: false }
|
||||
);
|
||||
).then(async (data) => {
|
||||
await gamesStatsCacheSublevel.put(levelKeys.game(shop, objectId), {
|
||||
...data,
|
||||
updatedAt: Date.now(),
|
||||
});
|
||||
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
registerEvent("getGameStats", getGameStats);
|
||||
|
||||
@@ -20,7 +20,6 @@ import "./library/create-game-shortcut";
|
||||
import "./library/close-game";
|
||||
import "./library/delete-game-folder";
|
||||
import "./library/get-game-by-object-id";
|
||||
import "./library/sync-game-by-object-id";
|
||||
import "./library/get-library";
|
||||
import "./library/extract-game-download";
|
||||
import "./library/open-game";
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { gamesSublevel, levelKeys } from "@main/level";
|
||||
import { HydraApi } from "@main/services";
|
||||
import type { GameShop, UserGameDetails } from "@types";
|
||||
|
||||
const syncGameByObjectId = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
shop: GameShop,
|
||||
objectId: string
|
||||
) => {
|
||||
return HydraApi.get<UserGameDetails>(
|
||||
`/profile/games/${shop}/${objectId}`
|
||||
).then(async (res) => {
|
||||
const { id, playTimeInSeconds, isFavorite, ...rest } = res;
|
||||
|
||||
const gameKey = levelKeys.game(shop, objectId);
|
||||
|
||||
const currentData = await gamesSublevel.get(gameKey);
|
||||
|
||||
await gamesSublevel.put(gameKey, {
|
||||
...currentData,
|
||||
...rest,
|
||||
remoteId: id,
|
||||
playTimeInMilliseconds: playTimeInSeconds * 1000,
|
||||
favorite: isFavorite ?? currentData?.favorite,
|
||||
});
|
||||
|
||||
return res;
|
||||
});
|
||||
};
|
||||
|
||||
registerEvent("syncGameByObjectId", syncGameByObjectId);
|
||||
11
src/main/level/sublevels/game-stats-cache.ts
Normal file
11
src/main/level/sublevels/game-stats-cache.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { GameStats } from "@types";
|
||||
|
||||
import { db } from "../level";
|
||||
import { levelKeys } from "./keys";
|
||||
|
||||
export const gamesStatsCacheSublevel = db.sublevel<
|
||||
string,
|
||||
GameStats & { updatedAt: number }
|
||||
>(levelKeys.gameStatsCache, {
|
||||
valueEncoding: "json",
|
||||
});
|
||||
@@ -2,6 +2,7 @@ export * from "./downloads";
|
||||
export * from "./games";
|
||||
export * from "./game-shop-assets";
|
||||
export * from "./game-shop-cache";
|
||||
export * from "./game-stats-cache";
|
||||
export * from "./game-achievements";
|
||||
export * from "./keys";
|
||||
export * from "./themes";
|
||||
|
||||
@@ -7,6 +7,7 @@ export const levelKeys = {
|
||||
auth: "auth",
|
||||
themes: "themes",
|
||||
gameShopAssets: "gameShopAssets",
|
||||
gameStatsCache: "gameStatsAssets",
|
||||
gameShopCache: "gameShopCache",
|
||||
gameShopCacheItem: (shop: GameShop, objectId: string, language: string) =>
|
||||
`${shop}:${objectId}:${language}`,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { logger } from "../logger";
|
||||
import { db, gameAchievementsSublevel, levelKeys } from "@main/level";
|
||||
import { AxiosError } from "axios";
|
||||
|
||||
const LOCAL_CACHE_EXPIRATION = 1000 * 60 * 30; // 30 minutes
|
||||
const LOCAL_CACHE_EXPIRATION = 1000 * 60 * 60; // 1 hour
|
||||
|
||||
const getModifiedSinceHeader = (
|
||||
cachedAchievements: GameAchievement | undefined
|
||||
|
||||
@@ -31,8 +31,8 @@ export interface ProcessPayload {
|
||||
exe: string | null;
|
||||
pid: number;
|
||||
name: string;
|
||||
environ: Record<string, string> | null;
|
||||
cwd: string | null;
|
||||
environ?: Record<string, string> | null;
|
||||
cwd?: string | null;
|
||||
}
|
||||
|
||||
export interface PauseSeedingPayload {
|
||||
|
||||
@@ -25,7 +25,7 @@ interface GameExecutables {
|
||||
[key: string]: ExecutableInfo[];
|
||||
}
|
||||
|
||||
const TICKS_TO_UPDATE_API = 80;
|
||||
const TICKS_TO_UPDATE_API = 120;
|
||||
let currentTick = 1;
|
||||
|
||||
const platform = process.platform;
|
||||
|
||||
@@ -187,8 +187,6 @@ contextBridge.exposeInMainWorld("electron", {
|
||||
ipcRenderer.invoke("deleteGameFolder", shop, objectId),
|
||||
getGameByObjectId: (shop: GameShop, objectId: string) =>
|
||||
ipcRenderer.invoke("getGameByObjectId", shop, objectId),
|
||||
syncGameByObjectId: (shop: GameShop, objectId: string) =>
|
||||
ipcRenderer.invoke("syncGameByObjectId", shop, objectId),
|
||||
resetGameAchievements: (shop: GameShop, objectId: string) =>
|
||||
ipcRenderer.invoke("resetGameAchievements", shop, objectId),
|
||||
extractGameDownload: (shop: GameShop, objectId: string) =>
|
||||
|
||||
@@ -182,14 +182,6 @@ export function GameDetailsContextProvider({
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
window.electron
|
||||
.syncGameByObjectId(shop, objectId)
|
||||
.then(() => {
|
||||
if (abortController.signal.aborted) return;
|
||||
updateGame();
|
||||
})
|
||||
.catch(() => {});
|
||||
}, [
|
||||
updateGame,
|
||||
dispatch,
|
||||
|
||||
1
src/renderer/src/declaration.d.ts
vendored
1
src/renderer/src/declaration.d.ts
vendored
@@ -155,7 +155,6 @@ declare global {
|
||||
shop: GameShop,
|
||||
objectId: string
|
||||
) => Promise<LibraryGame | null>;
|
||||
syncGameByObjectId: (shop: GameShop, objectId: string) => Promise<void>;
|
||||
onGamesRunning: (
|
||||
cb: (
|
||||
gamesRunning: Pick<GameRunning, "id" | "sessionDurationInMillis">[]
|
||||
|
||||
Reference in New Issue
Block a user