mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-21 18:13:55 +00:00
Compare commits
37 Commits
v3.1.0
...
feature/sh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f000ab2b2 | ||
|
|
d6bd0ec221 | ||
|
|
a9f8d1b42c | ||
|
|
83e662f633 | ||
|
|
c7b924bf2f | ||
|
|
e0d69ccf9d | ||
|
|
aa4e71076d | ||
|
|
eccff27739 | ||
|
|
601b3b0a00 | ||
|
|
1ceea5d5a3 | ||
|
|
9c99724e7d | ||
|
|
55e0f42702 | ||
|
|
b355930eaf | ||
|
|
57b47951a1 | ||
|
|
4780640ed0 | ||
|
|
8b92c8fdd9 | ||
|
|
acd98d0aad | ||
|
|
27239f848e | ||
|
|
c4d0a8eb94 | ||
|
|
60b12b2435 | ||
|
|
1c9515516f | ||
|
|
58a89372ab | ||
|
|
90841bf5e4 | ||
|
|
5564644378 | ||
|
|
89bfb517fb | ||
|
|
e1a1136e05 | ||
|
|
4c6f87f6e7 | ||
|
|
3613ad156b | ||
|
|
e50cb74d1d | ||
|
|
36800c6368 | ||
|
|
f67395c94c | ||
|
|
f8b9fe80fd | ||
|
|
e211517e24 | ||
|
|
538d3e5982 | ||
|
|
60e0b39f86 | ||
|
|
789bccf77a | ||
|
|
ce3ed6f17c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@ out
|
|||||||
ludusavi/
|
ludusavi/
|
||||||
hydra-python-rpc/
|
hydra-python-rpc/
|
||||||
aria2/
|
aria2/
|
||||||
|
.python-version
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
3.9.20
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
[](https://github.com/hydralauncher/hydra/releases)
|
[](https://github.com/hydralauncher/hydra/releases)
|
||||||
|
|
||||||
[](README.pt-BR.md)
|
[](README.pt-BR.md)
|
||||||
[](README.md)
|
[](../README.md)
|
||||||
[](README.ru.md)
|
[](README.ru.md)
|
||||||
[](README.uk-UA.md)
|
[](README.uk-UA.md)
|
||||||
[](README.be.md)
|
[](README.be.md)
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
[](README.nb.md)
|
[](README.nb.md)
|
||||||
[](README.et.md)
|
[](README.et.md)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
[](https://github.com/hydralauncher/hydra/releases)
|
[](https://github.com/hydralauncher/hydra/releases)
|
||||||
|
|
||||||
[](README.pt-BR.md)
|
[](README.pt-BR.md)
|
||||||
[](README.md)
|
[](../README.md)
|
||||||
[](README.ru.md)
|
[](README.ru.md)
|
||||||
[](README.uk-UA.md)
|
[](README.uk-UA.md)
|
||||||
[](README.be.md)
|
[](README.be.md)
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
[](README.nb.md)
|
[](README.nb.md)
|
||||||
[](README.et.md)
|
[](README.et.md)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
[](https://github.com/hydralauncher/hydra/releases)
|
[](https://github.com/hydralauncher/hydra/releases)
|
||||||
|
|
||||||
[](README.pt-BR.md)
|
[](README.pt-BR.md)
|
||||||
[](README.md)
|
[](../README.md)
|
||||||
[](README.ru.md)
|
[](README.ru.md)
|
||||||
[](README.uk-UA.md)
|
[](README.uk-UA.md)
|
||||||
[](README.be.md)
|
[](README.be.md)
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
[](README.da.md)
|
[](README.da.md)
|
||||||
[](README.et.md)
|
[](README.et.md)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
[](https://github.com/hydralauncher/hydra/actions)
|
[](https://github.com/hydralauncher/hydra/actions)
|
||||||
[](https://github.com/hydralauncher/hydra/releases)
|
[](https://github.com/hydralauncher/hydra/releases)
|
||||||
|
|
||||||
[](README.md)
|
[](../README.md)
|
||||||
[](README.be.md)
|
[](README.be.md)
|
||||||
[](README.pl.md)
|
[](README.pl.md)
|
||||||
[](README.pt-BR.md)
|
[](README.pt-BR.md)
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
[](README.nb.md)
|
[](README.nb.md)
|
||||||
[](README.et.md)
|
[](README.et.md)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
[](https://github.com/hydralauncher/hydra/releases)
|
[](https://github.com/hydralauncher/hydra/releases)
|
||||||
|
|
||||||
[](README.pt-BR.md)
|
[](README.pt-BR.md)
|
||||||
[](README.md)
|
[](../README.md)
|
||||||
[](README.ru.md)
|
[](README.ru.md)
|
||||||
[](README.uk-UA.md)
|
[](README.uk-UA.md)
|
||||||
[](README.be.md)
|
[](README.be.md)
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
[](README.nb.md)
|
[](README.nb.md)
|
||||||
[](README.et.md)
|
[](README.et.md)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -11,21 +11,21 @@
|
|||||||
[](https://github.com/hydralauncher/hydra/actions)
|
[](https://github.com/hydralauncher/hydra/actions)
|
||||||
[](https://github.com/hydralauncher/hydra/releases)
|
[](https://github.com/hydralauncher/hydra/releases)
|
||||||
|
|
||||||
[](./README.pt-BR.md)
|
[](README.pt-BR.md)
|
||||||
[](./README.md)
|
[](../README.md)
|
||||||
[](./README.ru.md)
|
[](README.ru.md)
|
||||||
[](./README.uk-UA.md)
|
[](README.uk-UA.md)
|
||||||
[](./README.be.md)
|
[](README.be.md)
|
||||||
[](./README.es.md)
|
[](README.es.md)
|
||||||
[](./README.fr.md)
|
[](README.fr.md)
|
||||||
[](./README.de.md)
|
[](README.de.md)
|
||||||
[](./README.it.md)
|
[](README.it.md)
|
||||||
[](./README.cs.md)
|
[](README.cs.md)
|
||||||
[](./README.da.md)
|
[](README.da.md)
|
||||||
[](./README.nb.md)
|
[](README.nb.md)
|
||||||
[](./README.et.md)
|
[](README.et.md)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
[](https://github.com/hydralauncher/hydra/releases)
|
[](https://github.com/hydralauncher/hydra/releases)
|
||||||
|
|
||||||
[](README.pt-BR.md)
|
[](README.pt-BR.md)
|
||||||
[](README.md)
|
[](../README.md)
|
||||||
[](README.ru.md)
|
[](README.ru.md)
|
||||||
[](README.uk-UA.md)
|
[](README.uk-UA.md)
|
||||||
[](README.be.md)
|
[](README.be.md)
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
[](README.nb.md)
|
[](README.nb.md)
|
||||||
[](README.et.md)
|
[](README.et.md)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
[](https://github.com/hydralauncher/hydra/releases)
|
[](https://github.com/hydralauncher/hydra/releases)
|
||||||
|
|
||||||
[](README.pt-BR.md)
|
[](README.pt-BR.md)
|
||||||
[](README.md)
|
[](../README.md)
|
||||||
[](README.ru.md)
|
[](README.ru.md)
|
||||||
[](README.uk-UA.md)
|
[](README.uk-UA.md)
|
||||||
[](README.be.md)
|
[](README.be.md)
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
[](README.nb.md)
|
[](README.nb.md)
|
||||||
[](README.et.md)
|
[](README.et.md)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||||
|
|
||||||
<h1 align="center">Hydra Launcher</h1>
|
<h1 align="center">Hydra Launcher</h1>
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
[](https://github.com/hydralauncher/hydra/releases)
|
[](https://github.com/hydralauncher/hydra/releases)
|
||||||
|
|
||||||
[](README.pt-BR.md)
|
[](README.pt-BR.md)
|
||||||
[](README.md)
|
[](../README.md)
|
||||||
[](README.ru.md)
|
[](README.ru.md)
|
||||||
[](README.uk-UA.md)
|
[](README.uk-UA.md)
|
||||||
[](README.be.md)
|
[](README.be.md)
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
[](README.nb.md)
|
[](README.nb.md)
|
||||||
[](README.et.md)
|
[](README.et.md)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydralauncher",
|
"name": "hydralauncher",
|
||||||
"version": "3.1.0",
|
"version": "3.1.2",
|
||||||
"description": "Hydra",
|
"description": "Hydra",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "Los Broxas",
|
"author": "Los Broxas",
|
||||||
|
|||||||
@@ -27,18 +27,27 @@ if start_download_payload:
|
|||||||
if initial_download['url'].startswith('magnet'):
|
if initial_download['url'].startswith('magnet'):
|
||||||
torrent_downloader = TorrentDownloader(torrent_session)
|
torrent_downloader = TorrentDownloader(torrent_session)
|
||||||
downloads[initial_download['game_id']] = torrent_downloader
|
downloads[initial_download['game_id']] = torrent_downloader
|
||||||
torrent_downloader.start_download(initial_download['url'], initial_download['save_path'], "")
|
try:
|
||||||
|
torrent_downloader.start_download(initial_download['url'], initial_download['save_path'], "")
|
||||||
|
except Exception as e:
|
||||||
|
print("Error starting torrent download", e)
|
||||||
else:
|
else:
|
||||||
http_downloader = HttpDownloader()
|
http_downloader = HttpDownloader()
|
||||||
downloads[initial_download['game_id']] = http_downloader
|
downloads[initial_download['game_id']] = http_downloader
|
||||||
http_downloader.start_download(initial_download['url'], initial_download['save_path'], initial_download.get('header'))
|
try:
|
||||||
|
http_downloader.start_download(initial_download['url'], initial_download['save_path'], initial_download.get('header'))
|
||||||
|
except Exception as e:
|
||||||
|
print("Error starting http download", e)
|
||||||
|
|
||||||
if start_seeding_payload:
|
if start_seeding_payload:
|
||||||
initial_seeding = json.loads(urllib.parse.unquote(start_seeding_payload))
|
initial_seeding = json.loads(urllib.parse.unquote(start_seeding_payload))
|
||||||
for seed in initial_seeding:
|
for seed in initial_seeding:
|
||||||
torrent_downloader = TorrentDownloader(torrent_session)
|
torrent_downloader = TorrentDownloader(torrent_session, lt.torrent_flags.upload_mode)
|
||||||
downloads[seed['game_id']] = torrent_downloader
|
downloads[seed['game_id']] = torrent_downloader
|
||||||
torrent_downloader.start_download(seed['url'], seed['save_path'], "")
|
try:
|
||||||
|
torrent_downloader.start_download(seed['url'], seed['save_path'], "")
|
||||||
|
except Exception as e:
|
||||||
|
print("Error starting seeding", e)
|
||||||
|
|
||||||
def validate_rpc_password():
|
def validate_rpc_password():
|
||||||
"""Middleware to validate RPC password."""
|
"""Middleware to validate RPC password."""
|
||||||
@@ -156,7 +165,7 @@ def action():
|
|||||||
if downloader:
|
if downloader:
|
||||||
downloader.cancel_download()
|
downloader.cancel_download()
|
||||||
elif action == 'resume_seeding':
|
elif action == 'resume_seeding':
|
||||||
torrent_downloader = TorrentDownloader(torrent_session)
|
torrent_downloader = TorrentDownloader(torrent_session, lt.torrent_flags.upload_mode)
|
||||||
downloads[game_id] = torrent_downloader
|
downloads[game_id] = torrent_downloader
|
||||||
torrent_downloader.start_download(data['url'], data['save_path'], "")
|
torrent_downloader.start_download(data['url'], data['save_path'], "")
|
||||||
elif action == 'pause_seeding':
|
elif action == 'pause_seeding':
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import libtorrent as lt
|
import libtorrent as lt
|
||||||
|
|
||||||
class TorrentDownloader:
|
class TorrentDownloader:
|
||||||
def __init__(self, torrent_session):
|
def __init__(self, torrent_session, flags = lt.torrent_flags.auto_managed):
|
||||||
self.torrent_handle = None
|
self.torrent_handle = None
|
||||||
self.session = torrent_session
|
self.session = torrent_session
|
||||||
|
self.flags = flags
|
||||||
self.trackers = [
|
self.trackers = [
|
||||||
"udp://tracker.opentrackr.org:1337/announce",
|
"udp://tracker.opentrackr.org:1337/announce",
|
||||||
"http://tracker.opentrackr.org:1337/announce",
|
"http://tracker.opentrackr.org:1337/announce",
|
||||||
@@ -102,9 +103,8 @@ class TorrentDownloader:
|
|||||||
]
|
]
|
||||||
|
|
||||||
def start_download(self, magnet: str, save_path: str, header: str):
|
def start_download(self, magnet: str, save_path: str, header: str):
|
||||||
params = {'url': magnet, 'save_path': save_path, 'trackers': self.trackers}
|
params = {'url': magnet, 'save_path': save_path, 'trackers': self.trackers, 'flags': self.flags}
|
||||||
self.torrent_handle = self.session.add_torrent(params)
|
self.torrent_handle = self.session.add_torrent(params)
|
||||||
self.torrent_handle.set_flags(lt.torrent_flags.auto_managed)
|
|
||||||
self.torrent_handle.resume()
|
self.torrent_handle.resume()
|
||||||
|
|
||||||
def pause_download(self):
|
def pause_download(self):
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ fs.readdir(dist, async (err, files) => {
|
|||||||
Bucket: process.env.S3_BUILDS_BUCKET_NAME,
|
Bucket: process.env.S3_BUILDS_BUCKET_NAME,
|
||||||
Key: fileName,
|
Key: fileName,
|
||||||
Body: fs.createReadStream(path.resolve(dist, file)),
|
Body: fs.createReadStream(path.resolve(dist, file)),
|
||||||
|
// 3 days
|
||||||
|
Expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 3),
|
||||||
});
|
});
|
||||||
|
|
||||||
await s3.send(command);
|
await s3.send(command);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
"developers": "Desarrolladores",
|
"developers": "Desarrolladores",
|
||||||
"genres": "Géneros",
|
"genres": "Géneros",
|
||||||
"tags": "Marcadores",
|
"tags": "Marcadores",
|
||||||
"publishers": "Distribuidoras",
|
"publishers": "Editores",
|
||||||
"download_sources": "Fuentes de descarga",
|
"download_sources": "Fuentes de descarga",
|
||||||
"result_count": "{{resultCount}} resultados",
|
"result_count": "{{resultCount}} resultados",
|
||||||
"filter_count": "{{filterCount}} disponibles",
|
"filter_count": "{{filterCount}} disponibles",
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
"backup_from": "Copia de seguridad de {{date}}",
|
"backup_from": "Copia de seguridad de {{date}}",
|
||||||
"custom_backup_location_set": "Se configuró la carpeta de copia de seguridad",
|
"custom_backup_location_set": "Se configuró la carpeta de copia de seguridad",
|
||||||
"clear": "Limpiar",
|
"clear": "Limpiar",
|
||||||
"no_directory_selected": "No se seleccionó un directório"
|
"no_directory_selected": "No se seleccionó un directorio"
|
||||||
},
|
},
|
||||||
"activation": {
|
"activation": {
|
||||||
"title": "Activar Hydra",
|
"title": "Activar Hydra",
|
||||||
@@ -208,7 +208,11 @@
|
|||||||
"queued": "En cola",
|
"queued": "En cola",
|
||||||
"no_downloads_title": "Esto está tan... vacío",
|
"no_downloads_title": "Esto está tan... vacío",
|
||||||
"no_downloads_description": "No has descargado nada con Hydra... aún, ¡pero nunca es tarde para comenzar!.",
|
"no_downloads_description": "No has descargado nada con Hydra... aún, ¡pero nunca es tarde para comenzar!.",
|
||||||
"checking_files": "Verificando archivos…"
|
"checking_files": "Verificando archivos…",
|
||||||
|
"seeding": "Seeding",
|
||||||
|
"stop_seeding": "Detener seeding",
|
||||||
|
"resume_seeding": "Continuar seeding",
|
||||||
|
"options": "Gestionar"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"downloads_path": "Ruta de descarga",
|
"downloads_path": "Ruta de descarga",
|
||||||
@@ -265,7 +269,9 @@
|
|||||||
"user_unblocked": "El usuario ha sido desbloqueado",
|
"user_unblocked": "El usuario ha sido desbloqueado",
|
||||||
"enable_achievement_notifications": "Cuando un logro se desbloquea",
|
"enable_achievement_notifications": "Cuando un logro se desbloquea",
|
||||||
"launch_minimized": "Iniciar Hydra minimizado",
|
"launch_minimized": "Iniciar Hydra minimizado",
|
||||||
"disable_nsfw_alert": "Desactivar alerta NSFW"
|
"disable_nsfw_alert": "Desactivar alerta NSFW",
|
||||||
|
"seed_after_download_complete": "Realizar seeding después de que se completa la descarga",
|
||||||
|
"show_hidden_achievement_description": "Ocultar descripción de logros ocultos antes de desbloquearlos"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"download_complete": "Descarga completada",
|
"download_complete": "Descarga completada",
|
||||||
@@ -366,7 +372,16 @@
|
|||||||
"upload_banner": "Subir un banner",
|
"upload_banner": "Subir un banner",
|
||||||
"uploading_banner": "Subiendo banner…",
|
"uploading_banner": "Subiendo banner…",
|
||||||
"background_image_updated": "Imagen de fondo actualizada",
|
"background_image_updated": "Imagen de fondo actualizada",
|
||||||
"playing": "Jugando {{game}}"
|
"playing": "Jugando {{game}}",
|
||||||
|
"achievements": "logros",
|
||||||
|
"achievements_unlocked": "Logros desbloqueados",
|
||||||
|
"earned_points": "Puntos Obtenidos",
|
||||||
|
"show_achievements_on_profile": "Mostrar tus logros en tu perfil",
|
||||||
|
"show_points_on_profile": "Mostrar tus puntos obtenidos en tu perfil",
|
||||||
|
"games": "Juegos",
|
||||||
|
"ranking_updated_weekly": "El Ranking se actualiza semanalmente",
|
||||||
|
"stats": "Estadísticas",
|
||||||
|
"top_percentile": "Top {{percentile}}%"
|
||||||
},
|
},
|
||||||
"achievement": {
|
"achievement": {
|
||||||
"achievement_unlocked": "Logro desbloqueado",
|
"achievement_unlocked": "Logro desbloqueado",
|
||||||
@@ -376,7 +391,12 @@
|
|||||||
"subscription_needed": "Se necesita una suscripción a Hydra Cloud necesita para ver este contenido",
|
"subscription_needed": "Se necesita una suscripción a Hydra Cloud necesita para ver este contenido",
|
||||||
"new_achievements_unlocked": "Desbloqueados {{achievementCount}} nuevos logros de {{gameCount}} juegos",
|
"new_achievements_unlocked": "Desbloqueados {{achievementCount}} nuevos logros de {{gameCount}} juegos",
|
||||||
"achievement_progress": "{{unlockedCount}}/{{totalCount}} logros",
|
"achievement_progress": "{{unlockedCount}}/{{totalCount}} logros",
|
||||||
"achievements_unlocked_for_game": "Se han desbloqueado {{achievementCount}} nuevos logros de {{gameTitle}}"
|
"achievements_unlocked_for_game": "Se han desbloqueado {{achievementCount}} nuevos logros de {{gameTitle}}",
|
||||||
|
"hidden_achievement_tooltip": "Este es un logro oculto",
|
||||||
|
"achievement_earn_points": "Obtén {{points}} puntos con este logro",
|
||||||
|
"earned_points": "Puntos obtenidos:",
|
||||||
|
"available_points": "Puntos disponibles:",
|
||||||
|
"how_to_earn_achievements_points": "¿Cómo obtener puntos de logros?"
|
||||||
},
|
},
|
||||||
"hydra_cloud": {
|
"hydra_cloud": {
|
||||||
"subscription_tour_title": "Suscripción Hydra Cloud",
|
"subscription_tour_title": "Suscripción Hydra Cloud",
|
||||||
@@ -386,6 +406,9 @@
|
|||||||
"animated_profile_picture": "Fotos de perfil animadas",
|
"animated_profile_picture": "Fotos de perfil animadas",
|
||||||
"premium_support": "Soporte Premium",
|
"premium_support": "Soporte Premium",
|
||||||
"show_and_compare_achievements": "Muestra y compara tus logros con otros usuarios",
|
"show_and_compare_achievements": "Muestra y compara tus logros con otros usuarios",
|
||||||
"animated_profile_banner": "Fondo de perfil animado"
|
"animated_profile_banner": "Fondo de perfil animado",
|
||||||
|
"hydra_cloud": "Hydra Cloud",
|
||||||
|
"hydra_cloud_feature_found": "¡Has descubierto una característica de Hydra Cloud!",
|
||||||
|
"learn_more": "Aprender más"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { registerEvent } from "../register-event";
|
import { registerEvent } from "../register-event";
|
||||||
import { gameRepository } from "../../repository";
|
import { gameRepository } from "../../repository";
|
||||||
import { DownloadManager } from "@main/services";
|
import { DownloadManager } from "@main/services";
|
||||||
|
import { Downloader } from "@shared";
|
||||||
|
|
||||||
const resumeGameSeed = async (
|
const resumeGameSeed = async (
|
||||||
_event: Electron.IpcMainInvokeEvent,
|
_event: Electron.IpcMainInvokeEvent,
|
||||||
@@ -10,7 +11,7 @@ const resumeGameSeed = async (
|
|||||||
where: {
|
where: {
|
||||||
id: gameId,
|
id: gameId,
|
||||||
isDeleted: false,
|
isDeleted: false,
|
||||||
downloader: 1,
|
downloader: Downloader.Torrent,
|
||||||
progress: 1,
|
progress: 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import { RealDebridClient } from "./services/download/real-debrid";
|
|||||||
import { HydraApi } from "./services/hydra-api";
|
import { HydraApi } from "./services/hydra-api";
|
||||||
import { uploadGamesBatch } from "./services/library-sync";
|
import { uploadGamesBatch } from "./services/library-sync";
|
||||||
import { Aria2 } from "./services/aria2";
|
import { Aria2 } from "./services/aria2";
|
||||||
|
import { Downloader } from "@shared";
|
||||||
|
import { IsNull, Not } from "typeorm";
|
||||||
|
|
||||||
const loadState = async (userPreferences: UserPreferences | null) => {
|
const loadState = async (userPreferences: UserPreferences | null) => {
|
||||||
import("./events");
|
import("./events");
|
||||||
@@ -37,8 +39,9 @@ const loadState = async (userPreferences: UserPreferences | null) => {
|
|||||||
const seedList = await gameRepository.find({
|
const seedList = await gameRepository.find({
|
||||||
where: {
|
where: {
|
||||||
shouldSeed: true,
|
shouldSeed: true,
|
||||||
downloader: 1,
|
downloader: Downloader.Torrent,
|
||||||
progress: 1,
|
progress: 1,
|
||||||
|
uri: Not(IsNull()),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -100,8 +100,6 @@ export class DownloadManager {
|
|||||||
public static async watchDownloads() {
|
public static async watchDownloads() {
|
||||||
const status = await this.getDownloadStatus();
|
const status = await this.getDownloadStatus();
|
||||||
|
|
||||||
// status = await RealDebridDownloader.getStatus();
|
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
const { gameId, progress } = status;
|
const { gameId, progress } = status;
|
||||||
const game = await gameRepository.findOne({
|
const game = await gameRepository.findOne({
|
||||||
|
|||||||
@@ -31,6 +31,6 @@ log.errorHandler.startCatching({
|
|||||||
|
|
||||||
log.initialize();
|
log.initialize();
|
||||||
|
|
||||||
export const pythonInstanceLogger = log.scope("python-instance");
|
export const pythonRpcLogger = log.scope("python-rpc");
|
||||||
export const logger = log.scope("main");
|
export const logger = log.scope("main");
|
||||||
export const achievementsLogger = log.scope("achievements");
|
export const achievementsLogger = log.scope("achievements");
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export const gamesPlaytime = new Map<
|
|||||||
interface ExecutableInfo {
|
interface ExecutableInfo {
|
||||||
name: string;
|
name: string;
|
||||||
os: string;
|
os: string;
|
||||||
|
exe: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GameExecutables {
|
interface GameExecutables {
|
||||||
@@ -30,47 +31,65 @@ interface GameExecutables {
|
|||||||
const TICKS_TO_UPDATE_API = 120;
|
const TICKS_TO_UPDATE_API = 120;
|
||||||
let currentTick = 1;
|
let currentTick = 1;
|
||||||
|
|
||||||
const gameExecutables = (
|
const isWindowsPlatform = process.platform === "win32";
|
||||||
await axios
|
const isLinuxPlatform = process.platform === "linux";
|
||||||
.get(
|
|
||||||
import.meta.env.MAIN_VITE_EXTERNAL_RESOURCES_URL +
|
const getGameExecutables = async () => {
|
||||||
"/game-executables.json"
|
const gameExecutables = (
|
||||||
)
|
await axios
|
||||||
.catch(() => {
|
.get(
|
||||||
return { data: {} };
|
import.meta.env.MAIN_VITE_EXTERNAL_RESOURCES_URL +
|
||||||
})
|
"/game-executables.json"
|
||||||
).data as GameExecutables;
|
)
|
||||||
|
.catch(() => {
|
||||||
|
return { data: {} };
|
||||||
|
})
|
||||||
|
).data as GameExecutables;
|
||||||
|
|
||||||
|
Object.keys(gameExecutables).forEach((key) => {
|
||||||
|
gameExecutables[key] = gameExecutables[key]
|
||||||
|
.filter((executable) => {
|
||||||
|
if (isWindowsPlatform) {
|
||||||
|
return executable.os === "win32";
|
||||||
|
} else if (isLinuxPlatform) {
|
||||||
|
return executable.os === "linux" || executable.os === "win32";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.map((executable) => {
|
||||||
|
return {
|
||||||
|
name: isWindowsPlatform
|
||||||
|
? executable.name.replace(/\//g, "\\")
|
||||||
|
: executable.name,
|
||||||
|
os: executable.os,
|
||||||
|
exe: executable.name.slice(executable.name.lastIndexOf("/") + 1),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return gameExecutables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const gameExecutables = await getGameExecutables();
|
||||||
|
|
||||||
const findGamePathByProcess = (
|
const findGamePathByProcess = (
|
||||||
processMap: Map<string, Set<string>>,
|
processMap: Map<string, Set<string>>,
|
||||||
gameId: string
|
gameId: string
|
||||||
) => {
|
) => {
|
||||||
const executables = gameExecutables[gameId].filter((info) => {
|
const executables = gameExecutables[gameId];
|
||||||
if (process.platform === "linux" && info.os === "linux") return true;
|
|
||||||
return info.os === "win32";
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const executable of executables) {
|
for (const executable of executables) {
|
||||||
const exe = executable.name.slice(executable.name.lastIndexOf("/") + 1);
|
const pathSet = processMap.get(executable.exe);
|
||||||
|
|
||||||
if (!exe) continue;
|
|
||||||
|
|
||||||
const pathSet = processMap.get(exe);
|
|
||||||
|
|
||||||
if (pathSet) {
|
if (pathSet) {
|
||||||
const executableName =
|
|
||||||
process.platform === "win32"
|
|
||||||
? executable.name.replace(/\//g, "\\")
|
|
||||||
: executable.name;
|
|
||||||
|
|
||||||
pathSet.forEach((path) => {
|
pathSet.forEach((path) => {
|
||||||
if (path.toLowerCase().endsWith(executableName)) {
|
if (path.toLowerCase().endsWith(executable.name)) {
|
||||||
gameRepository.update(
|
gameRepository.update(
|
||||||
{ objectID: gameId, shop: "steam" },
|
{ objectID: gameId, shop: "steam" },
|
||||||
{ executablePath: path }
|
{ executablePath: path }
|
||||||
);
|
);
|
||||||
|
|
||||||
if (process.platform === "linux") {
|
if (isLinuxPlatform) {
|
||||||
exec(commands.findWineDir, (err, out) => {
|
exec(commands.findWineDir, (err, out) => {
|
||||||
if (err) return;
|
if (err) return;
|
||||||
|
|
||||||
@@ -105,7 +124,7 @@ const getSystemProcessMap = async () => {
|
|||||||
map.set(key, currentSet.add(value));
|
map.set(key, currentSet.add(value));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process.platform === "linux") {
|
if (isLinuxPlatform) {
|
||||||
await new Promise((res) => {
|
await new Promise((res) => {
|
||||||
exec(commands.findWineExecutables, (err, out) => {
|
exec(commands.findWineExecutables, (err, out) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -152,7 +171,6 @@ export const watchProcesses = async () => {
|
|||||||
|
|
||||||
for (const game of games) {
|
for (const game of games) {
|
||||||
const executablePath = game.executablePath;
|
const executablePath = game.executablePath;
|
||||||
|
|
||||||
if (!executablePath) {
|
if (!executablePath) {
|
||||||
if (gameExecutables[game.objectID]) {
|
if (gameExecutables[game.objectID]) {
|
||||||
findGamePathByProcess(processMap, game.objectID);
|
findGamePathByProcess(processMap, game.objectID);
|
||||||
@@ -161,10 +179,7 @@ export const watchProcesses = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const executable = executablePath
|
const executable = executablePath
|
||||||
.slice(
|
.slice(executablePath.lastIndexOf(isWindowsPlatform ? "\\" : "/") + 1)
|
||||||
executablePath.lastIndexOf(process.platform === "win32" ? "\\" : "/") +
|
|
||||||
1
|
|
||||||
)
|
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
|
|
||||||
const hasProcess = processMap.get(executable)?.has(executablePath);
|
const hasProcess = processMap.get(executable)?.has(executablePath);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import fs from "node:fs";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import crypto from "node:crypto";
|
import crypto from "node:crypto";
|
||||||
|
|
||||||
import { logger } from "./logger";
|
import { pythonRpcLogger } from "./logger";
|
||||||
import { Readable } from "node:stream";
|
import { Readable } from "node:stream";
|
||||||
import { app, dialog } from "electron";
|
import { app, dialog } from "electron";
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ export class PythonRPC {
|
|||||||
if (!readable) return;
|
if (!readable) return;
|
||||||
|
|
||||||
readable.setEncoding("utf-8");
|
readable.setEncoding("utf-8");
|
||||||
readable.on("data", logger.log);
|
readable.on("data", pythonRpcLogger.log);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static spawn(
|
public static spawn(
|
||||||
@@ -100,7 +100,7 @@ export class PythonRPC {
|
|||||||
|
|
||||||
public static kill() {
|
public static kill() {
|
||||||
if (this.pythonProcess) {
|
if (this.pythonProcess) {
|
||||||
logger.log("Killing python process");
|
pythonRpcLogger.log("Killing python process");
|
||||||
this.pythonProcess.kill();
|
this.pythonProcess.kill();
|
||||||
this.pythonProcess = null;
|
this.pythonProcess = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { Pagination } from "./pagination";
|
|||||||
import { useCatalogue } from "@renderer/hooks/use-catalogue";
|
import { useCatalogue } from "@renderer/hooks/use-catalogue";
|
||||||
import { GameItem } from "./game-item";
|
import { GameItem } from "./game-item";
|
||||||
import { FilterItem } from "./filter-item";
|
import { FilterItem } from "./filter-item";
|
||||||
|
import { debounce } from "lodash-es";
|
||||||
|
|
||||||
const filterCategoryColors = {
|
const filterCategoryColors = {
|
||||||
genres: "hsl(262deg 50% 47%)",
|
genres: "hsl(262deg 50% 47%)",
|
||||||
@@ -58,26 +59,36 @@ export default function Catalogue() {
|
|||||||
|
|
||||||
const { getRepacksForObjectId } = useRepacks();
|
const { getRepacksForObjectId } = useRepacks();
|
||||||
|
|
||||||
|
const debouncedSearch = useRef(
|
||||||
|
debounce(async (filters, pageSize, offset) => {
|
||||||
|
const abortController = new AbortController();
|
||||||
|
abortControllerRef.current = abortController;
|
||||||
|
|
||||||
|
const response = await window.electron.searchGames(
|
||||||
|
filters,
|
||||||
|
pageSize,
|
||||||
|
offset
|
||||||
|
);
|
||||||
|
|
||||||
|
if (abortController.signal.aborted) return;
|
||||||
|
|
||||||
|
setResults(response.edges);
|
||||||
|
setItemsCount(response.count);
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 500)
|
||||||
|
).current;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setResults([]);
|
setResults([]);
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
abortControllerRef.current?.abort();
|
abortControllerRef.current?.abort();
|
||||||
|
|
||||||
const abortController = new AbortController();
|
debouncedSearch(filters, PAGE_SIZE, (page - 1) * PAGE_SIZE);
|
||||||
abortControllerRef.current = abortController;
|
|
||||||
|
|
||||||
window.electron
|
return () => {
|
||||||
.searchGames(filters, PAGE_SIZE, (page - 1) * PAGE_SIZE)
|
debouncedSearch.cancel();
|
||||||
.then((response) => {
|
};
|
||||||
if (abortController.signal.aborted) {
|
}, [filters, page, debouncedSearch]);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setResults(response.edges);
|
|
||||||
setItemsCount(response.count);
|
|
||||||
setIsLoading(false);
|
|
||||||
});
|
|
||||||
}, [filters, page, dispatch]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
downloadSourcesTable.toArray().then((sources) => {
|
downloadSourcesTable.toArray().then((sources) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user