Merge branch 'main' into teste-locale2

This commit is contained in:
Zamitto 2024-05-20 16:39:33 -03:00 committed by GitHub
commit fab15ccded
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 469 additions and 193 deletions

View File

@ -1,8 +1,6 @@
name: Build
on:
push:
branches: main
on: [pull_request]
jobs:
build:
@ -39,7 +37,6 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: yarn build:linux
env:
MAIN_VITE_STEAMGRIDDB_API_KEY: ${{ secrets.STEAMGRIDDB_API_KEY }}
MAIN_VITE_ONLINEFIX_USERNAME: ${{ secrets.ONLINEFIX_USERNAME }}
MAIN_VITE_ONLINEFIX_PASSWORD: ${{ secrets.ONLINEFIX_PASSWORD }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -48,7 +45,6 @@ jobs:
if: matrix.os == 'windows-latest'
run: yarn build:win
env:
MAIN_VITE_STEAMGRIDDB_API_KEY: ${{ secrets.STEAMGRIDDB_API_KEY }}
MAIN_VITE_ONLINEFIX_USERNAME: ${{ secrets.ONLINEFIX_USERNAME }}
MAIN_VITE_ONLINEFIX_PASSWORD: ${{ secrets.ONLINEFIX_PASSWORD }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -58,7 +54,7 @@ jobs:
with:
name: Build-${{ matrix.os }}
path: |
dist/*.exe
dist/win-unpacked/**
dist/*.zip
dist/*.dmg
dist/*.deb
@ -66,21 +62,3 @@ jobs:
dist/*.tar.gz
dist/*.yml
dist/*.blockmap
- name: Release
uses: softprops/action-gh-release@v1
with:
draft: true
files: |
dist/*.exe
dist/*.zip
dist/*.dmg
dist/*.AppImage
dist/*.snap
dist/*.deb
dist/*.rpm
dist/*.tar.gz
dist/*.yml
dist/*.blockmap
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

70
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,70 @@
name: Build
on:
push:
branches: main
jobs:
build:
strategy:
matrix:
os: [windows-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20.11.1
- name: Install dependencies
run: yarn
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: 3.9
- name: Install dependencies
run: pip install -r requirements.txt
- name: Build with cx_Freeze
run: python torrent-client/setup.py build
- name: Build Linux
if: matrix.os == 'ubuntu-latest'
run: yarn build:linux
env:
MAIN_VITE_ONLINEFIX_USERNAME: ${{ secrets.ONLINEFIX_USERNAME }}
MAIN_VITE_ONLINEFIX_PASSWORD: ${{ secrets.ONLINEFIX_PASSWORD }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build Windows
if: matrix.os == 'windows-latest'
run: yarn build:win
env:
MAIN_VITE_ONLINEFIX_USERNAME: ${{ secrets.ONLINEFIX_USERNAME }}
MAIN_VITE_ONLINEFIX_PASSWORD: ${{ secrets.ONLINEFIX_PASSWORD }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release
uses: softprops/action-gh-release@v1
with:
draft: true
files: |
dist/*.exe
dist/*.zip
dist/*.dmg
dist/*.AppImage
dist/*.snap
dist/*.deb
dist/*.rpm
dist/*.tar.gz
dist/*.yml
dist/*.blockmap
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,2 +1 @@
yarn lint
yarn typecheck
yarn format

View File

@ -1 +1,2 @@
yarn format
yarn lint
yarn typecheck

View File

@ -1,5 +1,6 @@
out
dist
seeds
pnpm-lock.yaml
LICENSE.md
tsconfig.json

View File

@ -119,7 +119,7 @@ yarn
### Усталёўка Python 3.9
Упэўніцеся, што ў вас усталяваны Python 3.9 на вашым кампутары. Вы можаце загрузіць і ўсталяваць яго з [python.org](https://www.python.org/downloads/release/python-3919/).
Упэўніцеся, што ў вас усталяваны Python 3.9 на вашым кампутары. Вы можаце загрузіць і ўсталяваць яго з [python.org](https://www.python.org/downloads/release/python-3913/).
### Усталёўка залежнасцяў Python

View File

@ -13,11 +13,11 @@
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
![Hydra Catalogue](./docs/screenshot.png)
@ -119,7 +119,7 @@ yarn
### Install Python 3.9
Ensure you have Python 3.9 installed on your machine. You can download and install it from [python.org](https://www.python.org/downloads/release/python-3919/).
Ensure you have Python 3.9 installed on your machine. You can download and install it from [python.org](https://www.python.org/downloads/release/python-3913/).
### Install Python Dependencies

185
README.pl.md Normal file
View File

@ -0,0 +1,185 @@
<br>
<div align="center">
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
<h1 align="center">Hydra Launcher</h1>
<p align="center">
<strong>Hydra - to program uruchamiający gry z własnym wbudowanym klientem bittorrent i samodzielnie zarządzanym repackagerem..</strong>
</p>
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
![Hydra Catalogue](./docs/screenshot.png)
</div>
## Zawartość.
- [O nas](#o-nas)
- [Cechy.](#cechy)
- [Instalacja](#instalacja)
- [Dokonaj wpłaty](#dokonaj-wpłaty)
- [Dołącz do naszego kanału Telegram](#dołącz-do-naszego-kanału-telegram)
- [Rozwidlenie i sklonowanie repozytorium](#rozwidlenie-i-sklonowanie-repozytorium)
- [Jak możesz wnieść swój wkład](#jak-możesz-pomóc)
- [Struktura projektu](#struktura-projektu)
- [Utwórz kompilację z kodu źródłowego](#utwórz-kompilację-z-kodu-źródłowego)
- [Instalacja Node.js](#zainstaluj-nodejs)
- [Instalacja Yarn](#zainstaluj-yarn)
- [Instalacja Node zależności](#zainstaluj-zależności-node)
- [Instalacja Python 3.9](#zainstaluj-python-39)
- [Instalacja Python zależności](#zainstaluj-zależności-pythona)
- [Zmienne środowiskowe](#zmienne-środowiskowe)
- [Uruchomienie](#utwórz-kompilację-z-kodu-źródłowego)
- [Tworzenie kompilacji](#tworzenie-kompilacji)
- [Tworzenie klienta bittorrent](#zbuduj-klienta-bittorrent)
- [Tworzenie kompilacji aplikacji Electron](#tworzenie-aplikacji-electron)
- [Współtwórcy](#współtwórcy)
## O nas
**Hydra** - jest **programem uruchamiającym gry** z wbudowanym **klientem BitTorrent** i **samozarządzającym się repackagerem**.
<br>
Ten launcher jest napisany w TypeScript (Electron) i Pythonie, który współpracuje z systemem torrent przy użyciu libtorrent.
## Cechy
- Samodzielnie zarządzany repackager wśród wszystkich najbardziej zaufanych stron na [Megathread]("https://www.reddit.com/r/Piracy/wiki/megathread/").
- Własny wbudowany klient bittorrent
- Integracja funkcji How Long To Beat (HLTB) na stronie gry
- Personalizacja folderu pobierania
- Powiadomienia o aktualizacjach listy repacków
- Wsparcie dla systemów Windows i Linux
- Stała aktualizacja
- I nie tylko ...
## Instalacja
Aby zainstalować, wykonaj poniższe czynności:
1. Pobierz najnowszą wersję programu Hydra ze strony [Wydania](https://github.com/hydralauncher/hydra/releases/latest).
- Pobierz .exe tylko, jeśli chcesz zainstalować Hydrę w systemie Windows.
- Pobierz .deb lub .rpm lub .zip, jeśli chcesz zainstalować Hydrę w systemie Linux (zależy od dystrybucji systemu Linux).
2. Uruchom pobrany plik.
3. Ciesz się Hydrą!
## <a name="contributing"> Dokonaj wpłaty
### <a name="join-our-telegram"></a> Dołącz do naszego kanału Telegram
Skupiamy nasze dyskusje na naszym kanale [Telegram](https://t.me/hydralauncher).
1. Dołącz do naszego kanału
2. Przejdź do kanału ról i wybierz rolę Pracownik.
3. Wejdź na kanał dev, komunikuj się z nami i dziel się swoimi pomysłami.
### Rozwidlenie i sklonowanie repozytorium
1. Rozwidlenie repozytorium [(kliknij tutaj, aby rozwidlić teraz)](https://github.com/hydralauncher/hydra/fork)
2. Sklonuj swój rozwidlony kod `git clone https://github.com/your_username/hydra`.
3. Utwórz nowy brunch
4. Wypchnij swoje zatwierdzenia
5. Wyślij nowy Pull Request
### Jak możesz pomóc
- Tłumaczenie: Chcemy, aby Hydra była dostępna dla jak największej liczby osób. Zachęcamy do pomocy w tłumaczeniu na nowe języki lub aktualizowaniu i ulepszaniu tych, które są już dostępne na Hydrze.
- Kod: Hydra jest zbudowana przy użyciu Typescript, Electron i odrobiny Pythona. Jeśli chcesz wnieść swój wkład, dołącz do naszego kanału Telegram!
### Struktura projektu
- Klient torrent: Używamy libtorrent, biblioteki Pythona, do zarządzania pobieraniem torrentów.
- src/renderer: interfejs aplikacji
- src/main: cała logika jest tutaj.
## Utwórz kompilację z kodu źródłowego
### Zainstaluj Node.js
Upewnij się, że masz zainstalowany Node.js na swoim komputerze. Jeśli nie, pobierz i zainstaluj go ze strony [nodejs.org](https://nodejs.org/).
### Zainstaluj Yarn
Yarn to menedżer pakietów dla Node.js. Jeśli jeszcze nie zainstalowałeś Yarn, możesz to zrobić, postępując zgodnie z instrukcjami na stronie [yarnpkg.com](https://classic.yarnpkg.com/lang/en/docs/install/).
### Zainstaluj zależności Node
Przejdź do katalogu projektu i zainstaluj zależności Node za pomocą Yarn:
```bash
cd hydra
yarn
```
### Zainstaluj Python 3.9
Upewnij się, że masz zainstalowany Python 3.9 na swoim komputerze. Można go pobrać i zainstalować ze strony [python.org](https://www.python.org/downloads/release/python-3913/).
### Zainstaluj zależności Pythona
Zainstaluj niezbędne zależności Pythona za pomocą pip:
```bash
pip install -r requirements.txt
```
## Zmienne środowiskowe
Będziesz potrzebował klucza API SteamGridDB, aby uzyskać ikony gier podczas instalacji.
Jeśli chcesz użyć onlinefix jako repackagera, musisz dodać swoje dane uwierzytelniające do .env
Po jego uzyskaniu można skopiować plik lub zmienić jego nazwę `.env.example` na `.env` i umieść go na`STEAMGRIDDB_API_KEY`, `ONLINEFIX_USERNAME`, `ONLINEFIX_PASSWORD`.
## Run
Po skonfigurowaniu wszystkiego można uruchomić następujące polecenie, aby uruchomić zarówno proces Electron, jak i klienta bittorrent:
```bash
yarn dev
```
## Tworzenie kompilacji
### Zbuduj klienta bittorrent
Zbuduj klienta bittorrent za pomocą tego poleceniaи:
```bash
python torrent-client/setup.py build
```
### Tworzenie aplikacji Electron
Zbuduj aplikację Electron za pomocą tego polecenia:
W systemie Windows:
```bash
yarn build:win
```
W systemie Linux:
```bash
yarn build:linux
```
## Współtwórcy
<a href="https://github.com/hydralauncher/hydra/graphs/contributors">
<img src="https://contrib.rocks/image?repo=hydralauncher/hydra" />
</a>
## License
Hydra posiada licencję [MIT License](LICENSE).

View File

@ -13,12 +13,11 @@
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
![Hydra Catalogue](./docs/screenshot.png)
</div>
@ -119,7 +118,7 @@ yarn
### <a name="install-python-39"></a> Instale Python 3.9
Certifique-se de ter o Python 3.9 instalado em sua máquina. Você pode baixá-lo e instalá-lo em [python.org](https://www.python.org/downloads/release/python-3919/).
Certifique-se de ter o Python 3.9 instalado em sua máquina. Você pode baixá-lo e instalá-lo em [python.org](https://www.python.org/downloads/release/python-3913/).
### <a name="install-python-dependencies"></a> Instale Python Dependencies

View File

@ -13,11 +13,11 @@
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
![Hydra Catalogue](./docs/screenshot.png)
@ -119,7 +119,7 @@ yarn
### Установка Python 3.9
Убедитесь, что у вас установлен Python 3.9 на вашем компьютере. Вы можете загрузить и установить его с [python.org](https://www.python.org/downloads/release/python-3919/).
Убедитесь, что у вас установлен Python 3.9 на вашем компьютере. Вы можете загрузить и установить его с [python.org](https://www.python.org/downloads/release/python-3913/).
### Установка зависимостей Python

View File

@ -13,11 +13,11 @@
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
![Hydra Catalogue](./docs/screenshot.png)
@ -123,7 +123,7 @@ yarn
### Встановіть Python 3.9
Переконайтеся, що на вашому комп'ютері встановлено Python 3.9. Ви можете завантажити та встановити його з [python.org](https://www.python.org/downloads/release/python-3919/).
Переконайтеся, що на вашому комп'ютері встановлено Python 3.9. Ви можете завантажити та встановити його з [python.org](https://www.python.org/downloads/release/python-3913/).
### Встановіть Python залежності

View File

@ -6,6 +6,7 @@ extraResources:
- hydra-download-manager
- hydra.db
- fastlist.exe
- seeds
files:
- "!**/.vscode/*"
- "!src/*"

BIN
hydra.db

Binary file not shown.

View File

@ -1,6 +1,6 @@
{
"name": "hydra",
"version": "1.2.2",
"version": "1.2.3",
"description": "Hydra",
"main": "./out/main/index.js",
"author": "Los Broxas",

1
seeds/steam-games.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -18,21 +18,6 @@ export const repackers = [
"onlinefix",
] as const;
export const months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
export const defaultDownloadsPath = app.getPath("downloads");
export const databasePath = path.join(
@ -41,5 +26,6 @@ export const databasePath = path.join(
"hydra.db"
);
export const INSTALLATION_ID_LENGTH = 6;
export const ACTIVATION_KEY_MULTIPLIER = 7;
export const seedsPath = app.isPackaged
? path.join(process.resourcesPath, "seeds")
: path.join(__dirname, "..", "..", "seeds");

View File

@ -1,25 +1,21 @@
import { DataSource } from "typeorm";
import {
Game,
GameShopCache,
Repack,
UserPreferences,
SteamGame,
} from "@main/entity";
import type { SqliteConnectionOptions } from "typeorm/driver/sqlite/SqliteConnectionOptions";
import { Game, GameShopCache, Repack, UserPreferences } from "@main/entity";
import type { BetterSqlite3ConnectionOptions } from "typeorm/driver/better-sqlite3/BetterSqlite3ConnectionOptions";
import { databasePath } from "./constants";
import migrations from "./migrations";
export const createDataSource = (options: Partial<SqliteConnectionOptions>) =>
export const createDataSource = (
options: Partial<BetterSqlite3ConnectionOptions>
) =>
new DataSource({
type: "better-sqlite3",
database: databasePath,
entities: [Game, Repack, UserPreferences, GameShopCache, SteamGame],
entities: [Game, Repack, UserPreferences, GameShopCache],
synchronize: true,
database: databasePath,
...options,
});
export const dataSource = createDataSource({
migrations: migrations,
migrations,
});

View File

@ -23,8 +23,8 @@ export class Game {
@Column("text")
title: string;
@Column("text")
iconUrl: string;
@Column("text", { nullable: true })
iconUrl: string | null;
@Column("text", { nullable: true })
folderName: string | null;

View File

@ -2,4 +2,3 @@ export * from "./game.entity";
export * from "./repack.entity";
export * from "./user-preferences.entity";
export * from "./game-shop-cache.entity";
export * from "./steam-game.entity";

View File

@ -1,10 +0,0 @@
import { Column, Entity, PrimaryColumn } from "typeorm";
@Entity("steam_game")
export class SteamGame {
@PrimaryColumn()
id: number;
@Column()
name: string;
}

View File

@ -1,9 +1,10 @@
import { gameShopCacheRepository, steamGameRepository } from "@main/repository";
import { gameShopCacheRepository } from "@main/repository";
import { getSteamAppDetails } from "@main/services";
import type { ShopDetails, GameShop, SteamAppDetails } from "@types";
import { registerEvent } from "../register-event";
import { stateManager } from "@main/state-manager";
const getLocalizedSteamAppDetails = (
objectID: string,
@ -13,10 +14,11 @@ const getLocalizedSteamAppDetails = (
return getSteamAppDetails(objectID, language);
}
return Promise.all([
steamGameRepository.findOne({ where: { id: Number(objectID) } }),
getSteamAppDetails(objectID, language),
]).then(([steamGame, localizedAppDetails]) => {
return getSteamAppDetails(objectID, language).then((localizedAppDetails) => {
const steamGame = stateManager
.getValue("steamGames")
.find((game) => game.id === Number(objectID));
if (steamGame && localizedAppDetails) {
return {
...localizedAppDetails,

View File

@ -3,8 +3,8 @@ import { gameRepository } from "@main/repository";
import { registerEvent } from "../register-event";
import type { GameShop } from "@types";
import { getFileBase64 } from "@main/helpers";
import { getSteamGameIconUrl } from "@main/services";
import { getFileBase64, getSteamAppAsset } from "@main/helpers";
import { stateManager } from "@main/state-manager";
const addGameToLibrary = async (
_event: Electron.IpcMainInvokeEvent,
@ -27,17 +27,29 @@ const addGameToLibrary = async (
)
.then(async ({ affected }) => {
if (!affected) {
const iconUrl = await getFileBase64(
await getSteamGameIconUrl(objectID)
);
const steamGame = stateManager
.getValue("steamGames")
.find((game) => game.id === Number(objectID));
await gameRepository.insert({
title,
iconUrl,
objectID,
shop: gameShop,
executablePath,
});
const iconUrl = steamGame?.clientIcon
? getSteamAppAsset("icon", objectID, steamGame.clientIcon)
: null;
await gameRepository
.insert({
title,
iconUrl,
objectID,
shop: gameShop,
executablePath,
})
.then(() => {
if (iconUrl) {
getFileBase64(iconUrl).then((base64) =>
gameRepository.update({ objectID }, { iconUrl: base64 })
);
}
});
}
});
};

View File

@ -1,4 +1,3 @@
import { getSteamGameIconUrl } from "@main/services";
import {
gameRepository,
repackRepository,
@ -8,10 +7,11 @@ import {
import { registerEvent } from "../register-event";
import type { GameShop } from "@types";
import { getFileBase64 } from "@main/helpers";
import { getFileBase64, getSteamAppAsset } from "@main/helpers";
import { In } from "typeorm";
import { DownloadManager } from "@main/services";
import { Downloader, GameStatus } from "@shared";
import { stateManager } from "@main/state-manager";
const startGameDownload = async (
_event: Electron.IpcMainInvokeEvent,
@ -76,18 +76,34 @@ const startGameDownload = async (
return game;
} else {
const iconUrl = await getFileBase64(await getSteamGameIconUrl(objectID));
const steamGame = stateManager
.getValue("steamGames")
.find((game) => game.id === Number(objectID));
const createdGame = await gameRepository.save({
title,
iconUrl,
objectID,
downloader,
shop: gameShop,
status: GameStatus.Downloading,
downloadPath,
repack: { id: repackId },
});
const iconUrl = steamGame?.clientIcon
? getSteamAppAsset("icon", objectID, steamGame.clientIcon)
: null;
const createdGame = await gameRepository
.save({
title,
iconUrl,
objectID,
downloader,
shop: gameShop,
status: GameStatus.Downloading,
downloadPath,
repack: { id: repackId },
})
.then((result) => {
if (iconUrl) {
getFileBase64(iconUrl).then((base64) =>
gameRepository.update({ objectID }, { iconUrl: base64 })
);
}
return result;
});
DownloadManager.downloadGame(createdGame.id);

View File

@ -13,7 +13,7 @@ import {
gogFormatter,
onlinefixFormatter,
} from "./formatters";
import { months, repackers } from "../constants";
import { repackers } from "../constants";
export const pipe =
<T>(...fns: ((arg: T) => any)[]) =>
@ -44,19 +44,6 @@ export const repackerFormatter: Record<
onlinefix: onlinefixFormatter,
};
export const formatUploadDate = (str: string) => {
const date = new Date();
const [month, day, year] = str.split(" ");
date.setMonth(months.indexOf(month.replace(".", "")));
date.setDate(Number(day.substring(0, 2)));
date.setFullYear(Number("20" + year.replace("'", "")));
date.setHours(0, 0, 0, 0);
return date;
};
export const getSteamAppAsset = (
category: "library" | "hero" | "logo" | "icon",
objectID: string,

View File

@ -19,7 +19,7 @@ autoUpdater.setFeedURL({
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) app.quit();
app.disableHardwareAcceleration();
app.commandLine.appendSwitch("--no-sandbox");
i18n.init({
resources,

View File

@ -1,5 +1,5 @@
import { stateManager } from "./state-manager";
import { repackersOn1337x } from "./constants";
import { repackersOn1337x, seedsPath } from "./constants";
import {
getNewGOGGames,
getNewRepacksFromUser,
@ -11,7 +11,6 @@ import {
import {
gameRepository,
repackRepository,
steamGameRepository,
userPreferencesRepository,
} from "./repository";
import { TorrentDownloader } from "./services";
@ -20,7 +19,11 @@ import { Notification } from "electron";
import { t } from "i18next";
import { GameStatus } from "@shared";
import { In } from "typeorm";
import fs from "node:fs";
import path from "node:path";
import { RealDebridClient } from "./services/real-debrid";
import { orderBy } from "lodash-es";
import { SteamGame } from "@types";
startProcessWatcher();
@ -69,21 +72,18 @@ const checkForNewRepacks = async (userPreferences: UserPreferences | null) => {
};
const loadState = async (userPreferences: UserPreferences | null) => {
const [repacks, steamGames] = await Promise.all([
repackRepository.find({
order: {
createdAt: "desc",
},
}),
steamGameRepository.find({
order: {
name: "asc",
},
}),
]);
const repacks = await repackRepository.find({
order: {
createdAt: "desc",
},
});
const steamGames = JSON.parse(
fs.readFileSync(path.join(seedsPath, "steam-games.json"), "utf-8")
) as SteamGame[];
stateManager.setValue("repacks", repacks);
stateManager.setValue("steamGames", steamGames);
stateManager.setValue("steamGames", orderBy(steamGames, ["name"], "asc"));
import("./events");

View File

@ -1,11 +1,5 @@
import { dataSource } from "./data-source";
import {
Game,
GameShopCache,
Repack,
UserPreferences,
SteamGame,
} from "@main/entity";
import { Game, GameShopCache, Repack, UserPreferences } from "@main/entity";
export const gameRepository = dataSource.getRepository(Game);
@ -15,5 +9,3 @@ export const userPreferencesRepository =
dataSource.getRepository(UserPreferences);
export const gameShopCacheRepository = dataSource.getRepository(GameShopCache);
export const steamGameRepository = dataSource.getRepository(SteamGame);

View File

@ -0,0 +1,40 @@
import path from "node:path";
import fs from "node:fs";
import { getSteamGameClientIcon, logger } from "@main/services";
import { chunk } from "lodash-es";
import { seedsPath } from "@main/constants";
import type { SteamGame } from "@types";
const steamGamesPath = path.join(seedsPath, "steam-games.json");
const steamGames = JSON.parse(
fs.readFileSync(steamGamesPath, "utf-8")
) as SteamGame[];
const chunks = chunk(steamGames, 1500);
for (const chunk of chunks) {
await Promise.all(
chunk.map(async (steamGame) => {
if (steamGame.clientIcon) return;
const index = steamGames.findIndex((game) => game.id === steamGame.id);
try {
const clientIcon = await getSteamGameClientIcon(String(steamGame.id));
steamGames[index].clientIcon = clientIcon;
logger.log("info", `Set ${steamGame.name} client icon`);
} catch (err) {
steamGames[index].clientIcon = null;
logger.log("info", `Could not set icon for ${steamGame.name}`);
}
})
);
fs.writeFileSync(steamGamesPath, JSON.stringify(steamGames));
logger.log("info", "Updated steam games");
}

View File

@ -1,13 +1,39 @@
import { JSDOM } from "jsdom";
import { formatUploadDate } from "@main/helpers";
import { Repack } from "@main/entity";
import { requestWebPage, savePage } from "./helpers";
const months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
export const request1337x = async (path: string) =>
requestWebPage(`https://1337xx.to${path}`);
const formatUploadDate = (str: string) => {
const date = new Date();
const [month, day, year] = str.split(" ");
date.setMonth(months.indexOf(month.replace(".", "")));
date.setDate(Number(day.substring(0, 2)));
date.setFullYear(Number("20" + year.replace("'", "")));
date.setHours(0, 0, 0, 0);
return date;
};
/* TODO: $a will often be null */
const getTorrentDetails = async (path: string) => {
const response = await request1337x(path);

View File

@ -1,5 +1,4 @@
import axios from "axios";
import { getSteamAppAsset } from "@main/helpers";
export interface SteamGridResponse {
success: boolean;
@ -59,16 +58,11 @@ export const getSteamGridGameById = async (
return response.data;
};
export const getSteamGameIconUrl = async (objectID: string) => {
export const getSteamGameClientIcon = async (objectID: string) => {
const {
data: { id: steamGridGameId },
} = await getSteamGridData(objectID, "games", "steam");
const steamGridGame = await getSteamGridGameById(steamGridGameId);
return getSteamAppAsset(
"icon",
objectID,
steamGridGame.data.platforms.steam.metadata.clienticon
);
return steamGridGame.data.platforms.steam.metadata.clienticon;
};

View File

@ -4,8 +4,8 @@ import { app } from "electron";
import { chunk } from "lodash-es";
import { createDataSource } from "@main/data-source";
import { Repack, SteamGame } from "@main/entity";
import { repackRepository, steamGameRepository } from "@main/repository";
import { Repack } from "@main/entity";
import { repackRepository } from "@main/repository";
export const resolveDatabaseUpdates = async () => {
const updateDataSource = createDataSource({
@ -16,12 +16,8 @@ export const resolveDatabaseUpdates = async () => {
return updateDataSource.initialize().then(async () => {
const updateRepackRepository = updateDataSource.getRepository(Repack);
const updateSteamGameRepository = updateDataSource.getRepository(SteamGame);
const [updateRepacks, updateSteamGames] = await Promise.all([
updateRepackRepository.find(),
updateSteamGameRepository.find(),
]);
const updateRepacks = await updateRepackRepository.find();
const updateRepacksChunks = chunk(updateRepacks, 800);
@ -33,16 +29,5 @@ export const resolveDatabaseUpdates = async () => {
.orIgnore()
.execute();
}
const steamGamesChunks = chunk(updateSteamGames, 800);
for (const chunk of steamGamesChunks) {
await steamGameRepository
.createQueryBuilder()
.insert()
.values(chunk)
.orIgnore()
.execute();
}
});
};

View File

@ -1,4 +1,5 @@
import type { Repack, SteamGame } from "@main/entity";
import type { Repack } from "@main/entity";
import type { SteamGame } from "@types";
interface State {
repacks: Repack[];

View File

@ -106,6 +106,8 @@ export const menuItemButtonLabel = style({
export const gameIcon = style({
width: "20px",
height: "20px",
minWidth: "20px",
minHeight: "20px",
borderRadius: "4px",
backgroundSize: "cover",
});

View File

@ -13,6 +13,8 @@ import * as styles from "./sidebar.css";
import { GameStatus, GameStatusHelper } from "@shared";
import { buildGameDetailsPath } from "@renderer/helpers";
import SteamLogo from "@renderer/assets/steam-logo.svg?react";
const SIDEBAR_MIN_WIDTH = 200;
const SIDEBAR_INITIAL_WIDTH = 250;
const SIDEBAR_MAX_WIDTH = 450;
@ -191,11 +193,16 @@ export function Sidebar() {
handleSidebarItemClick(buildGameDetailsPath(game))
}
>
<img
className={styles.gameIcon}
src={game.iconUrl}
alt={game.title}
/>
{game.iconUrl ? (
<img
className={styles.gameIcon}
src={game.iconUrl}
alt={game.title}
/>
) : (
<SteamLogo className={styles.gameIcon} />
)}
<span className={styles.menuItemButtonLabel}>
{getGameTitle(game)}
</span>

View File

@ -105,7 +105,7 @@ export function Downloads() {
if (GameStatusHelper.isReady(game?.status)) {
return (
<>
<p>{game?.repack.title}</p>
<p>{game?.repack?.title}</p>
<p>{t("completed")}</p>
</>
);

View File

@ -95,7 +95,7 @@ export interface Game extends Omit<CatalogueEntry, "cover"> {
folderName: string;
downloadPath: string | null;
repacks: GameRepack[];
repack: GameRepack;
repack: GameRepack | null;
progress: number;
fileVerificationProgress: number;
decompressionProgress: number;
@ -137,3 +137,9 @@ export interface Steam250Game {
title: string;
objectID: string;
}
export interface SteamGame {
id: number;
name: string;
clientIcon: string | null;
}