mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-22 02:13:59 +00:00
Merge branch 'feat/new-catalogue' into feat/achievements-points
# Conflicts: # src/preload/index.ts # src/renderer/src/app.tsx # src/renderer/src/features/index.ts # src/renderer/src/store.ts # yarn.lock
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
import { DataSource } from "typeorm";
|
||||
import {
|
||||
DownloadQueue,
|
||||
DownloadSource,
|
||||
Game,
|
||||
GameShopCache,
|
||||
Repack,
|
||||
UserPreferences,
|
||||
UserAuth,
|
||||
GameAchievement,
|
||||
@@ -17,12 +15,10 @@ export const dataSource = new DataSource({
|
||||
type: "better-sqlite3",
|
||||
entities: [
|
||||
Game,
|
||||
Repack,
|
||||
UserAuth,
|
||||
UserPreferences,
|
||||
UserSubscription,
|
||||
GameShopCache,
|
||||
DownloadSource,
|
||||
DownloadQueue,
|
||||
GameAchievement,
|
||||
],
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
OneToMany,
|
||||
} from "typeorm";
|
||||
import type { Repack } from "./repack.entity";
|
||||
|
||||
import { DownloadSourceStatus } from "@shared";
|
||||
|
||||
@Entity("download_source")
|
||||
export class DownloadSource {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column("text", { nullable: true, unique: true })
|
||||
url: string;
|
||||
|
||||
@Column("text")
|
||||
name: string;
|
||||
|
||||
@Column("text", { nullable: true })
|
||||
etag: string | null;
|
||||
|
||||
@Column("int", { default: 0 })
|
||||
downloadCount: number;
|
||||
|
||||
@Column("text", { default: DownloadSourceStatus.UpToDate })
|
||||
status: DownloadSourceStatus;
|
||||
|
||||
@OneToMany("Repack", "downloadSource", { cascade: true })
|
||||
repacks: Repack[];
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: Date;
|
||||
}
|
||||
@@ -5,9 +5,7 @@ import {
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
OneToOne,
|
||||
JoinColumn,
|
||||
} from "typeorm";
|
||||
import { Repack } from "./repack.entity";
|
||||
|
||||
import type { GameShop, GameStatus } from "@types";
|
||||
import { Downloader } from "@shared";
|
||||
@@ -72,13 +70,6 @@ export class Game {
|
||||
@Column("text", { nullable: true })
|
||||
uri: string | null;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@OneToOne("Repack", "game", { nullable: true })
|
||||
@JoinColumn()
|
||||
repack: Repack;
|
||||
|
||||
@OneToOne("DownloadQueue", "game")
|
||||
downloadQueue: DownloadQueue;
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
export * from "./game.entity";
|
||||
export * from "./repack.entity";
|
||||
export * from "./user-auth.entity";
|
||||
export * from "./user-preferences.entity";
|
||||
export * from "./user-subscription.entity";
|
||||
export * from "./game-shop-cache.entity";
|
||||
export * from "./game.entity";
|
||||
export * from "./game-achievements.entity";
|
||||
export * from "./download-source.entity";
|
||||
export * from "./download-queue.entity";
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
ManyToOne,
|
||||
} from "typeorm";
|
||||
import { DownloadSource } from "./download-source.entity";
|
||||
|
||||
@Entity("repack")
|
||||
export class Repack {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column("text", { unique: true })
|
||||
title: string;
|
||||
|
||||
/**
|
||||
* @deprecated Use uris instead
|
||||
*/
|
||||
@Column("text", { unique: true })
|
||||
magnet: string;
|
||||
|
||||
@Column("text")
|
||||
repacker: string;
|
||||
|
||||
@Column("text")
|
||||
fileSize: string;
|
||||
|
||||
@Column("datetime")
|
||||
uploadDate: Date | string;
|
||||
|
||||
@ManyToOne(() => DownloadSource, { nullable: true, onDelete: "CASCADE" })
|
||||
downloadSource: DownloadSource;
|
||||
|
||||
@Column("text", { default: "[]" })
|
||||
uris: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: Date;
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
import type { GameShop } from "@types";
|
||||
|
||||
import { registerEvent } from "../register-event";
|
||||
import { HydraApi } from "@main/services";
|
||||
import { CatalogueCategory, steamUrlBuilder } from "@shared";
|
||||
import { steamGamesWorker } from "@main/workers";
|
||||
import { CatalogueCategory } from "@shared";
|
||||
|
||||
const getCatalogue = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
@@ -14,26 +11,11 @@ const getCatalogue = async (
|
||||
skip: "0",
|
||||
});
|
||||
|
||||
const response = await HydraApi.get<{ objectId: string; shop: GameShop }[]>(
|
||||
return HydraApi.get(
|
||||
`/catalogue/${category}?${params.toString()}`,
|
||||
{},
|
||||
{ needsAuth: false }
|
||||
);
|
||||
|
||||
return Promise.all(
|
||||
response.map(async (game) => {
|
||||
const steamGame = await steamGamesWorker.run(Number(game.objectId), {
|
||||
name: "getById",
|
||||
});
|
||||
|
||||
return {
|
||||
title: steamGame.name,
|
||||
shop: game.shop,
|
||||
cover: steamUrlBuilder.library(game.objectId),
|
||||
objectId: game.objectId,
|
||||
};
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
registerEvent("getCatalogue", getCatalogue);
|
||||
|
||||
10
src/main/events/catalogue/get-developers.ts
Normal file
10
src/main/events/catalogue/get-developers.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { HydraApi } from "@main/services";
|
||||
import { registerEvent } from "../register-event";
|
||||
|
||||
const getDevelopers = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||
return HydraApi.get<string[]>(`/catalogue/developers`, null, {
|
||||
needsAuth: false,
|
||||
});
|
||||
};
|
||||
|
||||
registerEvent("getDevelopers", getDevelopers);
|
||||
@@ -1,29 +0,0 @@
|
||||
import type { CatalogueEntry } from "@types";
|
||||
|
||||
import { registerEvent } from "../register-event";
|
||||
import { HydraApi } from "@main/services";
|
||||
import { steamUrlBuilder } from "@shared";
|
||||
|
||||
const getGames = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
take = 12,
|
||||
skip = 0
|
||||
): Promise<CatalogueEntry[]> => {
|
||||
const searchParams = new URLSearchParams({
|
||||
take: take.toString(),
|
||||
skip: skip.toString(),
|
||||
});
|
||||
|
||||
const games = await HydraApi.get<CatalogueEntry[]>(
|
||||
`/games/catalogue?${searchParams.toString()}`,
|
||||
undefined,
|
||||
{ needsAuth: false }
|
||||
);
|
||||
|
||||
return games.map((game) => ({
|
||||
...game,
|
||||
cover: steamUrlBuilder.library(game.objectId),
|
||||
}));
|
||||
};
|
||||
|
||||
registerEvent("getGames", getGames);
|
||||
10
src/main/events/catalogue/get-publishers.ts
Normal file
10
src/main/events/catalogue/get-publishers.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { HydraApi } from "@main/services";
|
||||
import { registerEvent } from "../register-event";
|
||||
|
||||
const getPublishers = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||
return HydraApi.get<string[]>(`/catalogue/publishers`, null, {
|
||||
needsAuth: false,
|
||||
});
|
||||
};
|
||||
|
||||
registerEvent("getPublishers", getPublishers);
|
||||
@@ -1,23 +1,16 @@
|
||||
import type { CatalogueSearchPayload } from "@types";
|
||||
import { registerEvent } from "../register-event";
|
||||
import { convertSteamGameToCatalogueEntry } from "../helpers/search-games";
|
||||
import type { CatalogueEntry } from "@types";
|
||||
import { HydraApi } from "@main/services";
|
||||
|
||||
const searchGamesEvent = async (
|
||||
const searchGames = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
query: string
|
||||
): Promise<CatalogueEntry[]> => {
|
||||
const games = await HydraApi.get<
|
||||
{ objectId: string; title: string; shop: string }[]
|
||||
>("/games/search", { title: query, take: 12, skip: 0 }, { needsAuth: false });
|
||||
|
||||
return games.map((game) => {
|
||||
return convertSteamGameToCatalogueEntry({
|
||||
id: Number(game.objectId),
|
||||
name: game.title,
|
||||
clientIcon: null,
|
||||
});
|
||||
});
|
||||
payload: CatalogueSearchPayload
|
||||
) => {
|
||||
return HydraApi.post(
|
||||
"/catalogue/search",
|
||||
{ ...payload, take: 24, skip: 0 },
|
||||
{ needsAuth: false }
|
||||
);
|
||||
};
|
||||
|
||||
registerEvent("searchGames", searchGamesEvent);
|
||||
registerEvent("searchGames", searchGames);
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { knexClient } from "@main/knex-client";
|
||||
|
||||
const deleteDownloadSource = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
id: number
|
||||
) => knexClient("download_source").where({ id }).delete();
|
||||
|
||||
registerEvent("deleteDownloadSource", deleteDownloadSource);
|
||||
@@ -1,7 +0,0 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { knexClient } from "@main/knex-client";
|
||||
|
||||
const getDownloadSources = async (_event: Electron.IpcMainInvokeEvent) =>
|
||||
knexClient.select("*").from("download_source");
|
||||
|
||||
registerEvent("getDownloadSources", getDownloadSources);
|
||||
17
src/main/events/download-sources/put-download-source.ts
Normal file
17
src/main/events/download-sources/put-download-source.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { HydraApi } from "@main/services";
|
||||
import { registerEvent } from "../register-event";
|
||||
|
||||
const putDownloadSource = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
objectIds: string[]
|
||||
) => {
|
||||
return HydraApi.put<{ fingerprint: string }>(
|
||||
"/download-sources",
|
||||
{
|
||||
objectIds,
|
||||
},
|
||||
{ needsAuth: false }
|
||||
);
|
||||
};
|
||||
|
||||
registerEvent("putDownloadSource", putDownloadSource);
|
||||
@@ -1,31 +0,0 @@
|
||||
import type { GameShop, CatalogueEntry, SteamGame } from "@types";
|
||||
|
||||
import { steamGamesWorker } from "@main/workers";
|
||||
import { steamUrlBuilder } from "@shared";
|
||||
|
||||
export interface SearchGamesArgs {
|
||||
query?: string;
|
||||
take?: number;
|
||||
skip?: number;
|
||||
}
|
||||
|
||||
export const convertSteamGameToCatalogueEntry = (
|
||||
game: SteamGame
|
||||
): CatalogueEntry => ({
|
||||
objectId: String(game.id),
|
||||
title: game.name,
|
||||
shop: "steam" as GameShop,
|
||||
cover: steamUrlBuilder.library(String(game.id)),
|
||||
});
|
||||
|
||||
export const getSteamGameById = async (
|
||||
objectId: string
|
||||
): Promise<CatalogueEntry | null> => {
|
||||
const steamGame = await steamGamesWorker.run(Number(objectId), {
|
||||
name: "getById",
|
||||
});
|
||||
|
||||
if (!steamGame) return null;
|
||||
|
||||
return convertSteamGameToCatalogueEntry(steamGame);
|
||||
};
|
||||
@@ -3,12 +3,13 @@ import { ipcMain } from "electron";
|
||||
|
||||
import "./catalogue/get-catalogue";
|
||||
import "./catalogue/get-game-shop-details";
|
||||
import "./catalogue/get-games";
|
||||
import "./catalogue/get-how-long-to-beat";
|
||||
import "./catalogue/get-random-game";
|
||||
import "./catalogue/search-games";
|
||||
import "./catalogue/get-game-stats";
|
||||
import "./catalogue/get-trending-games";
|
||||
import "./catalogue/get-publishers";
|
||||
import "./catalogue/get-developers";
|
||||
import "./hardware/get-disk-free-space";
|
||||
import "./library/add-game-to-library";
|
||||
import "./library/create-game-shortcut";
|
||||
@@ -40,8 +41,7 @@ import "./user-preferences/auto-launch";
|
||||
import "./autoupdater/check-for-updates";
|
||||
import "./autoupdater/restart-and-install-update";
|
||||
import "./user-preferences/authenticate-real-debrid";
|
||||
import "./download-sources/delete-download-source";
|
||||
import "./download-sources/get-download-sources";
|
||||
import "./download-sources/put-download-source";
|
||||
import "./auth/sign-out";
|
||||
import "./auth/open-auth-window";
|
||||
import "./auth/get-session-hash";
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { dataSource } from "./data-source";
|
||||
import {
|
||||
DownloadQueue,
|
||||
DownloadSource,
|
||||
Game,
|
||||
GameShopCache,
|
||||
Repack,
|
||||
UserPreferences,
|
||||
UserAuth,
|
||||
GameAchievement,
|
||||
@@ -13,16 +11,11 @@ import {
|
||||
|
||||
export const gameRepository = dataSource.getRepository(Game);
|
||||
|
||||
export const repackRepository = dataSource.getRepository(Repack);
|
||||
|
||||
export const userPreferencesRepository =
|
||||
dataSource.getRepository(UserPreferences);
|
||||
|
||||
export const gameShopCacheRepository = dataSource.getRepository(GameShopCache);
|
||||
|
||||
export const downloadSourceRepository =
|
||||
dataSource.getRepository(DownloadSource);
|
||||
|
||||
export const downloadQueueRepository = dataSource.getRepository(DownloadQueue);
|
||||
|
||||
export const userAuthRepository = dataSource.getRepository(UserAuth);
|
||||
|
||||
Reference in New Issue
Block a user