From c6fda9b4d8b04a1ff137a6939933805db3d73304 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Mon, 21 Oct 2024 01:48:47 -0300 Subject: [PATCH] feat: start watching new achievements only after finishing sync --- ...atcher.ts => AchievementWatcherManager.ts} | 130 ++++++++++++++---- .../update-local-unlocked-achivements.ts | 69 +--------- .../library-sync/upload-games-batch.ts | 4 +- src/main/services/main-loop.ts | 4 +- 4 files changed, 109 insertions(+), 98 deletions(-) rename src/main/services/achievements/{achievement-watcher.ts => AchievementWatcherManager.ts} (59%) diff --git a/src/main/services/achievements/achievement-watcher.ts b/src/main/services/achievements/AchievementWatcherManager.ts similarity index 59% rename from src/main/services/achievements/achievement-watcher.ts rename to src/main/services/achievements/AchievementWatcherManager.ts index 0986f8be..31c913f7 100644 --- a/src/main/services/achievements/achievement-watcher.ts +++ b/src/main/services/achievements/AchievementWatcherManager.ts @@ -1,4 +1,4 @@ -import { gameRepository } from "@main/repository"; +import { gameAchievementRepository, gameRepository } from "@main/repository"; import { parseAchievementFile } from "./parse-achievement-file"; import { Game } from "@main/entity"; import { mergeAchievements } from "./merge-achievements"; @@ -9,10 +9,11 @@ import { findAllAchievementFiles, getAlternativeObjectIds, } from "./find-achivement-files"; -import type { AchievementFile } from "@types"; +import type { AchievementFile, UnlockedAchievement } from "@types"; import { achievementsLogger } from "../logger"; import { Cracker } from "@shared"; import { IsNull, Not } from "typeorm"; +import { getGameAchievementData } from "./get-game-achievement-data"; const fileStats: Map = new Map(); const fltFiles: Map> = new Map(); @@ -72,30 +73,6 @@ const watchAchievementsWithWine = async () => { } }; -export const watchAchievements = async () => { - if (process.platform === "win32") { - return watchAchievementsWindows(); - } - - watchAchievementsWithWine(); -}; - -const processAchievementFileDiff = async ( - game: Game, - file: AchievementFile -) => { - const unlockedAchievements = parseAchievementFile(file.filePath, file.type); - - if (unlockedAchievements.length) { - return mergeAchievements( - game.objectID, - game.shop, - unlockedAchievements, - true - ); - } -}; - const compareFltFolder = async (game: Game, file: AchievementFile) => { try { const currentAchievements = new Set(readdirSync(file.filePath)); @@ -156,3 +133,104 @@ const compareFile = (game: Game, file: AchievementFile) => { return; } }; + +const processAchievementFileDiff = async ( + game: Game, + file: AchievementFile +) => { + const unlockedAchievements = parseAchievementFile(file.filePath, file.type); + + if (unlockedAchievements.length) { + return mergeAchievements( + game.objectID, + game.shop, + unlockedAchievements, + true + ); + } +}; + +export class AchievementWatcherManager { + private static hasFinishedMergingWithRemote = false; + + public static watchAchievements = async () => { + if (!this.hasFinishedMergingWithRemote) return; + + if (process.platform === "win32") { + return watchAchievementsWindows(); + } + + watchAchievementsWithWine(); + }; + + public static preSearchAchievements = async () => { + const games = await gameRepository.find({ + where: { + isDeleted: false, + }, + }); + + const gameAchievementFilesMap = findAllAchievementFiles(); + + await Promise.all( + games.map(async (game) => { + gameAchievementRepository + .findOne({ + where: { objectId: game.objectID, shop: "steam" }, + }) + .then((localAchievements) => { + if (!localAchievements || !localAchievements.achievements) { + getGameAchievementData(game.objectID, "steam"); + } + }); + + const gameAchievementFiles: AchievementFile[] = []; + const unlockedAchievements: UnlockedAchievement[] = []; + + for (const objectId of getAlternativeObjectIds(game.objectID)) { + gameAchievementFiles.push( + ...(gameAchievementFilesMap.get(objectId) || []) + ); + + gameAchievementFiles.push( + ...findAchievementFileInExecutableDirectory(game) + ); + } + + for (const achievementFile of gameAchievementFiles) { + const parsedAchievements = parseAchievementFile( + achievementFile.filePath, + achievementFile.type + ); + + try { + const currentStat = fs.statSync(achievementFile.filePath); + fileStats.set(achievementFile.filePath, currentStat.mtimeMs); + } catch { + fileStats.set(achievementFile.filePath, -1); + } + + if (parsedAchievements.length) { + unlockedAchievements.push(...parsedAchievements); + + achievementsLogger.log( + "Achievement file for", + game.title, + achievementFile.filePath, + parsedAchievements + ); + } + + await mergeAchievements( + game.objectID, + "steam", + unlockedAchievements, + false + ); + } + }) + ); + + this.hasFinishedMergingWithRemote = true; + }; +} diff --git a/src/main/services/achievements/update-local-unlocked-achivements.ts b/src/main/services/achievements/update-local-unlocked-achivements.ts index 177808d8..f579382f 100644 --- a/src/main/services/achievements/update-local-unlocked-achivements.ts +++ b/src/main/services/achievements/update-local-unlocked-achivements.ts @@ -1,79 +1,12 @@ -import { gameAchievementRepository, gameRepository } from "@main/repository"; import { - findAllAchievementFiles, findAchievementFiles, findAchievementFileInExecutableDirectory, - getAlternativeObjectIds, } from "./find-achivement-files"; import { parseAchievementFile } from "./parse-achievement-file"; import { mergeAchievements } from "./merge-achievements"; -import type { AchievementFile, UnlockedAchievement } from "@types"; -import { getGameAchievementData } from "./get-game-achievement-data"; -import { achievementsLogger } from "../logger"; +import type { UnlockedAchievement } from "@types"; import { Game } from "@main/entity"; -export const updateAllLocalUnlockedAchievements = async () => { - const games = await gameRepository.find({ - where: { - isDeleted: false, - }, - }); - - if (games.length === 0) return; - - const gameAchievementFilesMap = findAllAchievementFiles(); - - for (const game of games) { - gameAchievementRepository - .findOne({ - where: { objectId: game.objectID, shop: "steam" }, - }) - .then((localAchievements) => { - if (!localAchievements || !localAchievements.achievements) { - getGameAchievementData(game.objectID, "steam"); - } - }); - - const gameAchievementFiles: AchievementFile[] = []; - const unlockedAchievements: UnlockedAchievement[] = []; - - for (const objectId of getAlternativeObjectIds(game.objectID)) { - gameAchievementFiles.push( - ...(gameAchievementFilesMap.get(objectId) || []) - ); - - gameAchievementFiles.push( - ...findAchievementFileInExecutableDirectory(game) - ); - } - - for (const achievementFile of gameAchievementFiles) { - const parsedAchievements = parseAchievementFile( - achievementFile.filePath, - achievementFile.type - ); - - if (parsedAchievements.length) { - unlockedAchievements.push(...parsedAchievements); - - achievementsLogger.log( - "Achievement file for", - game.title, - achievementFile.filePath, - parsedAchievements - ); - } - - await mergeAchievements( - game.objectID, - "steam", - unlockedAchievements, - false - ); - } - } -}; - export const updateLocalUnlockedAchivements = async (game: Game) => { const gameAchievementFiles = findAchievementFiles(game); diff --git a/src/main/services/library-sync/upload-games-batch.ts b/src/main/services/library-sync/upload-games-batch.ts index 366f6c4e..b40bfcda 100644 --- a/src/main/services/library-sync/upload-games-batch.ts +++ b/src/main/services/library-sync/upload-games-batch.ts @@ -4,7 +4,7 @@ import { IsNull } from "typeorm"; import { HydraApi } from "../hydra-api"; import { mergeWithRemoteGames } from "./merge-with-remote-games"; import { WindowManager } from "../window-manager"; -import { updateAllLocalUnlockedAchievements } from "../achievements/update-local-unlocked-achivements"; +import { AchievementWatcherManager } from "../achievements/AchievementWatcherManager"; export const uploadGamesBatch = async () => { const games = await gameRepository.find({ @@ -29,7 +29,7 @@ export const uploadGamesBatch = async () => { await mergeWithRemoteGames(); - await updateAllLocalUnlockedAchievements(); + await AchievementWatcherManager.preSearchAchievements(); if (WindowManager.mainWindow) WindowManager.mainWindow.webContents.send("on-library-batch-complete"); diff --git a/src/main/services/main-loop.ts b/src/main/services/main-loop.ts index 5ba57fc3..48db4887 100644 --- a/src/main/services/main-loop.ts +++ b/src/main/services/main-loop.ts @@ -1,7 +1,7 @@ import { sleep } from "@main/helpers"; import { DownloadManager } from "./download"; import { watchProcesses } from "./process-watcher"; -import { watchAchievements } from "./achievements/achievement-watcher"; +import { AchievementWatcherManager } from "./achievements/AchievementWatcherManager"; export const startMainLoop = async () => { // eslint-disable-next-line no-constant-condition @@ -9,7 +9,7 @@ export const startMainLoop = async () => { await Promise.allSettled([ watchProcesses(), DownloadManager.watchDownloads(), - watchAchievements(), + AchievementWatcherManager.watchAchievements(), ]); await sleep(1500);