Files
hydra/src/main/services/achievements/game-achievements-observer.ts
2024-09-26 21:51:15 -03:00

86 lines
2.4 KiB
TypeScript

import { watch } from "node:fs/promises";
import { checkUnlockedAchievements } from "./check-unlocked-achievements";
import { parseAchievementFile } from "./parse-achievement-file";
import { Game } from "@main/entity";
import { mergeAchievements } from "./merge-achievements";
import fs from "node:fs";
import { findSteamGameAchievementFiles } from "./find-steam-game-achivement-files";
import type { AchievementFile } from "@types";
type GameAchievementObserver = {
[id: number]: AbortController;
};
const gameAchievementObserver: GameAchievementObserver = {};
const processAchievementFile = async (game: Game, file: AchievementFile) => {
const localAchievementFile = await parseAchievementFile(file.filePath);
console.log(localAchievementFile);
if (localAchievementFile) {
const unlockedAchievements = checkUnlockedAchievements(
file.type,
localAchievementFile
);
console.log(unlockedAchievements);
if (unlockedAchievements.length) {
mergeAchievements(game.objectID, game.shop, unlockedAchievements, true);
}
}
};
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) => {
if (game.shop !== "steam") return;
if (gameAchievementObserver[game.id]) return;
const achievementFiles =
findSteamGameAchievementFiles(game.objectID).get(game.objectID) || [];
console.log(
"Achievements files to observe for:",
game.title,
achievementFiles
);
for (const file of achievementFiles) {
if (!fs.existsSync(file.filePath)) {
continue;
}
if (!gameAchievementObserver[game.id]) {
const abortController = new AbortController();
gameAchievementObserver[game.id] = abortController;
}
startFileWatch(game, file);
}
};
export const stopGameAchievementObserver = (gameId: number) => {
gameAchievementObserver[gameId]?.abort();
delete gameAchievementObserver[gameId];
};