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,34 +30,9 @@ const processAchievementFile = async (game: Game, file: AchievementFile) => {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const startGameAchievementObserver = async (game: Game) => {
 | 
					const startFileWatch = async (game: Game, file: AchievementFile) => {
 | 
				
			||||||
  if (gameAchievementObserver[game.id]) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  console.log(`Starting: ${game.title}`);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const achievementFiles = await getGameAchievementsToWatch(game.id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  console.log(
 | 
					 | 
				
			||||||
    "Achievements files to observe for:",
 | 
					 | 
				
			||||||
    game.title,
 | 
					 | 
				
			||||||
    achievementFiles
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (const file of achievementFiles) {
 | 
					 | 
				
			||||||
    if (!fs.existsSync(file.filePath)) {
 | 
					 | 
				
			||||||
      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;
 | 
					  const signal = gameAchievementObserver[game.id]?.signal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    (async () => {
 | 
					 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    processAchievementFile(game, file);
 | 
					    processAchievementFile(game, file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,12 +50,36 @@ export const startGameAchievementObserver = async (game: Game) => {
 | 
				
			||||||
    console.log(`cracker: ${file.type}, steamId ${game.objectID}`);
 | 
					    console.log(`cracker: ${file.type}, steamId ${game.objectID}`);
 | 
				
			||||||
    throw err;
 | 
					    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) => {
 | 
					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