mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
feat: refactor
This commit is contained in:
parent
c72eefdb77
commit
780ab5f909
10 changed files with 68 additions and 131 deletions
|
@ -1,4 +1,5 @@
|
||||||
import { Cracker, UnlockedAchievement } from "../types";
|
import { Cracker } from "@shared";
|
||||||
|
import type { UnlockedAchievement } from "@types";
|
||||||
|
|
||||||
export const checkUnlockedAchievements = (
|
export const checkUnlockedAchievements = (
|
||||||
type: Cracker,
|
type: Cracker,
|
|
@ -1,10 +1,11 @@
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import { Cracker, GameAchievementFiles } from "../types";
|
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
|
import type { AchievementFile } from "@types";
|
||||||
|
import { Cracker } from "@shared";
|
||||||
|
|
||||||
const addGame = (
|
const addGame = (
|
||||||
achievementFiles: GameAchievementFiles,
|
achievementFiles: Map<string, AchievementFile[]>,
|
||||||
achievementPath: string,
|
achievementPath: string,
|
||||||
objectId: string,
|
objectId: string,
|
||||||
fileLocation: string[],
|
fileLocation: string[],
|
||||||
|
@ -17,19 +18,17 @@ const addGame = (
|
||||||
filePath,
|
filePath,
|
||||||
};
|
};
|
||||||
|
|
||||||
achievementFiles[objectId]
|
achievementFiles.get(objectId)
|
||||||
? achievementFiles[objectId].push(achivementFile)
|
? achievementFiles.get(objectId)!.push(achivementFile)
|
||||||
: (achievementFiles[objectId] = [achivementFile]);
|
: achievementFiles.set(objectId, [achivementFile]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const steamFindGameAchievementFiles = (
|
export const findSteamGameAchievementFiles = (objectId?: string) => {
|
||||||
objectId?: string
|
|
||||||
): GameAchievementFiles => {
|
|
||||||
//TODO: change to a automatized method
|
//TODO: change to a automatized method
|
||||||
const publicDir = path.join("C:", "Users", "Public", "Documents");
|
const publicDir = path.join("C:", "Users", "Public", "Documents");
|
||||||
const appData = app.getPath("appData");
|
const appData = app.getPath("appData");
|
||||||
|
|
||||||
const gameAchievementFiles: GameAchievementFiles = {};
|
const gameAchievementFiles = new Map<string, AchievementFile[]>();
|
||||||
|
|
||||||
const crackers = [
|
const crackers = [
|
||||||
Cracker.codex,
|
Cracker.codex,
|
|
@ -1,11 +1,11 @@
|
||||||
import { watch } from "node:fs/promises";
|
import { watch } from "node:fs/promises";
|
||||||
import { getGameAchievementsToWatch } from "./get-game-achievements-to-watch";
|
import { checkUnlockedAchievements } from "./check-unlocked-achievements";
|
||||||
import { checkUnlockedAchievements } from "./util/check-unlocked-achievements";
|
import { parseAchievementFile } from "./parse-achievement-file";
|
||||||
import { parseAchievementFile } from "./util/parseAchievementFile";
|
|
||||||
import { Game } from "@main/entity";
|
import { Game } from "@main/entity";
|
||||||
import { mergeAchievements } from "./merge-achievements";
|
import { mergeAchievements } from "./merge-achievements";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import { AchievementFile } from "./types";
|
import { findSteamGameAchievementFiles } from "./find-steam-game-achivement-files";
|
||||||
|
import type { AchievementFile } from "@types";
|
||||||
|
|
||||||
type GameAchievementObserver = {
|
type GameAchievementObserver = {
|
||||||
[id: number]: AbortController;
|
[id: number]: AbortController;
|
||||||
|
@ -30,12 +30,34 @@ const processAchievementFile = async (game: Game, file: AchievementFile) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const startFileWatch = async (game: Game, file: AchievementFile) => {
|
||||||
|
const signal = gameAchievementObserver[game.id]?.signal;
|
||||||
|
|
||||||
|
try {
|
||||||
|
processAchievementFile(game, file);
|
||||||
|
|
||||||
|
const watcher = watch(file.filePath, {
|
||||||
|
signal,
|
||||||
|
});
|
||||||
|
|
||||||
|
for await (const event of watcher) {
|
||||||
|
if (event.eventType === "change") {
|
||||||
|
processAchievementFile(game, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err?.name === "AbortError") return;
|
||||||
|
console.log(`cracker: ${file.type}, steamId ${game.objectID}`);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const startGameAchievementObserver = async (game: Game) => {
|
export const startGameAchievementObserver = async (game: Game) => {
|
||||||
|
if (game.shop !== "steam") return;
|
||||||
if (gameAchievementObserver[game.id]) return;
|
if (gameAchievementObserver[game.id]) return;
|
||||||
|
|
||||||
console.log(`Starting: ${game.title}`);
|
const achievementFiles =
|
||||||
|
findSteamGameAchievementFiles(game.objectID).get(game.objectID) || [];
|
||||||
const achievementFiles = await getGameAchievementsToWatch(game.id);
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
"Achievements files to observe for:",
|
"Achievements files to observe for:",
|
||||||
|
@ -48,39 +70,16 @@ export const startGameAchievementObserver = async (game: Game) => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`cracker: ${file.type}, objectId: ${game.objectID}`);
|
|
||||||
|
|
||||||
if (!gameAchievementObserver[game.id]) {
|
if (!gameAchievementObserver[game.id]) {
|
||||||
const abortController = new AbortController();
|
const abortController = new AbortController();
|
||||||
gameAchievementObserver[game.id] = abortController;
|
gameAchievementObserver[game.id] = abortController;
|
||||||
}
|
}
|
||||||
|
|
||||||
const signal = gameAchievementObserver[game.id]?.signal;
|
startFileWatch(game, file);
|
||||||
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
processAchievementFile(game, file);
|
|
||||||
|
|
||||||
const watcher = watch(file.filePath, {
|
|
||||||
signal,
|
|
||||||
});
|
|
||||||
|
|
||||||
for await (const event of watcher) {
|
|
||||||
if (event.eventType === "change") {
|
|
||||||
processAchievementFile(game, file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
if (err?.name === "AbortError") return;
|
|
||||||
console.log(`cracker: ${file.type}, steamId ${game.objectID}`);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const stopGameAchievementObserver = (gameId: number) => {
|
export const stopGameAchievementObserver = (gameId: number) => {
|
||||||
console.log(`Stopping: ${gameId}`);
|
|
||||||
gameAchievementObserver[gameId]?.abort();
|
gameAchievementObserver[gameId]?.abort();
|
||||||
delete gameAchievementObserver[gameId];
|
delete gameAchievementObserver[gameId];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { gameRepository } from "@main/repository";
|
|
||||||
import { steamFindGameAchievementFiles } from "./steam/steam-find-game-achivement-files";
|
|
||||||
import { AchievementFile } from "./types";
|
|
||||||
|
|
||||||
export const getGameAchievementsToWatch = async (
|
|
||||||
gameId: number
|
|
||||||
): Promise<AchievementFile[]> => {
|
|
||||||
const game = await gameRepository.findOne({ where: { id: gameId } });
|
|
||||||
|
|
||||||
if (!game || game.shop !== "steam") return [];
|
|
||||||
|
|
||||||
const steamId = Number(game.objectID);
|
|
||||||
|
|
||||||
const achievementFiles = steamFindGameAchievementFiles(game.objectID)[
|
|
||||||
steamId
|
|
||||||
];
|
|
||||||
console.log(
|
|
||||||
"achivements files:",
|
|
||||||
achievementFiles,
|
|
||||||
game.title,
|
|
||||||
game.objectID
|
|
||||||
);
|
|
||||||
|
|
||||||
return achievementFiles || [];
|
|
||||||
};
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { gameAchievementRepository, gameRepository } from "@main/repository";
|
import { gameAchievementRepository, gameRepository } from "@main/repository";
|
||||||
import { UnlockedAchievement } from "./types";
|
|
||||||
import { publishNewAchievementNotification } from "../notifications";
|
import { publishNewAchievementNotification } from "../notifications";
|
||||||
import { GameShop } from "@types";
|
import type { GameShop, UnlockedAchievement } from "@types";
|
||||||
|
|
||||||
export const mergeAchievements = async (
|
export const mergeAchievements = async (
|
||||||
objectId: string,
|
objectId: string,
|
||||||
|
|
|
@ -3,19 +3,19 @@ import {
|
||||||
gameRepository,
|
gameRepository,
|
||||||
userPreferencesRepository,
|
userPreferencesRepository,
|
||||||
} from "@main/repository";
|
} from "@main/repository";
|
||||||
import { steamFindGameAchievementFiles } from "./steam/steam-find-game-achivement-files";
|
import { findSteamGameAchievementFiles } from "./find-steam-game-achivement-files";
|
||||||
import { parseAchievementFile } from "./util/parseAchievementFile";
|
import { parseAchievementFile } from "./parse-achievement-file";
|
||||||
import { HydraApi } from "@main/services";
|
import { HydraApi } from "@main/services";
|
||||||
import { checkUnlockedAchievements } from "./util/check-unlocked-achievements";
|
import { checkUnlockedAchievements } from "./check-unlocked-achievements";
|
||||||
import { mergeAchievements } from "./merge-achievements";
|
import { mergeAchievements } from "./merge-achievements";
|
||||||
import { UnlockedAchievement } from "./types";
|
import type { UnlockedAchievement } from "@types";
|
||||||
|
|
||||||
export const saveAllLocalSteamAchivements = async () => {
|
export const saveAllLocalSteamAchivements = async () => {
|
||||||
const userPreferences = await userPreferencesRepository.findOne({
|
const userPreferences = await userPreferencesRepository.findOne({
|
||||||
where: { id: 1 },
|
where: { id: 1 },
|
||||||
});
|
});
|
||||||
|
|
||||||
const gameAchievementFiles = steamFindGameAchievementFiles();
|
const gameAchievementFiles = findSteamGameAchievementFiles();
|
||||||
|
|
||||||
for (const objectId of Object.keys(gameAchievementFiles)) {
|
for (const objectId of Object.keys(gameAchievementFiles)) {
|
||||||
const [game, localAchievements] = await Promise.all([
|
const [game, localAchievements] = await Promise.all([
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
export enum Cracker {
|
|
||||||
codex = "CODEX",
|
|
||||||
rune = "RUNE",
|
|
||||||
onlineFix = "OnlineFix",
|
|
||||||
goldberg = "Goldberg",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CheckedAchievements {
|
|
||||||
all: Achievement[];
|
|
||||||
new: Achievement[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UnlockedAchievement {
|
|
||||||
name: string;
|
|
||||||
unlockTime: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Achievement {
|
|
||||||
id: string;
|
|
||||||
percent: number;
|
|
||||||
imageUrl: string;
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
achieved: boolean;
|
|
||||||
curProgress: number;
|
|
||||||
maxProgress: number;
|
|
||||||
unlockTime: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AchievementInfo {
|
|
||||||
imageUrl: string;
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AchievementPercentage {
|
|
||||||
name: string;
|
|
||||||
percent: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CheckedAchievement {
|
|
||||||
all: Achievement[];
|
|
||||||
new: Achievement[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AchievementFile {
|
|
||||||
type: Cracker;
|
|
||||||
filePath: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type GameAchievementFiles = {
|
|
||||||
[id: string]: AchievementFile[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type GameAchievementFile = {
|
|
||||||
[id: string]: AchievementFile[];
|
|
||||||
};
|
|
|
@ -23,3 +23,10 @@ export enum SteamContentDescriptor {
|
||||||
FrequentNudityOrSexualContent = 4,
|
FrequentNudityOrSexualContent = 4,
|
||||||
GeneralMatureContent = 5,
|
GeneralMatureContent = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum Cracker {
|
||||||
|
codex = "CODEX",
|
||||||
|
rune = "RUNE",
|
||||||
|
onlineFix = "OnlineFix",
|
||||||
|
goldberg = "Goldberg",
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { DownloadSourceStatus, Downloader } from "@shared";
|
import type { Cracker, DownloadSourceStatus, Downloader } from "@shared";
|
||||||
import type { SteamAppDetails } from "./steam.types";
|
import type { SteamAppDetails } from "./steam.types";
|
||||||
|
|
||||||
export type GameStatus =
|
export type GameStatus =
|
||||||
|
@ -265,5 +265,19 @@ export interface UserStats {
|
||||||
friendsCount: number;
|
friendsCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UnlockedAchievement {
|
||||||
|
name: string;
|
||||||
|
unlockTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AchievementFile {
|
||||||
|
type: Cracker;
|
||||||
|
filePath: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GameAchievementFiles = {
|
||||||
|
[id: string]: AchievementFile[];
|
||||||
|
};
|
||||||
|
|
||||||
export * from "./steam.types";
|
export * from "./steam.types";
|
||||||
export * from "./real-debrid.types";
|
export * from "./real-debrid.types";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue