From 780ab5f909dc92eb85894027cf42d247556cf3c9 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:33:32 -0300 Subject: [PATCH] feat: refactor --- .../{util => }/check-unlocked-achievements.ts | 3 +- ...ts => find-steam-game-achivement-files.ts} | 17 +++--- .../game-achievements-observer.ts | 61 +++++++++---------- .../get-game-achievements-to-watch.ts | 25 -------- .../achievements/merge-achievements.ts | 3 +- ...ementFile.ts => parse-achievement-file.ts} | 0 .../save-all-local-steam-achivements.ts | 10 +-- src/main/services/achievements/types/index.ts | 57 ----------------- src/shared/constants.ts | 7 +++ src/types/index.ts | 16 ++++- 10 files changed, 68 insertions(+), 131 deletions(-) rename src/main/services/achievements/{util => }/check-unlocked-achievements.ts (95%) rename src/main/services/achievements/{steam/steam-find-game-achivement-files.ts => find-steam-game-achivement-files.ts} (77%) delete mode 100644 src/main/services/achievements/get-game-achievements-to-watch.ts rename src/main/services/achievements/{util/parseAchievementFile.ts => parse-achievement-file.ts} (100%) delete mode 100644 src/main/services/achievements/types/index.ts diff --git a/src/main/services/achievements/util/check-unlocked-achievements.ts b/src/main/services/achievements/check-unlocked-achievements.ts similarity index 95% rename from src/main/services/achievements/util/check-unlocked-achievements.ts rename to src/main/services/achievements/check-unlocked-achievements.ts index 4d82f09f..71a80b2b 100644 --- a/src/main/services/achievements/util/check-unlocked-achievements.ts +++ b/src/main/services/achievements/check-unlocked-achievements.ts @@ -1,4 +1,5 @@ -import { Cracker, UnlockedAchievement } from "../types"; +import { Cracker } from "@shared"; +import type { UnlockedAchievement } from "@types"; export const checkUnlockedAchievements = ( type: Cracker, diff --git a/src/main/services/achievements/steam/steam-find-game-achivement-files.ts b/src/main/services/achievements/find-steam-game-achivement-files.ts similarity index 77% rename from src/main/services/achievements/steam/steam-find-game-achivement-files.ts rename to src/main/services/achievements/find-steam-game-achivement-files.ts index e3c23bd2..fdc21184 100644 --- a/src/main/services/achievements/steam/steam-find-game-achivement-files.ts +++ b/src/main/services/achievements/find-steam-game-achivement-files.ts @@ -1,10 +1,11 @@ import path from "node:path"; import fs from "node:fs"; -import { Cracker, GameAchievementFiles } from "../types"; import { app } from "electron"; +import type { AchievementFile } from "@types"; +import { Cracker } from "@shared"; const addGame = ( - achievementFiles: GameAchievementFiles, + achievementFiles: Map, achievementPath: string, objectId: string, fileLocation: string[], @@ -17,19 +18,17 @@ const addGame = ( filePath, }; - achievementFiles[objectId] - ? achievementFiles[objectId].push(achivementFile) - : (achievementFiles[objectId] = [achivementFile]); + achievementFiles.get(objectId) + ? achievementFiles.get(objectId)!.push(achivementFile) + : achievementFiles.set(objectId, [achivementFile]); }; -export const steamFindGameAchievementFiles = ( - objectId?: string -): GameAchievementFiles => { +export const findSteamGameAchievementFiles = (objectId?: string) => { //TODO: change to a automatized method const publicDir = path.join("C:", "Users", "Public", "Documents"); const appData = app.getPath("appData"); - const gameAchievementFiles: GameAchievementFiles = {}; + const gameAchievementFiles = new Map(); const crackers = [ Cracker.codex, diff --git a/src/main/services/achievements/game-achievements-observer.ts b/src/main/services/achievements/game-achievements-observer.ts index 8e0f6ce2..16cafa48 100644 --- a/src/main/services/achievements/game-achievements-observer.ts +++ b/src/main/services/achievements/game-achievements-observer.ts @@ -1,11 +1,11 @@ import { watch } from "node:fs/promises"; -import { getGameAchievementsToWatch } from "./get-game-achievements-to-watch"; -import { checkUnlockedAchievements } from "./util/check-unlocked-achievements"; -import { parseAchievementFile } from "./util/parseAchievementFile"; +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 { AchievementFile } from "./types"; +import { findSteamGameAchievementFiles } from "./find-steam-game-achivement-files"; +import type { AchievementFile } from "@types"; type GameAchievementObserver = { [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) => { + if (game.shop !== "steam") return; if (gameAchievementObserver[game.id]) return; - console.log(`Starting: ${game.title}`); - - const achievementFiles = await getGameAchievementsToWatch(game.id); + const achievementFiles = + findSteamGameAchievementFiles(game.objectID).get(game.objectID) || []; console.log( "Achievements files to observe for:", @@ -48,39 +70,16 @@ export const startGameAchievementObserver = async (game: Game) => { continue; } - console.log(`cracker: ${file.type}, objectId: ${game.objectID}`); - if (!gameAchievementObserver[game.id]) { const abortController = new AbortController(); gameAchievementObserver[game.id] = abortController; } - const signal = gameAchievementObserver[game.id]?.signal; - - (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; - } - })(); + startFileWatch(game, file); } }; export const stopGameAchievementObserver = (gameId: number) => { - console.log(`Stopping: ${gameId}`); gameAchievementObserver[gameId]?.abort(); delete gameAchievementObserver[gameId]; }; diff --git a/src/main/services/achievements/get-game-achievements-to-watch.ts b/src/main/services/achievements/get-game-achievements-to-watch.ts deleted file mode 100644 index 48df8652..00000000 --- a/src/main/services/achievements/get-game-achievements-to-watch.ts +++ /dev/null @@ -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 => { - 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 || []; -}; diff --git a/src/main/services/achievements/merge-achievements.ts b/src/main/services/achievements/merge-achievements.ts index adf05092..ac76b82c 100644 --- a/src/main/services/achievements/merge-achievements.ts +++ b/src/main/services/achievements/merge-achievements.ts @@ -1,7 +1,6 @@ import { gameAchievementRepository, gameRepository } from "@main/repository"; -import { UnlockedAchievement } from "./types"; import { publishNewAchievementNotification } from "../notifications"; -import { GameShop } from "@types"; +import type { GameShop, UnlockedAchievement } from "@types"; export const mergeAchievements = async ( objectId: string, diff --git a/src/main/services/achievements/util/parseAchievementFile.ts b/src/main/services/achievements/parse-achievement-file.ts similarity index 100% rename from src/main/services/achievements/util/parseAchievementFile.ts rename to src/main/services/achievements/parse-achievement-file.ts diff --git a/src/main/services/achievements/save-all-local-steam-achivements.ts b/src/main/services/achievements/save-all-local-steam-achivements.ts index 4f4bd0b0..b736bc4c 100644 --- a/src/main/services/achievements/save-all-local-steam-achivements.ts +++ b/src/main/services/achievements/save-all-local-steam-achivements.ts @@ -3,19 +3,19 @@ import { gameRepository, userPreferencesRepository, } from "@main/repository"; -import { steamFindGameAchievementFiles } from "./steam/steam-find-game-achivement-files"; -import { parseAchievementFile } from "./util/parseAchievementFile"; +import { findSteamGameAchievementFiles } from "./find-steam-game-achivement-files"; +import { parseAchievementFile } from "./parse-achievement-file"; import { HydraApi } from "@main/services"; -import { checkUnlockedAchievements } from "./util/check-unlocked-achievements"; +import { checkUnlockedAchievements } from "./check-unlocked-achievements"; import { mergeAchievements } from "./merge-achievements"; -import { UnlockedAchievement } from "./types"; +import type { UnlockedAchievement } from "@types"; export const saveAllLocalSteamAchivements = async () => { const userPreferences = await userPreferencesRepository.findOne({ where: { id: 1 }, }); - const gameAchievementFiles = steamFindGameAchievementFiles(); + const gameAchievementFiles = findSteamGameAchievementFiles(); for (const objectId of Object.keys(gameAchievementFiles)) { const [game, localAchievements] = await Promise.all([ diff --git a/src/main/services/achievements/types/index.ts b/src/main/services/achievements/types/index.ts deleted file mode 100644 index 7d110ccd..00000000 --- a/src/main/services/achievements/types/index.ts +++ /dev/null @@ -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[]; -}; diff --git a/src/shared/constants.ts b/src/shared/constants.ts index 896d2ede..15661959 100644 --- a/src/shared/constants.ts +++ b/src/shared/constants.ts @@ -23,3 +23,10 @@ export enum SteamContentDescriptor { FrequentNudityOrSexualContent = 4, GeneralMatureContent = 5, } + +export enum Cracker { + codex = "CODEX", + rune = "RUNE", + onlineFix = "OnlineFix", + goldberg = "Goldberg", +} diff --git a/src/types/index.ts b/src/types/index.ts index 817b5c8b..2e448f9d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,4 +1,4 @@ -import type { DownloadSourceStatus, Downloader } from "@shared"; +import type { Cracker, DownloadSourceStatus, Downloader } from "@shared"; import type { SteamAppDetails } from "./steam.types"; export type GameStatus = @@ -265,5 +265,19 @@ export interface UserStats { 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 "./real-debrid.types";