From 2e82c29f4c76e8c4dd818f9d83149465a82617b7 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:12:36 -0300 Subject: [PATCH] feat: searching from api --- src/main/events/catalogue/get-random-game.ts | 8 +-- src/main/events/catalogue/search-games.ts | 18 +++++- src/main/events/helpers/search-games.ts | 29 ++++----- src/main/services/hydra-api.ts | 60 ++++++++++++++----- src/main/services/repacks-manager.ts | 5 ++ src/main/workers/steam-games.worker.ts | 23 +------ .../src/pages/home/search-results.tsx | 2 +- 7 files changed, 83 insertions(+), 62 deletions(-) diff --git a/src/main/events/catalogue/get-random-game.ts b/src/main/events/catalogue/get-random-game.ts index 69f57800..0f0341b4 100644 --- a/src/main/events/catalogue/get-random-game.ts +++ b/src/main/events/catalogue/get-random-game.ts @@ -3,7 +3,7 @@ import { shuffle } from "lodash-es"; import { getSteam250List } from "@main/services"; import { registerEvent } from "../register-event"; -import { searchSteamGames } from "../helpers/search-games"; +import { getSteamGameById } from "../helpers/search-games"; import type { Steam250Game } from "@types"; const state = { games: Array(), index: 0 }; @@ -12,11 +12,9 @@ const filterGames = async (games: Steam250Game[]) => { const results: Steam250Game[] = []; for (const game of games) { - const catalogue = await searchSteamGames({ query: game.title }); - - if (catalogue.length) { - const [steamGame] = catalogue; + const steamGame = await getSteamGameById(game.objectID); + if (steamGame) { if (steamGame.repacks.length) { results.push(game); } diff --git a/src/main/events/catalogue/search-games.ts b/src/main/events/catalogue/search-games.ts index ec397599..504b0209 100644 --- a/src/main/events/catalogue/search-games.ts +++ b/src/main/events/catalogue/search-games.ts @@ -1,10 +1,24 @@ import { registerEvent } from "../register-event"; -import { searchSteamGames } from "../helpers/search-games"; +import { getSteamGameById } from "../helpers/search-games"; import { CatalogueEntry } from "@types"; +import { HydraApi } from "@main/services"; const searchGamesEvent = async ( _event: Electron.IpcMainInvokeEvent, query: string -): Promise => searchSteamGames({ query, limit: 12 }); +): Promise => { + const games = await HydraApi.get< + { objectId: string; title: string; shop: string }[] + >("/games/search", { title: query, take: 12, skip: 0 }, { needsAuth: false }); + + const steamGames = await Promise.all( + games.map((game) => getSteamGameById(game.objectId)) + ); + const filteredGames = steamGames.filter( + (game) => game !== null + ) as CatalogueEntry[]; + + return filteredGames; +}; registerEvent("searchGames", searchGamesEvent); diff --git a/src/main/events/helpers/search-games.ts b/src/main/events/helpers/search-games.ts index 74be1f07..c5878dcb 100644 --- a/src/main/events/helpers/search-games.ts +++ b/src/main/events/helpers/search-games.ts @@ -1,6 +1,3 @@ -import { orderBy } from "lodash-es"; -import flexSearch from "flexsearch"; - import type { GameShop, CatalogueEntry, SteamGame } from "@types"; import { getSteamAppAsset } from "@main/helpers"; @@ -23,20 +20,18 @@ export const convertSteamGameToCatalogueEntry = ( repacks: [], }); -export const searchSteamGames = async ( - options: flexSearch.SearchOptions -): Promise => { - const steamGames = (await steamGamesWorker.run(options, { - name: "search", - })) as SteamGame[]; +export const getSteamGameById = async ( + objectId: string +): Promise => { + const steamGame = await steamGamesWorker.run(Number(objectId), { + name: "getById", + }); - const result = RepacksManager.findRepacksForCatalogueEntries( - steamGames.map((game) => convertSteamGameToCatalogueEntry(game)) - ); + if (!steamGame) return null; - return orderBy( - result, - [({ repacks }) => repacks.length, "repacks"], - ["desc"] - ); + const catalogueEntry = convertSteamGameToCatalogueEntry(steamGame); + + const result = RepacksManager.findRepacksForCatalogueEntry(catalogueEntry); + + return result; }; diff --git a/src/main/services/hydra-api.ts b/src/main/services/hydra-api.ts index 120d27ac..bbf390d0 100644 --- a/src/main/services/hydra-api.ts +++ b/src/main/services/hydra-api.ts @@ -7,6 +7,10 @@ import { clearGamesRemoteIds } from "./library-sync/clear-games-remote-id"; import { logger } from "./logger"; import { UserNotLoggedInError } from "@shared"; +interface HydraApiOptions { + needsAuth: boolean; +} + export class HydraApi { private static instance: AxiosInstance; @@ -204,50 +208,76 @@ export class HydraApi { throw err; }; - static async get(url: string, params?: any) { - if (!this.isLoggedIn()) throw new UserNotLoggedInError(); + static async get( + url: string, + params?: any, + options?: HydraApiOptions + ) { + if (!options || options.needsAuth) { + if (!this.isLoggedIn()) throw new UserNotLoggedInError(); + await this.revalidateAccessTokenIfExpired(); + } - await this.revalidateAccessTokenIfExpired(); return this.instance .get(url, { params, ...this.getAxiosConfig() }) .then((response) => response.data) .catch(this.handleUnauthorizedError); } - static async post(url: string, data?: any) { - if (!this.isLoggedIn()) throw new UserNotLoggedInError(); + static async post( + url: string, + data?: any, + options?: HydraApiOptions + ) { + if (!options || options.needsAuth) { + if (!this.isLoggedIn()) throw new UserNotLoggedInError(); + await this.revalidateAccessTokenIfExpired(); + } - await this.revalidateAccessTokenIfExpired(); return this.instance .post(url, data, this.getAxiosConfig()) .then((response) => response.data) .catch(this.handleUnauthorizedError); } - static async put(url: string, data?: any) { - if (!this.isLoggedIn()) throw new UserNotLoggedInError(); + static async put( + url: string, + data?: any, + options?: HydraApiOptions + ) { + if (!options || options.needsAuth) { + if (!this.isLoggedIn()) throw new UserNotLoggedInError(); + await this.revalidateAccessTokenIfExpired(); + } - await this.revalidateAccessTokenIfExpired(); return this.instance .put(url, data, this.getAxiosConfig()) .then((response) => response.data) .catch(this.handleUnauthorizedError); } - static async patch(url: string, data?: any) { - if (!this.isLoggedIn()) throw new UserNotLoggedInError(); + static async patch( + url: string, + data?: any, + options?: HydraApiOptions + ) { + if (!options || options.needsAuth) { + if (!this.isLoggedIn()) throw new UserNotLoggedInError(); + await this.revalidateAccessTokenIfExpired(); + } - await this.revalidateAccessTokenIfExpired(); return this.instance .patch(url, data, this.getAxiosConfig()) .then((response) => response.data) .catch(this.handleUnauthorizedError); } - static async delete(url: string) { - if (!this.isLoggedIn()) throw new UserNotLoggedInError(); + static async delete(url: string, options?: HydraApiOptions) { + if (!options || options.needsAuth) { + if (!this.isLoggedIn()) throw new UserNotLoggedInError(); + await this.revalidateAccessTokenIfExpired(); + } - await this.revalidateAccessTokenIfExpired(); return this.instance .delete(url, this.getAxiosConfig()) .then((response) => response.data) diff --git a/src/main/services/repacks-manager.ts b/src/main/services/repacks-manager.ts index 93157d6c..933d7431 100644 --- a/src/main/services/repacks-manager.ts +++ b/src/main/services/repacks-manager.ts @@ -49,6 +49,11 @@ export class RepacksManager { .map((index) => this.repacks[index]); } + public static findRepacksForCatalogueEntry(entry: CatalogueEntry) { + const repacks = this.search({ query: formatName(entry.title) }); + return { ...entry, repacks }; + } + public static findRepacksForCatalogueEntries(entries: CatalogueEntry[]) { return entries.map((entry) => { const repacks = this.search({ query: formatName(entry.title) }); diff --git a/src/main/workers/steam-games.worker.ts b/src/main/workers/steam-games.worker.ts index ad399943..9085082b 100644 --- a/src/main/workers/steam-games.worker.ts +++ b/src/main/workers/steam-games.worker.ts @@ -1,36 +1,15 @@ import { SteamGame } from "@types"; -import { orderBy, slice } from "lodash-es"; -import flexSearch from "flexsearch"; +import { slice } from "lodash-es"; import fs from "node:fs"; -import { formatName } from "@shared"; import { workerData } from "node:worker_threads"; -const steamGamesIndex = new flexSearch.Index({ - tokenize: "reverse", -}); - const { steamGamesPath } = workerData; const data = fs.readFileSync(steamGamesPath, "utf-8"); const steamGames = JSON.parse(data) as SteamGame[]; -for (let i = 0; i < steamGames.length; i++) { - const steamGame = steamGames[i]; - - const formattedName = formatName(steamGame.name); - - steamGamesIndex.add(i, formattedName); -} - -export const search = (options: flexSearch.SearchOptions) => { - const results = steamGamesIndex.search(options); - const games = results.map((index) => steamGames[index]); - - return orderBy(games, ["name"], ["asc"]); -}; - export const getById = (id: number) => steamGames.find((game) => game.id === id); diff --git a/src/renderer/src/pages/home/search-results.tsx b/src/renderer/src/pages/home/search-results.tsx index 30b3ea68..cc7a2a97 100644 --- a/src/renderer/src/pages/home/search-results.tsx +++ b/src/renderer/src/pages/home/search-results.tsx @@ -48,7 +48,7 @@ export function SearchResults() { .finally(() => { setIsLoading(false); }); - }, 300); + }, 500); debouncedFunc.current(); }, [searchParams, dispatch]);